File: | root/firefox-clang/docshell/base/nsDocShell.cpp |
Warning: | line 3438, column 9 Value stored to 'error' is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
2 | /* vim: set ts=8 sts=2 et sw=2 tw=80: */ |
3 | /* This Source Code Form is subject to the terms of the Mozilla Public |
4 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
5 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
6 | |
7 | #include "nsDocShell.h" |
8 | |
9 | #include <algorithm> |
10 | #include "mozilla/dom/HTMLFormElement.h" |
11 | |
12 | #ifdef XP_WIN |
13 | # include <process.h> |
14 | # define getpid _getpid |
15 | #else |
16 | # include <unistd.h> // for getpid() |
17 | #endif |
18 | |
19 | #include "mozilla/ArrayUtils.h" |
20 | #include "mozilla/Attributes.h" |
21 | #include "mozilla/AutoRestore.h" |
22 | #include "mozilla/BasePrincipal.h" |
23 | #include "mozilla/Casting.h" |
24 | #include "mozilla/CheckedInt.h" |
25 | #include "mozilla/Components.h" |
26 | #include "mozilla/DebugOnly.h" |
27 | #include "mozilla/Encoding.h" |
28 | #include "mozilla/EventStateManager.h" |
29 | #include "mozilla/HTMLEditor.h" |
30 | #include "mozilla/InputTaskManager.h" |
31 | #include "mozilla/LoadInfo.h" |
32 | #include "mozilla/Logging.h" |
33 | #include "mozilla/MediaFeatureChange.h" |
34 | #include "mozilla/Preferences.h" |
35 | #include "mozilla/PresShell.h" |
36 | #include "mozilla/ResultExtensions.h" |
37 | #include "mozilla/SchedulerGroup.h" |
38 | #include "mozilla/ScopeExit.h" |
39 | #include "mozilla/ScrollContainerFrame.h" |
40 | #include "mozilla/ScrollTypes.h" |
41 | #include "mozilla/SimpleEnumerator.h" |
42 | #include "mozilla/StaticPrefs_browser.h" |
43 | #include "mozilla/StaticPrefs_docshell.h" |
44 | #include "mozilla/StaticPrefs_dom.h" |
45 | #include "mozilla/StaticPrefs_extensions.h" |
46 | #include "mozilla/StaticPrefs_privacy.h" |
47 | #include "mozilla/StaticPrefs_security.h" |
48 | #include "mozilla/StaticPrefs_ui.h" |
49 | #include "mozilla/StaticPrefs_fission.h" |
50 | #include "mozilla/StartupTimeline.h" |
51 | #include "mozilla/StorageAccess.h" |
52 | #include "mozilla/StoragePrincipalHelper.h" |
53 | #include "mozilla/Telemetry.h" |
54 | |
55 | #include "mozilla/Unused.h" |
56 | #include "mozilla/WidgetUtils.h" |
57 | |
58 | #include "mozilla/dom/AutoEntryScript.h" |
59 | #include "mozilla/dom/ChildProcessChannelListener.h" |
60 | #include "mozilla/dom/ClientChannelHelper.h" |
61 | #include "mozilla/dom/ClientHandle.h" |
62 | #include "mozilla/dom/ClientInfo.h" |
63 | #include "mozilla/dom/ClientManager.h" |
64 | #include "mozilla/dom/ClientSource.h" |
65 | #include "mozilla/dom/ContentChild.h" |
66 | #include "mozilla/dom/ContentFrameMessageManager.h" |
67 | #include "mozilla/dom/DocGroup.h" |
68 | #include "mozilla/dom/Element.h" |
69 | #include "mozilla/dom/FragmentDirective.h" |
70 | #include "mozilla/dom/HTMLAnchorElement.h" |
71 | #include "mozilla/dom/HTMLIFrameElement.h" |
72 | #include "mozilla/dom/Navigation.h" |
73 | #include "mozilla/dom/NavigationBinding.h" |
74 | #include "mozilla/dom/NavigationHistoryEntry.h" |
75 | #include "mozilla/dom/PerformanceNavigation.h" |
76 | #include "mozilla/dom/PermissionMessageUtils.h" |
77 | #include "mozilla/dom/PopupBlocker.h" |
78 | #include "mozilla/dom/ScreenOrientation.h" |
79 | #include "mozilla/dom/ScriptSettings.h" |
80 | #include "mozilla/dom/ServiceWorkerInterceptController.h" |
81 | #include "mozilla/dom/ServiceWorkerUtils.h" |
82 | #include "mozilla/dom/SessionHistoryEntry.h" |
83 | #include "mozilla/dom/SessionStorageManager.h" |
84 | #include "mozilla/dom/SessionStoreChangeListener.h" |
85 | #include "mozilla/dom/SessionStoreChild.h" |
86 | #include "mozilla/dom/SessionStoreUtils.h" |
87 | #include "mozilla/dom/BrowserChild.h" |
88 | #include "mozilla/dom/ToJSValue.h" |
89 | #include "mozilla/dom/UserActivation.h" |
90 | #include "mozilla/dom/ChildSHistory.h" |
91 | #include "mozilla/dom/nsCSPContext.h" |
92 | #include "mozilla/dom/nsHTTPSOnlyUtils.h" |
93 | #include "mozilla/dom/LoadURIOptionsBinding.h" |
94 | #include "mozilla/dom/JSWindowActorChild.h" |
95 | #include "mozilla/dom/DocumentBinding.h" |
96 | #include "mozilla/glean/DocshellMetrics.h" |
97 | #include "mozilla/ipc/ProtocolUtils.h" |
98 | #include "mozilla/net/DocumentChannel.h" |
99 | #include "mozilla/net/DocumentChannelChild.h" |
100 | #include "mozilla/net/ParentChannelWrapper.h" |
101 | #include "mozilla/net/UrlClassifierFeatureFactory.h" |
102 | #include "ReferrerInfo.h" |
103 | |
104 | #include "nsIAuthPrompt.h" |
105 | #include "nsIAuthPrompt2.h" |
106 | #include "nsICachingChannel.h" |
107 | #include "nsICaptivePortalService.h" |
108 | #include "nsIChannel.h" |
109 | #include "nsIChannelEventSink.h" |
110 | #include "nsIClassifiedChannel.h" |
111 | #include "nsIClassOfService.h" |
112 | #include "nsIConsoleReportCollector.h" |
113 | #include "nsIContent.h" |
114 | #include "nsIContentInlines.h" |
115 | #include "nsIContentSecurityPolicy.h" |
116 | #include "nsIController.h" |
117 | #include "nsIDocShellTreeItem.h" |
118 | #include "nsIDocShellTreeOwner.h" |
119 | #include "nsIDocumentViewer.h" |
120 | #include "mozilla/dom/Document.h" |
121 | #include "nsHTMLDocument.h" |
122 | #include "nsIDocumentLoaderFactory.h" |
123 | #include "nsIDOMWindow.h" |
124 | #include "nsIEditingSession.h" |
125 | #include "nsIEffectiveTLDService.h" |
126 | #include "nsIExternalProtocolService.h" |
127 | #include "nsIFormPOSTActionChannel.h" |
128 | #include "nsIFrame.h" |
129 | #include "nsIGlobalObject.h" |
130 | #include "nsIHttpChannel.h" |
131 | #include "nsIHttpChannelInternal.h" |
132 | #include "nsIIDNService.h" |
133 | #include "nsIInputStreamChannel.h" |
134 | #include "nsIInterfaceRequestorUtils.h" |
135 | #include "nsILayoutHistoryState.h" |
136 | #include "nsILoadInfo.h" |
137 | #include "nsILoadURIDelegate.h" |
138 | #include "nsIMultiPartChannel.h" |
139 | #include "nsINestedURI.h" |
140 | #include "nsINetworkPredictor.h" |
141 | #include "nsINode.h" |
142 | #include "nsINSSErrorsService.h" |
143 | #include "nsIObserverService.h" |
144 | #include "nsIOService.h" |
145 | #include "nsIPrincipal.h" |
146 | #include "nsIPrivacyTransitionObserver.h" |
147 | #include "nsIPrompt.h" |
148 | #include "nsIPromptCollection.h" |
149 | #include "nsIPromptFactory.h" |
150 | #include "nsIPublicKeyPinningService.h" |
151 | #include "nsIReflowObserver.h" |
152 | #include "nsIScriptChannel.h" |
153 | #include "nsIScriptObjectPrincipal.h" |
154 | #include "nsIScriptSecurityManager.h" |
155 | #include "nsScriptSecurityManager.h" |
156 | #include "nsIScrollObserver.h" |
157 | #include "nsISupportsPrimitives.h" |
158 | #include "nsISecureBrowserUI.h" |
159 | #include "nsISeekableStream.h" |
160 | #include "nsISelectionDisplay.h" |
161 | #include "nsISHEntry.h" |
162 | #include "nsISiteSecurityService.h" |
163 | #include "nsISocketProvider.h" |
164 | #include "nsIStringBundle.h" |
165 | #include "nsIStructuredCloneContainer.h" |
166 | #include "nsIBrowserChild.h" |
167 | #include "nsITextToSubURI.h" |
168 | #include "nsITimedChannel.h" |
169 | #include "nsITimer.h" |
170 | #include "nsITransportSecurityInfo.h" |
171 | #include "nsIUploadChannel.h" |
172 | #include "nsIURIFixup.h" |
173 | #include "nsIURIMutator.h" |
174 | #include "nsIURILoader.h" |
175 | #include "nsIViewSourceChannel.h" |
176 | #include "nsIWebBrowserChrome.h" |
177 | #include "nsIWebBrowserFind.h" |
178 | #include "nsIWebProgress.h" |
179 | #include "nsIWidget.h" |
180 | #include "nsIWindowWatcher.h" |
181 | #include "nsIWritablePropertyBag2.h" |
182 | #include "nsIX509Cert.h" |
183 | #include "nsIXULRuntime.h" |
184 | |
185 | #include "nsCommandManager.h" |
186 | #include "nsPIDOMWindow.h" |
187 | #include "nsPIWindowRoot.h" |
188 | |
189 | #include "IHistory.h" |
190 | #include "IUrlClassifierUITelemetry.h" |
191 | |
192 | #include "nsArray.h" |
193 | #include "nsArrayUtils.h" |
194 | #include "nsBrowserStatusFilter.h" |
195 | #include "nsCExternalHandlerService.h" |
196 | #include "nsContentDLF.h" |
197 | #include "nsContentPolicyUtils.h" // NS_CheckContentLoadPolicy(...) |
198 | #include "nsContentSecurityManager.h" |
199 | #include "nsContentSecurityUtils.h" |
200 | #include "nsContentUtils.h" |
201 | #include "nsCURILoader.h" |
202 | #include "nsDocShellCID.h" |
203 | #include "nsDocShellEditorData.h" |
204 | #include "nsDocShellEnumerator.h" |
205 | #include "nsDocShellLoadState.h" |
206 | #include "nsDocShellLoadTypes.h" |
207 | #include "nsDOMCID.h" |
208 | #include "nsDOMNavigationTiming.h" |
209 | #include "nsDSURIContentListener.h" |
210 | #include "nsEditingSession.h" |
211 | #include "nsError.h" |
212 | #include "nsEscape.h" |
213 | #include "nsFocusManager.h" |
214 | #include "nsGlobalWindowInner.h" |
215 | #include "nsGlobalWindowOuter.h" |
216 | #include "nsJSEnvironment.h" |
217 | #include "nsNetCID.h" |
218 | #include "nsNetUtil.h" |
219 | #include "nsObjectLoadingContent.h" |
220 | #include "nsPingListener.h" |
221 | #include "nsPoint.h" |
222 | #include "nsQueryObject.h" |
223 | #include "nsQueryActor.h" |
224 | #include "nsRect.h" |
225 | #include "nsRefreshTimer.h" |
226 | #include "nsSandboxFlags.h" |
227 | #include "nsSHEntry.h" |
228 | #include "nsSHistory.h" |
229 | #include "nsSHEntry.h" |
230 | #include "nsStructuredCloneContainer.h" |
231 | #include "nsSubDocumentFrame.h" |
232 | #include "nsURILoader.h" |
233 | #include "nsURLHelper.h" |
234 | #include "nsView.h" |
235 | #include "nsViewManager.h" |
236 | #include "nsViewSourceHandler.h" |
237 | #include "nsWebBrowserFind.h" |
238 | #include "nsWhitespaceTokenizer.h" |
239 | #include "nsWidgetsCID.h" |
240 | #include "nsXULAppAPI.h" |
241 | |
242 | #include "CertVerifier.h" |
243 | #include "ThirdPartyUtil.h" |
244 | #include "GeckoProfiler.h" |
245 | #include "mozilla/NullPrincipal.h" |
246 | #include "Navigator.h" |
247 | #include "prenv.h" |
248 | #include "mozilla/ipc/URIUtils.h" |
249 | #include "sslerr.h" |
250 | #include "mozpkix/pkix.h" |
251 | #include "NSSErrorsService.h" |
252 | |
253 | #include "nsDocShellTelemetryUtils.h" |
254 | |
255 | #ifdef MOZ_PLACES1 |
256 | # include "mozilla/places/nsFaviconService.h" |
257 | # include "mozIPlacesPendingOperation.h" |
258 | #endif |
259 | |
260 | #if NS_PRINT_PREVIEW1 |
261 | # include "nsIDocumentViewerPrint.h" |
262 | # include "nsIWebBrowserPrint.h" |
263 | #endif |
264 | |
265 | using namespace mozilla; |
266 | using namespace mozilla::dom; |
267 | using namespace mozilla::net; |
268 | |
269 | using mozilla::ipc::Endpoint; |
270 | |
271 | // Threshold value in ms for META refresh based redirects |
272 | #define REFRESH_REDIRECT_TIMER15000 15000 |
273 | |
274 | static mozilla::LazyLogModule gCharsetMenuLog("CharsetMenu"); |
275 | |
276 | #define LOGCHARSETMENU(args)do { const ::mozilla::LogModule* moz_real_module = gCharsetMenuLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print (moz_real_module, mozilla::LogLevel::Debug, MOZ_LOG_EXPAND_ARGS args); } } while (0) \ |
277 | MOZ_LOG(gCharsetMenuLog, mozilla::LogLevel::Debug, args)do { const ::mozilla::LogModule* moz_real_module = gCharsetMenuLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print (moz_real_module, mozilla::LogLevel::Debug, MOZ_LOG_EXPAND_ARGS args); } } while (0) |
278 | |
279 | #ifdef DEBUG1 |
280 | unsigned long nsDocShell::gNumberOfDocShells = 0; |
281 | static uint64_t gDocshellIDCounter = 0; |
282 | |
283 | static mozilla::LazyLogModule gDocShellLog("nsDocShell"); |
284 | static mozilla::LazyLogModule gDocShellAndDOMWindowLeakLogging( |
285 | "DocShellAndDOMWindowLeak"); |
286 | #endif |
287 | static mozilla::LazyLogModule gDocShellLeakLog("nsDocShellLeak"); |
288 | extern mozilla::LazyLogModule gPageCacheLog; |
289 | extern mozilla::LazyLogModule gNavigationLog; |
290 | mozilla::LazyLogModule gSHLog("SessionHistory"); |
291 | extern mozilla::LazyLogModule gSHIPBFCacheLog; |
292 | |
293 | const char kAppstringsBundleURL[] = |
294 | "chrome://global/locale/appstrings.properties"; |
295 | |
296 | static bool IsTopLevelDoc(BrowsingContext* aBrowsingContext, |
297 | nsILoadInfo* aLoadInfo) { |
298 | MOZ_ASSERT(aBrowsingContext)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aBrowsingContext)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aBrowsingContext))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aBrowsingContext" , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 298); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "aBrowsingContext" ")"); do { MOZ_CrashSequence (__null, 298); __attribute__((nomerge)) ::abort(); } while (false ); } } while (false); |
299 | MOZ_ASSERT(aLoadInfo)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aLoadInfo)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aLoadInfo))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aLoadInfo", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 299); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadInfo" ")" ); do { MOZ_CrashSequence(__null, 299); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
300 | |
301 | if (aLoadInfo->GetExternalContentPolicyType() != |
302 | ExtContentPolicy::TYPE_DOCUMENT) { |
303 | return false; |
304 | } |
305 | |
306 | return aBrowsingContext->IsTopContent(); |
307 | } |
308 | |
309 | // True if loading for top level document loading in active tab. |
310 | static bool IsUrgentStart(BrowsingContext* aBrowsingContext, |
311 | nsILoadInfo* aLoadInfo, uint32_t aLoadType) { |
312 | MOZ_ASSERT(aBrowsingContext)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aBrowsingContext)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aBrowsingContext))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aBrowsingContext" , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 312); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "aBrowsingContext" ")"); do { MOZ_CrashSequence (__null, 312); __attribute__((nomerge)) ::abort(); } while (false ); } } while (false); |
313 | MOZ_ASSERT(aLoadInfo)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aLoadInfo)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aLoadInfo))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aLoadInfo", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 313); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadInfo" ")" ); do { MOZ_CrashSequence(__null, 313); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
314 | |
315 | if (!IsTopLevelDoc(aBrowsingContext, aLoadInfo)) { |
316 | return false; |
317 | } |
318 | |
319 | if (aLoadType & |
320 | (nsIDocShell::LOAD_CMD_NORMAL | nsIDocShell::LOAD_CMD_HISTORY)) { |
321 | return true; |
322 | } |
323 | |
324 | return aBrowsingContext->IsActive(); |
325 | } |
326 | |
327 | nsDocShell::nsDocShell(BrowsingContext* aBrowsingContext, |
328 | uint64_t aContentWindowID) |
329 | : nsDocLoader(true), |
330 | mContentWindowID(aContentWindowID), |
331 | mBrowsingContext(aBrowsingContext), |
332 | mParentCharset(nullptr), |
333 | mTreeOwner(nullptr), |
334 | mScrollbarPref(ScrollbarPreference::Auto), |
335 | mCharsetReloadState(eCharsetReloadInit), |
336 | mParentCharsetSource(0), |
337 | mFrameMargins(-1, -1), |
338 | mItemType(aBrowsingContext->IsContent() ? typeContent : typeChrome), |
339 | mPreviousEntryIndex(-1), |
340 | mLoadedEntryIndex(-1), |
341 | mBusyFlags(BUSY_FLAGS_NONE), |
342 | mAppType(nsIDocShell::APP_TYPE_UNKNOWN), |
343 | mLoadType(0), |
344 | mFailedLoadType(0), |
345 | mChannelToDisconnectOnPageHide(0), |
346 | mCreatingDocument(false), |
347 | #ifdef DEBUG1 |
348 | mInEnsureScriptEnv(false), |
349 | #endif |
350 | mInitialized(false), |
351 | mAllowSubframes(true), |
352 | mAllowMetaRedirects(true), |
353 | mAllowImages(true), |
354 | mAllowMedia(true), |
355 | mAllowDNSPrefetch(true), |
356 | mAllowWindowControl(true), |
357 | mCSSErrorReportingEnabled(false), |
358 | mAllowAuth(mItemType == typeContent), |
359 | mAllowKeywordFixup(false), |
360 | mDisableMetaRefreshWhenInactive(false), |
361 | mWindowDraggingAllowed(false), |
362 | mInFrameSwap(false), |
363 | mFiredUnloadEvent(false), |
364 | mEODForCurrentDocument(false), |
365 | mURIResultedInDocument(false), |
366 | mIsBeingDestroyed(false), |
367 | mIsExecutingOnLoadHandler(false), |
368 | mSavingOldViewer(false), |
369 | mInvisible(false), |
370 | mHasLoadedNonBlankURI(false), |
371 | mBlankTiming(false), |
372 | mTitleValidForCurrentURI(false), |
373 | mWillChangeProcess(false), |
374 | mIsNavigating(false), |
375 | mForcedAutodetection(false), |
376 | mCheckingSessionHistory(false), |
377 | mNeedToReportActiveAfterLoadingBecomesActive(false) { |
378 | // If no outer window ID was provided, generate a new one. |
379 | if (aContentWindowID == 0) { |
380 | mContentWindowID = nsContentUtils::GenerateWindowId(); |
381 | } |
382 | |
383 | MOZ_LOG(gDocShellLeakLog, LogLevel::Debug, ("DOCSHELL %p created\n", this))do { const ::mozilla::LogModule* moz_real_module = gDocShellLeakLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "DOCSHELL %p created\n", this); } } while ( 0); |
384 | |
385 | #ifdef DEBUG1 |
386 | mDocShellID = gDocshellIDCounter++; |
387 | // We're counting the number of |nsDocShells| to help find leaks |
388 | ++gNumberOfDocShells; |
389 | MOZ_LOG(gDocShellAndDOMWindowLeakLogging, LogLevel::Info,do { const ::mozilla::LogModule* moz_real_module = gDocShellAndDOMWindowLeakLogging ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Info, "++DOCSHELL %p == %ld [pid = %d] [id = %" "l" "u" "]\n", (void*)this, gNumberOfDocShells, getpid(), mDocShellID ); } } while (0) |
390 | ("++DOCSHELL %p == %ld [pid = %d] [id = %" PRIu64 "]\n", (void*)this,do { const ::mozilla::LogModule* moz_real_module = gDocShellAndDOMWindowLeakLogging ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Info, "++DOCSHELL %p == %ld [pid = %d] [id = %" "l" "u" "]\n", (void*)this, gNumberOfDocShells, getpid(), mDocShellID ); } } while (0) |
391 | gNumberOfDocShells, getpid(), mDocShellID))do { const ::mozilla::LogModule* moz_real_module = gDocShellAndDOMWindowLeakLogging ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Info, "++DOCSHELL %p == %ld [pid = %d] [id = %" "l" "u" "]\n", (void*)this, gNumberOfDocShells, getpid(), mDocShellID ); } } while (0); |
392 | #endif |
393 | } |
394 | |
395 | nsDocShell::~nsDocShell() { |
396 | // Avoid notifying observers while we're in the dtor. |
397 | mIsBeingDestroyed = true; |
398 | |
399 | Destroy(); |
400 | |
401 | if (mDocumentViewer) { |
402 | mDocumentViewer->Close(nullptr); |
403 | mDocumentViewer->Destroy(); |
404 | mDocumentViewer = nullptr; |
405 | } |
406 | |
407 | MOZ_LOG(gDocShellLeakLog, LogLevel::Debug, ("DOCSHELL %p destroyed\n", this))do { const ::mozilla::LogModule* moz_real_module = gDocShellLeakLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "DOCSHELL %p destroyed\n", this); } } while (0); |
408 | |
409 | #ifdef DEBUG1 |
410 | if (MOZ_LOG_TEST(gDocShellAndDOMWindowLeakLogging, LogLevel::Info)(__builtin_expect(!!(mozilla::detail::log_test(gDocShellAndDOMWindowLeakLogging , LogLevel::Info)), 0))) { |
411 | nsAutoCString url; |
412 | if (mLastOpenedURI) { |
413 | url = mLastOpenedURI->GetSpecOrDefault(); |
414 | |
415 | // Data URLs can be very long, so truncate to avoid flooding the log. |
416 | const uint32_t maxURLLength = 1000; |
417 | if (url.Length() > maxURLLength) { |
418 | url.Truncate(maxURLLength); |
419 | } |
420 | } |
421 | |
422 | // We're counting the number of |nsDocShells| to help find leaks |
423 | --gNumberOfDocShells; |
424 | MOZ_LOG(do { const ::mozilla::LogModule* moz_real_module = gDocShellAndDOMWindowLeakLogging ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Info, "--DOCSHELL %p == %ld [pid = %d] [id = %" "l" "u" "] [url = %s]\n", (void*)this, gNumberOfDocShells, getpid (), mDocShellID, url.get()); } } while (0) |
425 | gDocShellAndDOMWindowLeakLogging, LogLevel::Info,do { const ::mozilla::LogModule* moz_real_module = gDocShellAndDOMWindowLeakLogging ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Info, "--DOCSHELL %p == %ld [pid = %d] [id = %" "l" "u" "] [url = %s]\n", (void*)this, gNumberOfDocShells, getpid (), mDocShellID, url.get()); } } while (0) |
426 | ("--DOCSHELL %p == %ld [pid = %d] [id = %" PRIu64 "] [url = %s]\n",do { const ::mozilla::LogModule* moz_real_module = gDocShellAndDOMWindowLeakLogging ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Info, "--DOCSHELL %p == %ld [pid = %d] [id = %" "l" "u" "] [url = %s]\n", (void*)this, gNumberOfDocShells, getpid (), mDocShellID, url.get()); } } while (0) |
427 | (void*)this, gNumberOfDocShells, getpid(), mDocShellID, url.get()))do { const ::mozilla::LogModule* moz_real_module = gDocShellAndDOMWindowLeakLogging ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Info, "--DOCSHELL %p == %ld [pid = %d] [id = %" "l" "u" "] [url = %s]\n", (void*)this, gNumberOfDocShells, getpid (), mDocShellID, url.get()); } } while (0); |
428 | } |
429 | #endif |
430 | } |
431 | |
432 | bool nsDocShell::Initialize() { |
433 | if (mInitialized) { |
434 | // We've already been initialized. |
435 | return true; |
436 | } |
437 | |
438 | NS_ASSERTION(mItemType == typeContent || mItemType == typeChrome,do { if (!(mItemType == typeContent || mItemType == typeChrome )) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Unexpected item type in docshell" , "mItemType == typeContent || mItemType == typeChrome", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 439); MOZ_PretendNoReturn(); } } while (0) |
439 | "Unexpected item type in docshell")do { if (!(mItemType == typeContent || mItemType == typeChrome )) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Unexpected item type in docshell" , "mItemType == typeContent || mItemType == typeChrome", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 439); MOZ_PretendNoReturn(); } } while (0); |
440 | |
441 | NS_ENSURE_TRUE(Preferences::GetRootBranch(), false)do { if ((__builtin_expect(!!(!(Preferences::GetRootBranch()) ), 0))) { NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "Preferences::GetRootBranch()" ") failed", nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 441); return false; } } while (false); |
442 | mInitialized = true; |
443 | |
444 | mDisableMetaRefreshWhenInactive = |
445 | Preferences::GetBool("browser.meta_refresh_when_inactive.disabled", |
446 | mDisableMetaRefreshWhenInactive); |
447 | |
448 | if (nsCOMPtr<nsIObserverService> serv = services::GetObserverService()) { |
449 | const char* msg = mItemType == typeContent ? NS_WEBNAVIGATION_CREATE"webnavigation-create" |
450 | : NS_CHROME_WEBNAVIGATION_CREATE"chrome-webnavigation-create"; |
451 | serv->NotifyWhenScriptSafe(GetAsSupports(this), msg, nullptr); |
452 | } |
453 | |
454 | return true; |
455 | } |
456 | |
457 | /* static */ |
458 | already_AddRefed<nsDocShell> nsDocShell::Create( |
459 | BrowsingContext* aBrowsingContext, uint64_t aContentWindowID) { |
460 | MOZ_ASSERT(aBrowsingContext, "DocShell without a BrowsingContext!")do { static_assert( mozilla::detail::AssertionConditionType< decltype(aBrowsingContext)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aBrowsingContext))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aBrowsingContext" " (" "DocShell without a BrowsingContext!" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 460); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aBrowsingContext" ") (" "DocShell without a BrowsingContext!" ")"); do { MOZ_CrashSequence (__null, 460); __attribute__((nomerge)) ::abort(); } while (false ); } } while (false); |
461 | |
462 | nsresult rv; |
463 | RefPtr<nsDocShell> ds = new nsDocShell(aBrowsingContext, aContentWindowID); |
464 | |
465 | // Initialize the underlying nsDocLoader. |
466 | rv = ds->nsDocLoader::InitWithBrowsingContext(aBrowsingContext); |
467 | if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv )), 0))), "NS_FAILED(rv)", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 467)) { |
468 | return nullptr; |
469 | } |
470 | |
471 | // Create our ContentListener |
472 | ds->mContentListener = new nsDSURIContentListener(ds); |
473 | |
474 | // We enable if we're in the parent process in order to support non-e10s |
475 | // configurations. |
476 | // Note: This check is duplicated in SharedWorkerInterfaceRequestor's |
477 | // constructor. |
478 | if (XRE_IsParentProcess()) { |
479 | ds->mInterceptController = new ServiceWorkerInterceptController(); |
480 | } |
481 | |
482 | // We want to hold a strong ref to the loadgroup, so it better hold a weak |
483 | // ref to us... use an InterfaceRequestorProxy to do this. |
484 | nsCOMPtr<nsIInterfaceRequestor> proxy = new InterfaceRequestorProxy(ds); |
485 | ds->mLoadGroup->SetNotificationCallbacks(proxy); |
486 | |
487 | // XXX(nika): We have our BrowsingContext, so we might be able to skip this. |
488 | // It could be nice to directly set up our DocLoader tree? |
489 | rv = nsDocLoader::AddDocLoaderAsChildOfRoot(ds); |
490 | if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv )), 0))), "NS_FAILED(rv)", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 490)) { |
491 | return nullptr; |
492 | } |
493 | |
494 | uint32_t notifyMask = |
495 | nsIWebProgress::NOTIFY_STATE_ALL | nsIWebProgress::NOTIFY_LOCATION | |
496 | nsIWebProgress::NOTIFY_SECURITY | nsIWebProgress::NOTIFY_STATUS; |
497 | |
498 | // NOTE: Only listen for NOTIFY_PROGRESS on toplevel BrowsingContexts, as |
499 | // listeners in the browser UI only cares about total progress on the toplevel |
500 | // context. Aggregation of the total progress is currently handled within |
501 | // `nsDocLoader`, and does not take out-of-process iframes into account. |
502 | if (aBrowsingContext->IsTop()) { |
503 | notifyMask |= nsIWebProgress::NOTIFY_PROGRESS; |
504 | } |
505 | |
506 | // Add |ds| as a progress listener to itself. A little weird, but simpler |
507 | // than reproducing all the listener-notification logic in overrides of the |
508 | // various methods via which nsDocLoader can be notified. Note that this |
509 | // holds an nsWeakPtr to |ds|, so it's ok. |
510 | rv = ds->AddProgressListener(ds, notifyMask); |
511 | if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv )), 0))), "NS_FAILED(rv)", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 511)) { |
512 | return nullptr; |
513 | } |
514 | |
515 | // If our BrowsingContext has private browsing enabled, update the number of |
516 | // private browsing docshells. |
517 | if (aBrowsingContext->UsePrivateBrowsing()) { |
518 | ds->NotifyPrivateBrowsingChanged(); |
519 | } |
520 | |
521 | // If our parent window is present in this process, set up our parent now. |
522 | RefPtr<WindowContext> parentWC = aBrowsingContext->GetParentWindowContext(); |
523 | if (parentWC && parentWC->IsInProcess()) { |
524 | // If we don't have a parent element anymore, we can't finish this load! |
525 | // How'd we get here? |
526 | RefPtr<Element> parentElement = aBrowsingContext->GetEmbedderElement(); |
527 | if (!parentElement) { |
528 | MOZ_ASSERT_UNREACHABLE("nsDocShell::Create() - !parentElement")do { static_assert( mozilla::detail::AssertionConditionType< decltype(false)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: " "nsDocShell::Create() - !parentElement" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 528); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: " "nsDocShell::Create() - !parentElement" ")"); do { MOZ_CrashSequence(__null, 528); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
529 | return nullptr; |
530 | } |
531 | |
532 | // We have an in-process parent window, but don't have a parent nsDocShell? |
533 | // How'd we get here! |
534 | nsCOMPtr<nsIDocShell> parentShell = |
535 | parentElement->OwnerDoc()->GetDocShell(); |
536 | if (!parentShell) { |
537 | MOZ_ASSERT_UNREACHABLE("nsDocShell::Create() - !parentShell")do { static_assert( mozilla::detail::AssertionConditionType< decltype(false)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: " "nsDocShell::Create() - !parentShell" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 537); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: " "nsDocShell::Create() - !parentShell" ")"); do { MOZ_CrashSequence(__null, 537); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
538 | return nullptr; |
539 | } |
540 | parentShell->AddChild(ds); |
541 | } |
542 | |
543 | // Make |ds| the primary DocShell for the given context. |
544 | aBrowsingContext->SetDocShell(ds); |
545 | |
546 | // Set |ds| default load flags on load group. |
547 | ds->SetLoadGroupDefaultLoadFlags(aBrowsingContext->GetDefaultLoadFlags()); |
548 | |
549 | return ds.forget(); |
550 | } |
551 | |
552 | void nsDocShell::DestroyChildren() { |
553 | for (auto* child : mChildList.ForwardRange()) { |
554 | nsCOMPtr<nsIDocShellTreeItem> shell = do_QueryObject(child); |
555 | NS_ASSERTION(shell, "docshell has null child")do { if (!(shell)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "docshell has null child" , "shell", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 555); MOZ_PretendNoReturn(); } } while (0); |
556 | |
557 | if (shell) { |
558 | shell->SetTreeOwner(nullptr); |
559 | } |
560 | } |
561 | |
562 | nsDocLoader::DestroyChildren(); |
563 | } |
564 | |
565 | NS_IMPL_CYCLE_COLLECTION_WEAK_PTR_INHERITED(nsDocShell, nsDocLoader,nsDocShell::cycleCollection nsDocShell::_cycleCollectorGlobal ; void nsDocShell::cycleCollection::Unlink(void* p) { nsDocShell * tmp = DowncastCCParticipant<nsDocShell>(p); nsISupports * s = static_cast<nsISupports*>(p); nsDocLoader::cycleCollection ::Unlink(s); ImplCycleCollectionUnlink(tmp->mScriptGlobal) ; ImplCycleCollectionUnlink(tmp->mInitialClientSource); ImplCycleCollectionUnlink (tmp->mBrowsingContext); ImplCycleCollectionUnlink(tmp-> mChromeEventHandler); ImplCycleCollectionUnlink(tmp->mBCWebProgressStatusFilter ); tmp->DetachWeakPtr(); (void)tmp; } nsresult nsDocShell:: cycleCollection::TraverseNative( void* p, nsCycleCollectionTraversalCallback & cb) { nsDocShell* tmp = DowncastCCParticipant<nsDocShell >(p); nsISupports* s = static_cast<nsISupports*>(p); if (nsDocLoader::cycleCollection::TraverseNative(s, cb) == NS_SUCCESS_INTERRUPTED_TRAVERSE ) { return NS_SUCCESS_INTERRUPTED_TRAVERSE; } ImplCycleCollectionTraverse (cb, tmp->mScriptGlobal, "mScriptGlobal", 0); ImplCycleCollectionTraverse (cb, tmp->mInitialClientSource, "mInitialClientSource", 0) ; ImplCycleCollectionTraverse(cb, tmp->mBrowsingContext, "mBrowsingContext" , 0); ImplCycleCollectionTraverse(cb, tmp->mChromeEventHandler , "mChromeEventHandler", 0); ImplCycleCollectionTraverse(cb, tmp ->mBCWebProgressStatusFilter, "mBCWebProgressStatusFilter" , 0); (void)tmp; return NS_OK; } |
566 | mScriptGlobal, mInitialClientSource,nsDocShell::cycleCollection nsDocShell::_cycleCollectorGlobal ; void nsDocShell::cycleCollection::Unlink(void* p) { nsDocShell * tmp = DowncastCCParticipant<nsDocShell>(p); nsISupports * s = static_cast<nsISupports*>(p); nsDocLoader::cycleCollection ::Unlink(s); ImplCycleCollectionUnlink(tmp->mScriptGlobal) ; ImplCycleCollectionUnlink(tmp->mInitialClientSource); ImplCycleCollectionUnlink (tmp->mBrowsingContext); ImplCycleCollectionUnlink(tmp-> mChromeEventHandler); ImplCycleCollectionUnlink(tmp->mBCWebProgressStatusFilter ); tmp->DetachWeakPtr(); (void)tmp; } nsresult nsDocShell:: cycleCollection::TraverseNative( void* p, nsCycleCollectionTraversalCallback & cb) { nsDocShell* tmp = DowncastCCParticipant<nsDocShell >(p); nsISupports* s = static_cast<nsISupports*>(p); if (nsDocLoader::cycleCollection::TraverseNative(s, cb) == NS_SUCCESS_INTERRUPTED_TRAVERSE ) { return NS_SUCCESS_INTERRUPTED_TRAVERSE; } ImplCycleCollectionTraverse (cb, tmp->mScriptGlobal, "mScriptGlobal", 0); ImplCycleCollectionTraverse (cb, tmp->mInitialClientSource, "mInitialClientSource", 0) ; ImplCycleCollectionTraverse(cb, tmp->mBrowsingContext, "mBrowsingContext" , 0); ImplCycleCollectionTraverse(cb, tmp->mChromeEventHandler , "mChromeEventHandler", 0); ImplCycleCollectionTraverse(cb, tmp ->mBCWebProgressStatusFilter, "mBCWebProgressStatusFilter" , 0); (void)tmp; return NS_OK; } |
567 | mBrowsingContext,nsDocShell::cycleCollection nsDocShell::_cycleCollectorGlobal ; void nsDocShell::cycleCollection::Unlink(void* p) { nsDocShell * tmp = DowncastCCParticipant<nsDocShell>(p); nsISupports * s = static_cast<nsISupports*>(p); nsDocLoader::cycleCollection ::Unlink(s); ImplCycleCollectionUnlink(tmp->mScriptGlobal) ; ImplCycleCollectionUnlink(tmp->mInitialClientSource); ImplCycleCollectionUnlink (tmp->mBrowsingContext); ImplCycleCollectionUnlink(tmp-> mChromeEventHandler); ImplCycleCollectionUnlink(tmp->mBCWebProgressStatusFilter ); tmp->DetachWeakPtr(); (void)tmp; } nsresult nsDocShell:: cycleCollection::TraverseNative( void* p, nsCycleCollectionTraversalCallback & cb) { nsDocShell* tmp = DowncastCCParticipant<nsDocShell >(p); nsISupports* s = static_cast<nsISupports*>(p); if (nsDocLoader::cycleCollection::TraverseNative(s, cb) == NS_SUCCESS_INTERRUPTED_TRAVERSE ) { return NS_SUCCESS_INTERRUPTED_TRAVERSE; } ImplCycleCollectionTraverse (cb, tmp->mScriptGlobal, "mScriptGlobal", 0); ImplCycleCollectionTraverse (cb, tmp->mInitialClientSource, "mInitialClientSource", 0) ; ImplCycleCollectionTraverse(cb, tmp->mBrowsingContext, "mBrowsingContext" , 0); ImplCycleCollectionTraverse(cb, tmp->mChromeEventHandler , "mChromeEventHandler", 0); ImplCycleCollectionTraverse(cb, tmp ->mBCWebProgressStatusFilter, "mBCWebProgressStatusFilter" , 0); (void)tmp; return NS_OK; } |
568 | mChromeEventHandler,nsDocShell::cycleCollection nsDocShell::_cycleCollectorGlobal ; void nsDocShell::cycleCollection::Unlink(void* p) { nsDocShell * tmp = DowncastCCParticipant<nsDocShell>(p); nsISupports * s = static_cast<nsISupports*>(p); nsDocLoader::cycleCollection ::Unlink(s); ImplCycleCollectionUnlink(tmp->mScriptGlobal) ; ImplCycleCollectionUnlink(tmp->mInitialClientSource); ImplCycleCollectionUnlink (tmp->mBrowsingContext); ImplCycleCollectionUnlink(tmp-> mChromeEventHandler); ImplCycleCollectionUnlink(tmp->mBCWebProgressStatusFilter ); tmp->DetachWeakPtr(); (void)tmp; } nsresult nsDocShell:: cycleCollection::TraverseNative( void* p, nsCycleCollectionTraversalCallback & cb) { nsDocShell* tmp = DowncastCCParticipant<nsDocShell >(p); nsISupports* s = static_cast<nsISupports*>(p); if (nsDocLoader::cycleCollection::TraverseNative(s, cb) == NS_SUCCESS_INTERRUPTED_TRAVERSE ) { return NS_SUCCESS_INTERRUPTED_TRAVERSE; } ImplCycleCollectionTraverse (cb, tmp->mScriptGlobal, "mScriptGlobal", 0); ImplCycleCollectionTraverse (cb, tmp->mInitialClientSource, "mInitialClientSource", 0) ; ImplCycleCollectionTraverse(cb, tmp->mBrowsingContext, "mBrowsingContext" , 0); ImplCycleCollectionTraverse(cb, tmp->mChromeEventHandler , "mChromeEventHandler", 0); ImplCycleCollectionTraverse(cb, tmp ->mBCWebProgressStatusFilter, "mBCWebProgressStatusFilter" , 0); (void)tmp; return NS_OK; } |
569 | mBCWebProgressStatusFilter)nsDocShell::cycleCollection nsDocShell::_cycleCollectorGlobal ; void nsDocShell::cycleCollection::Unlink(void* p) { nsDocShell * tmp = DowncastCCParticipant<nsDocShell>(p); nsISupports * s = static_cast<nsISupports*>(p); nsDocLoader::cycleCollection ::Unlink(s); ImplCycleCollectionUnlink(tmp->mScriptGlobal) ; ImplCycleCollectionUnlink(tmp->mInitialClientSource); ImplCycleCollectionUnlink (tmp->mBrowsingContext); ImplCycleCollectionUnlink(tmp-> mChromeEventHandler); ImplCycleCollectionUnlink(tmp->mBCWebProgressStatusFilter ); tmp->DetachWeakPtr(); (void)tmp; } nsresult nsDocShell:: cycleCollection::TraverseNative( void* p, nsCycleCollectionTraversalCallback & cb) { nsDocShell* tmp = DowncastCCParticipant<nsDocShell >(p); nsISupports* s = static_cast<nsISupports*>(p); if (nsDocLoader::cycleCollection::TraverseNative(s, cb) == NS_SUCCESS_INTERRUPTED_TRAVERSE ) { return NS_SUCCESS_INTERRUPTED_TRAVERSE; } ImplCycleCollectionTraverse (cb, tmp->mScriptGlobal, "mScriptGlobal", 0); ImplCycleCollectionTraverse (cb, tmp->mInitialClientSource, "mInitialClientSource", 0) ; ImplCycleCollectionTraverse(cb, tmp->mBrowsingContext, "mBrowsingContext" , 0); ImplCycleCollectionTraverse(cb, tmp->mChromeEventHandler , "mChromeEventHandler", 0); ImplCycleCollectionTraverse(cb, tmp ->mBCWebProgressStatusFilter, "mBCWebProgressStatusFilter" , 0); (void)tmp; return NS_OK; } |
570 | |
571 | NS_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; } |
572 | NS_IMPL_RELEASE_INHERITED(nsDocShell, nsDocLoader)MozExternalRefCountType nsDocShell::Release(void) { nsrefcnt r = nsDocLoader::Release(); if constexpr (::mozilla::detail::ShouldLogInheritedRefcnt <nsDocShell>) { NS_LogRelease((this), (r), ("nsDocShell" )); } return r; } |
573 | |
574 | NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsDocShell)nsresult nsDocShell::QueryInterface(const nsIID& aIID, void ** aInstancePtr) { do { if (!(aInstancePtr)) { NS_DebugBreak( NS_DEBUG_ASSERTION, "QueryInterface requires a non-NULL destination!" , "aInstancePtr", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 574); MOZ_PretendNoReturn(); } } while (0); nsISupports* foundInterface ; if (TopThreeWordsEquals( aIID, (nsXPCOMCycleCollectionParticipant ::kIID), (nsCycleCollectionISupports::kIID)) && (LowWordEquals (aIID, (nsXPCOMCycleCollectionParticipant::kIID)) || LowWordEquals (aIID, (nsCycleCollectionISupports::kIID)))) { if (LowWordEquals (aIID, (nsXPCOMCycleCollectionParticipant::kIID))) { *aInstancePtr = nsDocShell::cycleCollection::GetParticipant(); return NS_OK ; } if (LowWordEquals(aIID, (nsCycleCollectionISupports::kIID ))) { *aInstancePtr = nsDocShell::cycleCollection::Upcast(this ); return NS_OK; } foundInterface = nullptr; } else |
575 | NS_INTERFACE_MAP_ENTRY(nsIDocShell)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t <decltype(*this)>, nsIDocShell>)) foundInterface = static_cast <nsIDocShell*>(this); else |
576 | NS_INTERFACE_MAP_ENTRY(nsIDocShellTreeItem)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t <decltype(*this)>, nsIDocShellTreeItem>)) foundInterface = static_cast<nsIDocShellTreeItem*>(this); else |
577 | NS_INTERFACE_MAP_ENTRY(nsIWebNavigation)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t <decltype(*this)>, nsIWebNavigation>)) foundInterface = static_cast<nsIWebNavigation*>(this); else |
578 | NS_INTERFACE_MAP_ENTRY(nsIBaseWindow)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t <decltype(*this)>, nsIBaseWindow>)) foundInterface = static_cast<nsIBaseWindow*>(this); else |
579 | NS_INTERFACE_MAP_ENTRY(nsIRefreshURI)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t <decltype(*this)>, nsIRefreshURI>)) foundInterface = static_cast<nsIRefreshURI*>(this); else |
580 | NS_INTERFACE_MAP_ENTRY(nsIWebProgressListener)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t <decltype(*this)>, nsIWebProgressListener>)) foundInterface = static_cast<nsIWebProgressListener*>(this); else |
581 | NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t <decltype(*this)>, nsISupportsWeakReference>)) foundInterface = static_cast<nsISupportsWeakReference*>(this); else |
582 | NS_INTERFACE_MAP_ENTRY(nsIWebPageDescriptor)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t <decltype(*this)>, nsIWebPageDescriptor>)) foundInterface = static_cast<nsIWebPageDescriptor*>(this); else |
583 | NS_INTERFACE_MAP_ENTRY(nsIAuthPromptProvider)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t <decltype(*this)>, nsIAuthPromptProvider>)) foundInterface = static_cast<nsIAuthPromptProvider*>(this); else |
584 | NS_INTERFACE_MAP_ENTRY(nsILoadContext)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t <decltype(*this)>, nsILoadContext>)) foundInterface = static_cast<nsILoadContext*>(this); else |
585 | NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsINetworkInterceptController,if ((mInterceptController) && aIID.Equals(mozilla::detail ::kImplementedIID<std::remove_reference_t<decltype(*this )>, nsINetworkInterceptController>)) foundInterface = static_cast <nsINetworkInterceptController*>(this); else |
586 | mInterceptController)if ((mInterceptController) && aIID.Equals(mozilla::detail ::kImplementedIID<std::remove_reference_t<decltype(*this )>, nsINetworkInterceptController>)) foundInterface = static_cast <nsINetworkInterceptController*>(this); else |
587 | NS_INTERFACE_MAP_END_INHERITING(nsDocLoader)foundInterface = 0; nsresult status; if (!foundInterface) status = nsDocLoader::QueryInterface(aIID, (void**)&foundInterface ); else { (foundInterface)->AddRef(); status = NS_OK; } *aInstancePtr = foundInterface; return status; } |
588 | |
589 | NS_IMETHODIMPnsresult |
590 | nsDocShell::GetInterface(const nsIID& aIID, void** aSink) { |
591 | MOZ_ASSERT(aSink, "null out param")do { static_assert( mozilla::detail::AssertionConditionType< decltype(aSink)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(aSink))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("aSink" " (" "null out param" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 591 ); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aSink" ") (" "null out param" ")"); do { MOZ_CrashSequence(__null, 591); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
592 | |
593 | *aSink = nullptr; |
594 | |
595 | if (aIID.Equals(NS_GET_IID(nsICommandManager)(nsICommandManager::kIID))) { |
596 | NS_ENSURE_SUCCESS(EnsureCommandHandler(), NS_ERROR_FAILURE)do { nsresult __rv = EnsureCommandHandler(); if (((bool)(__builtin_expect (!!(NS_FAILED_impl(__rv)), 0)))) { const char* name = mozilla ::GetStaticErrorName(__rv); mozilla::SmprintfPointer msg = mozilla ::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "EnsureCommandHandler()", "NS_ERROR_FAILURE", static_cast <uint32_t>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 596); return NS_ERROR_FAILURE; } } while (false); |
597 | *aSink = static_cast<nsICommandManager*>(mCommandManager.get()); |
598 | } else if (aIID.Equals(NS_GET_IID(nsIURIContentListener)(nsIURIContentListener::kIID))) { |
599 | *aSink = mContentListener; |
600 | } else if ((aIID.Equals(NS_GET_IID(nsIScriptGlobalObject)(nsIScriptGlobalObject::kIID)) || |
601 | aIID.Equals(NS_GET_IID(nsIGlobalObject)(nsIGlobalObject::kIID)) || |
602 | aIID.Equals(NS_GET_IID(nsPIDOMWindowOuter)(nsPIDOMWindowOuter::kIID)) || |
603 | aIID.Equals(NS_GET_IID(mozIDOMWindowProxy)(mozIDOMWindowProxy::kIID)) || |
604 | aIID.Equals(NS_GET_IID(nsIDOMWindow)(nsIDOMWindow::kIID))) && |
605 | NS_SUCCEEDED(EnsureScriptEnvironment())((bool)(__builtin_expect(!!(!NS_FAILED_impl(EnsureScriptEnvironment ())), 1)))) { |
606 | return mScriptGlobal->QueryInterface(aIID, aSink); |
607 | } else if (aIID.Equals(NS_GET_IID(Document)(Document::kIID)) && |
608 | NS_SUCCEEDED(EnsureDocumentViewer())((bool)(__builtin_expect(!!(!NS_FAILED_impl(EnsureDocumentViewer ())), 1)))) { |
609 | RefPtr<Document> doc = mDocumentViewer->GetDocument(); |
610 | doc.forget(aSink); |
611 | return *aSink ? NS_OK : NS_NOINTERFACE; |
612 | } else if (aIID.Equals(NS_GET_IID(nsIPrompt)(nsIPrompt::kIID)) && |
613 | NS_SUCCEEDED(EnsureScriptEnvironment())((bool)(__builtin_expect(!!(!NS_FAILED_impl(EnsureScriptEnvironment ())), 1)))) { |
614 | nsresult rv; |
615 | nsCOMPtr<nsIWindowWatcher> wwatch = |
616 | do_GetService(NS_WINDOWWATCHER_CONTRACTID"@mozilla.org/embedcomp/window-watcher;1", &rv); |
617 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 617); return rv; } } while (false); |
618 | |
619 | // Get the an auth prompter for our window so that the parenting |
620 | // of the dialogs works as it should when using tabs. |
621 | nsIPrompt* prompt; |
622 | rv = wwatch->GetNewPrompter(mScriptGlobal, &prompt); |
623 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 623); return rv; } } while (false); |
624 | |
625 | *aSink = prompt; |
626 | return NS_OK; |
627 | } else if (aIID.Equals(NS_GET_IID(nsIAuthPrompt)(nsIAuthPrompt::kIID)) || |
628 | aIID.Equals(NS_GET_IID(nsIAuthPrompt2)(nsIAuthPrompt2::kIID))) { |
629 | return NS_SUCCEEDED(GetAuthPrompt(PROMPT_NORMAL, aIID, aSink))((bool)(__builtin_expect(!!(!NS_FAILED_impl(GetAuthPrompt(PROMPT_NORMAL , aIID, aSink))), 1))) |
630 | ? NS_OK |
631 | : NS_NOINTERFACE; |
632 | } else if (aIID.Equals(NS_GET_IID(nsISHistory)(nsISHistory::kIID))) { |
633 | // This is deprecated, you should instead directly get |
634 | // ChildSHistory from the browsing context. |
635 | MOZ_DIAGNOSTIC_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType< decltype(false)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("false" " (" "Do not try to get a nsISHistory interface from nsIDocShell" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 636 ); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false" ") (" "Do not try to get a nsISHistory interface from nsIDocShell" ")"); do { MOZ_CrashSequence(__null, 636); __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
636 | false, "Do not try to get a nsISHistory interface from nsIDocShell")do { static_assert( mozilla::detail::AssertionConditionType< decltype(false)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("false" " (" "Do not try to get a nsISHistory interface from nsIDocShell" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 636 ); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false" ") (" "Do not try to get a nsISHistory interface from nsIDocShell" ")"); do { MOZ_CrashSequence(__null, 636); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
637 | return NS_NOINTERFACE; |
638 | } else if (aIID.Equals(NS_GET_IID(nsIWebBrowserFind)(nsIWebBrowserFind::kIID))) { |
639 | nsresult rv = EnsureFind(); |
640 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
641 | return rv; |
642 | } |
643 | |
644 | *aSink = mFind; |
645 | NS_ADDREF((nsISupports*)*aSink)((nsISupports*)*aSink)->AddRef(); |
646 | return NS_OK; |
647 | } else if (aIID.Equals(NS_GET_IID(nsISelectionDisplay)(nsISelectionDisplay::kIID))) { |
648 | if (PresShell* presShell = GetPresShell()) { |
649 | return presShell->QueryInterface(aIID, aSink); |
650 | } |
651 | } else if (aIID.Equals(NS_GET_IID(nsIDocShellTreeOwner)(nsIDocShellTreeOwner::kIID))) { |
652 | nsCOMPtr<nsIDocShellTreeOwner> treeOwner; |
653 | nsresult rv = GetTreeOwner(getter_AddRefs(treeOwner)); |
654 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && treeOwner) { |
655 | return treeOwner->QueryInterface(aIID, aSink); |
656 | } |
657 | } else if (aIID.Equals(NS_GET_IID(nsIBrowserChild)(nsIBrowserChild::kIID))) { |
658 | *aSink = GetBrowserChild().take(); |
659 | return *aSink ? NS_OK : NS_ERROR_FAILURE; |
660 | } else { |
661 | return nsDocLoader::GetInterface(aIID, aSink); |
662 | } |
663 | |
664 | NS_IF_ADDREF(((nsISupports*)*aSink))ns_if_addref(((nsISupports*)*aSink)); |
665 | return *aSink ? NS_OK : NS_NOINTERFACE; |
666 | } |
667 | |
668 | NS_IMETHODIMPnsresult |
669 | nsDocShell::SetCancelContentJSEpoch(int32_t aEpoch) { |
670 | // Note: this gets called fairly early (before a pageload actually starts). |
671 | // We could probably defer this even longer. |
672 | nsCOMPtr<nsIBrowserChild> browserChild = GetBrowserChild(); |
673 | static_cast<BrowserChild*>(browserChild.get()) |
674 | ->SetCancelContentJSEpoch(aEpoch); |
675 | return NS_OK; |
676 | } |
677 | |
678 | nsresult nsDocShell::CheckDisallowedJavascriptLoad( |
679 | nsDocShellLoadState* aLoadState) { |
680 | if (!aLoadState->URI()->SchemeIs("javascript")) { |
681 | return NS_OK; |
682 | } |
683 | |
684 | if (nsCOMPtr<nsIPrincipal> targetPrincipal = |
685 | GetInheritedPrincipal(/* aConsiderCurrentDocument */ true)) { |
686 | if (!aLoadState->TriggeringPrincipal()->Subsumes(targetPrincipal)) { |
687 | return NS_ERROR_DOM_BAD_CROSS_ORIGIN_URI; |
688 | } |
689 | return NS_OK; |
690 | } |
691 | return NS_ERROR_DOM_BAD_CROSS_ORIGIN_URI; |
692 | } |
693 | |
694 | NS_IMETHODIMPnsresult |
695 | nsDocShell::LoadURI(nsDocShellLoadState* aLoadState, bool aSetNavigating) { |
696 | return LoadURI(aLoadState, aSetNavigating, false); |
697 | } |
698 | |
699 | nsresult nsDocShell::LoadURI(nsDocShellLoadState* aLoadState, |
700 | bool aSetNavigating, |
701 | bool aContinueHandlingSubframeHistory) { |
702 | MOZ_ASSERT(aLoadState, "Must have a valid load state!")do { static_assert( mozilla::detail::AssertionConditionType< decltype(aLoadState)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aLoadState))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aLoadState" " (" "Must have a valid load state!" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 702 ); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState" ") (" "Must have a valid load state!" ")"); do { MOZ_CrashSequence (__null, 702); __attribute__((nomerge)) ::abort(); } while (false ); } } while (false); |
703 | // NOTE: This comparison between what appears to be internal/external load |
704 | // flags is intentional, as it's ensuring that the caller isn't using any of |
705 | // the flags reserved for implementations by the `nsIWebNavigation` interface. |
706 | // In the future, this check may be dropped. |
707 | MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType< decltype((aLoadState->LoadFlags() & INTERNAL_LOAD_FLAGS_LOADURI_SETUP_FLAGS ) == 0)>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!((aLoadState->LoadFlags() & INTERNAL_LOAD_FLAGS_LOADURI_SETUP_FLAGS ) == 0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("(aLoadState->LoadFlags() & INTERNAL_LOAD_FLAGS_LOADURI_SETUP_FLAGS) == 0" " (" "Should not have these flags set" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 709); AnnotateMozCrashReason("MOZ_ASSERT" "(" "(aLoadState->LoadFlags() & INTERNAL_LOAD_FLAGS_LOADURI_SETUP_FLAGS) == 0" ") (" "Should not have these flags set" ")"); do { MOZ_CrashSequence (__null, 709); __attribute__((nomerge)) ::abort(); } while (false ); } } while (false) |
708 | (aLoadState->LoadFlags() & INTERNAL_LOAD_FLAGS_LOADURI_SETUP_FLAGS) == 0,do { static_assert( mozilla::detail::AssertionConditionType< decltype((aLoadState->LoadFlags() & INTERNAL_LOAD_FLAGS_LOADURI_SETUP_FLAGS ) == 0)>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!((aLoadState->LoadFlags() & INTERNAL_LOAD_FLAGS_LOADURI_SETUP_FLAGS ) == 0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("(aLoadState->LoadFlags() & INTERNAL_LOAD_FLAGS_LOADURI_SETUP_FLAGS) == 0" " (" "Should not have these flags set" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 709); AnnotateMozCrashReason("MOZ_ASSERT" "(" "(aLoadState->LoadFlags() & INTERNAL_LOAD_FLAGS_LOADURI_SETUP_FLAGS) == 0" ") (" "Should not have these flags set" ")"); do { MOZ_CrashSequence (__null, 709); __attribute__((nomerge)) ::abort(); } while (false ); } } while (false) |
709 | "Should not have these flags set")do { static_assert( mozilla::detail::AssertionConditionType< decltype((aLoadState->LoadFlags() & INTERNAL_LOAD_FLAGS_LOADURI_SETUP_FLAGS ) == 0)>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!((aLoadState->LoadFlags() & INTERNAL_LOAD_FLAGS_LOADURI_SETUP_FLAGS ) == 0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("(aLoadState->LoadFlags() & INTERNAL_LOAD_FLAGS_LOADURI_SETUP_FLAGS) == 0" " (" "Should not have these flags set" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 709); AnnotateMozCrashReason("MOZ_ASSERT" "(" "(aLoadState->LoadFlags() & INTERNAL_LOAD_FLAGS_LOADURI_SETUP_FLAGS) == 0" ") (" "Should not have these flags set" ")"); do { MOZ_CrashSequence (__null, 709); __attribute__((nomerge)) ::abort(); } while (false ); } } while (false); |
710 | MOZ_ASSERT(aLoadState->TargetBrowsingContext().IsNull(),do { static_assert( mozilla::detail::AssertionConditionType< decltype(aLoadState->TargetBrowsingContext().IsNull())> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(aLoadState->TargetBrowsingContext().IsNull()))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("aLoadState->TargetBrowsingContext().IsNull()" " (" "Targeting doesn't occur until InternalLoad" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 711); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->TargetBrowsingContext().IsNull()" ") (" "Targeting doesn't occur until InternalLoad" ")"); do { MOZ_CrashSequence(__null, 711); __attribute__((nomerge)) ::abort (); } while (false); } } while (false) |
711 | "Targeting doesn't occur until InternalLoad")do { static_assert( mozilla::detail::AssertionConditionType< decltype(aLoadState->TargetBrowsingContext().IsNull())> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(aLoadState->TargetBrowsingContext().IsNull()))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("aLoadState->TargetBrowsingContext().IsNull()" " (" "Targeting doesn't occur until InternalLoad" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 711); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->TargetBrowsingContext().IsNull()" ") (" "Targeting doesn't occur until InternalLoad" ")"); do { MOZ_CrashSequence(__null, 711); __attribute__((nomerge)) ::abort (); } while (false); } } while (false); |
712 | |
713 | if (!aLoadState->TriggeringPrincipal()) { |
714 | MOZ_ASSERT(false, "LoadURI must have a triggering principal")do { static_assert( mozilla::detail::AssertionConditionType< decltype(false)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("false" " (" "LoadURI must have a triggering principal" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 714 ); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "LoadURI must have a triggering principal" ")"); do { MOZ_CrashSequence(__null, 714); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
715 | return NS_ERROR_FAILURE; |
716 | } |
717 | |
718 | MOZ_TRY(CheckDisallowedJavascriptLoad(aLoadState))__extension__({ auto mozTryVarTempResult = ::mozilla::ToResult (CheckDisallowedJavascriptLoad(aLoadState)); if ((__builtin_expect (!!(mozTryVarTempResult.isErr()), 0))) { return mozTryVarTempResult .propagateErr(); } mozTryVarTempResult.unwrap(); }); |
719 | |
720 | bool oldIsNavigating = mIsNavigating; |
721 | auto cleanupIsNavigating = |
722 | MakeScopeExit([&]() { mIsNavigating = oldIsNavigating; }); |
723 | if (aSetNavigating) { |
724 | mIsNavigating = true; |
725 | } |
726 | |
727 | PopupBlocker::PopupControlState popupState = PopupBlocker::openOverridden; |
728 | if (aLoadState->HasLoadFlags(LOAD_FLAGS_ALLOW_POPUPS)) { |
729 | popupState = PopupBlocker::openAllowed; |
730 | // If we allow popups as part of the navigation, ensure we fake a user |
731 | // interaction, so that popups can, in fact, be allowed to open. |
732 | if (WindowContext* wc = mBrowsingContext->GetCurrentWindowContext()) { |
733 | wc->NotifyUserGestureActivation(); |
734 | } |
735 | } |
736 | |
737 | AutoPopupStatePusherAutoPopupStatePusherInternal statePusher(popupState); |
738 | |
739 | if (aLoadState->GetCancelContentJSEpoch().isSome()) { |
740 | SetCancelContentJSEpoch(*aLoadState->GetCancelContentJSEpoch()); |
741 | } |
742 | |
743 | // Note: we allow loads to get through here even if mFiredUnloadEvent is |
744 | // true; that case will get handled in LoadInternal or LoadHistoryEntry, |
745 | // so we pass false as the second parameter to IsNavigationAllowed. |
746 | // However, we don't allow the page to change location *in the middle of* |
747 | // firing beforeunload, so we do need to check if *beforeunload* is currently |
748 | // firing, so we call IsNavigationAllowed rather than just IsPrintingOrPP. |
749 | if (!IsNavigationAllowed(true, false)) { |
750 | return NS_OK; // JS may not handle returning of an error code |
751 | } |
752 | |
753 | nsLoadFlags defaultLoadFlags = mBrowsingContext->GetDefaultLoadFlags(); |
754 | if (aLoadState->HasLoadFlags(LOAD_FLAGS_FORCE_TRR)) { |
755 | defaultLoadFlags |= nsIRequest::LOAD_TRR_ONLY_MODE; |
756 | } else if (aLoadState->HasLoadFlags(LOAD_FLAGS_DISABLE_TRR)) { |
757 | defaultLoadFlags |= nsIRequest::LOAD_TRR_DISABLED_MODE; |
758 | } |
759 | |
760 | MOZ_ALWAYS_SUCCEEDS(mBrowsingContext->SetDefaultLoadFlags(defaultLoadFlags))do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl (mBrowsingContext->SetDefaultLoadFlags(defaultLoadFlags))) , 1)))), 1))) { } else { do { do { } while (false); MOZ_ReportCrash ("" "NS_SUCCEEDED(mBrowsingContext->SetDefaultLoadFlags(defaultLoadFlags))" , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 760); AnnotateMozCrashReason ("MOZ_CRASH(" "NS_SUCCEEDED(mBrowsingContext->SetDefaultLoadFlags(defaultLoadFlags))" ")"); do { MOZ_CrashSequence(__null, 760); __attribute__((nomerge )) ::abort(); } while (false); } while (false); } } while (false ); |
761 | |
762 | if (!StartupTimeline::HasRecord(StartupTimeline::FIRST_LOAD_URI) && |
763 | mItemType == typeContent && !NS_IsAboutBlank(aLoadState->URI())) { |
764 | StartupTimeline::RecordOnce(StartupTimeline::FIRST_LOAD_URI); |
765 | } |
766 | |
767 | // LoadType used to be set to a default value here, if no LoadInfo/LoadState |
768 | // object was passed in. That functionality has been removed as of bug |
769 | // 1492648. LoadType should now be set up by the caller at the time they |
770 | // create their nsDocShellLoadState object to pass into LoadURI. |
771 | |
772 | MOZ_LOG(do { const ::mozilla::LogModule* moz_real_module = gDocShellLeakLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "nsDocShell[%p]: loading %s with flags 0x%08x" , this, aLoadState->URI()->GetSpecOrDefault().get(), aLoadState ->LoadFlags()); } } while (0) |
773 | gDocShellLeakLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gDocShellLeakLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "nsDocShell[%p]: loading %s with flags 0x%08x" , this, aLoadState->URI()->GetSpecOrDefault().get(), aLoadState ->LoadFlags()); } } while (0) |
774 | ("nsDocShell[%p]: loading %s with flags 0x%08x", this,do { const ::mozilla::LogModule* moz_real_module = gDocShellLeakLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "nsDocShell[%p]: loading %s with flags 0x%08x" , this, aLoadState->URI()->GetSpecOrDefault().get(), aLoadState ->LoadFlags()); } } while (0) |
775 | aLoadState->URI()->GetSpecOrDefault().get(), aLoadState->LoadFlags()))do { const ::mozilla::LogModule* moz_real_module = gDocShellLeakLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "nsDocShell[%p]: loading %s with flags 0x%08x" , this, aLoadState->URI()->GetSpecOrDefault().get(), aLoadState ->LoadFlags()); } } while (0); |
776 | |
777 | if ((!aLoadState->LoadIsFromSessionHistory() && |
778 | !LOAD_TYPE_HAS_FLAGS(aLoadState->LoadType(),((aLoadState->LoadType()) & ((LOAD_FLAGS_REPLACE_HISTORY ) << 16)) |
779 | LOAD_FLAGS_REPLACE_HISTORY)((aLoadState->LoadType()) & ((LOAD_FLAGS_REPLACE_HISTORY ) << 16))) || |
780 | aContinueHandlingSubframeHistory) { |
781 | // This is possibly a subframe, so handle it accordingly. |
782 | // |
783 | // If history exists, it will be loaded into the aLoadState object, and the |
784 | // LoadType will be changed. |
785 | if (MaybeHandleSubframeHistory(aLoadState, |
786 | aContinueHandlingSubframeHistory)) { |
787 | // MaybeHandleSubframeHistory returns true if we need to continue loading |
788 | // asynchronously. |
789 | return NS_OK; |
790 | } |
791 | } |
792 | |
793 | if (aLoadState->LoadIsFromSessionHistory()) { |
794 | MOZ_LOG(gSHLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gSHLog; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "nsDocShell[%p]: loading from session history" , this); } } while (0) |
795 | ("nsDocShell[%p]: loading from session history", this))do { const ::mozilla::LogModule* moz_real_module = gSHLog; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "nsDocShell[%p]: loading from session history" , this); } } while (0); |
796 | |
797 | if (!mozilla::SessionHistoryInParent()) { |
798 | nsCOMPtr<nsISHEntry> entry = aLoadState->SHEntry(); |
799 | return LoadHistoryEntry(entry, aLoadState->LoadType(), |
800 | aLoadState->HasValidUserGestureActivation()); |
801 | } |
802 | |
803 | // FIXME Null check aLoadState->GetLoadingSessionHistoryInfo()? |
804 | return LoadHistoryEntry(*aLoadState->GetLoadingSessionHistoryInfo(), |
805 | aLoadState->LoadType(), |
806 | aLoadState->HasValidUserGestureActivation()); |
807 | } |
808 | |
809 | // On history navigation via Back/Forward buttons, don't execute |
810 | // automatic JavaScript redirection such as |location.href = ...| or |
811 | // |window.open()| |
812 | // |
813 | // LOAD_NORMAL: window.open(...) etc. |
814 | // LOAD_STOP_CONTENT: location.href = ..., location.assign(...) |
815 | if ((aLoadState->LoadType() == LOAD_NORMAL || |
816 | aLoadState->LoadType() == LOAD_STOP_CONTENT) && |
817 | ShouldBlockLoadingForBackButton()) { |
818 | return NS_OK; |
819 | } |
820 | |
821 | BrowsingContext::Type bcType = mBrowsingContext->GetType(); |
822 | |
823 | // Set up the inheriting principal in LoadState. |
824 | nsresult rv = aLoadState->SetupInheritingPrincipal( |
825 | bcType, mBrowsingContext->OriginAttributesRef()); |
826 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 826); return rv; } } while (false); |
827 | |
828 | rv = aLoadState->SetupTriggeringPrincipal( |
829 | mBrowsingContext->OriginAttributesRef()); |
830 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 830); return rv; } } while (false); |
831 | |
832 | aLoadState->CalculateLoadURIFlags(); |
833 | |
834 | MOZ_ASSERT(aLoadState->TypeHint().IsVoid(),do { static_assert( mozilla::detail::AssertionConditionType< decltype(aLoadState->TypeHint().IsVoid())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aLoadState->TypeHint().IsVoid ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("aLoadState->TypeHint().IsVoid()" " (" "Typehint should be null when calling InternalLoad from LoadURI" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 835 ); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->TypeHint().IsVoid()" ") (" "Typehint should be null when calling InternalLoad from LoadURI" ")"); do { MOZ_CrashSequence(__null, 835); __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
835 | "Typehint should be null when calling InternalLoad from LoadURI")do { static_assert( mozilla::detail::AssertionConditionType< decltype(aLoadState->TypeHint().IsVoid())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aLoadState->TypeHint().IsVoid ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("aLoadState->TypeHint().IsVoid()" " (" "Typehint should be null when calling InternalLoad from LoadURI" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 835 ); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->TypeHint().IsVoid()" ") (" "Typehint should be null when calling InternalLoad from LoadURI" ")"); do { MOZ_CrashSequence(__null, 835); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
836 | MOZ_ASSERT(aLoadState->FileName().IsVoid(),do { static_assert( mozilla::detail::AssertionConditionType< decltype(aLoadState->FileName().IsVoid())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aLoadState->FileName().IsVoid ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("aLoadState->FileName().IsVoid()" " (" "FileName should be null when calling InternalLoad from LoadURI" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 837 ); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->FileName().IsVoid()" ") (" "FileName should be null when calling InternalLoad from LoadURI" ")"); do { MOZ_CrashSequence(__null, 837); __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
837 | "FileName should be null when calling InternalLoad from LoadURI")do { static_assert( mozilla::detail::AssertionConditionType< decltype(aLoadState->FileName().IsVoid())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aLoadState->FileName().IsVoid ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("aLoadState->FileName().IsVoid()" " (" "FileName should be null when calling InternalLoad from LoadURI" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 837 ); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->FileName().IsVoid()" ") (" "FileName should be null when calling InternalLoad from LoadURI" ")"); do { MOZ_CrashSequence(__null, 837); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
838 | MOZ_ASSERT(!aLoadState->LoadIsFromSessionHistory(),do { static_assert( mozilla::detail::AssertionConditionType< decltype(!aLoadState->LoadIsFromSessionHistory())>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(!aLoadState->LoadIsFromSessionHistory()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!aLoadState->LoadIsFromSessionHistory()" " (" "Shouldn't be loading from an entry when calling InternalLoad " "from LoadURI" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 840); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aLoadState->LoadIsFromSessionHistory()" ") (" "Shouldn't be loading from an entry when calling InternalLoad " "from LoadURI" ")"); do { MOZ_CrashSequence(__null, 840); __attribute__ ((nomerge)) ::abort(); } while (false); } } while (false) |
839 | "Shouldn't be loading from an entry when calling InternalLoad "do { static_assert( mozilla::detail::AssertionConditionType< decltype(!aLoadState->LoadIsFromSessionHistory())>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(!aLoadState->LoadIsFromSessionHistory()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!aLoadState->LoadIsFromSessionHistory()" " (" "Shouldn't be loading from an entry when calling InternalLoad " "from LoadURI" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 840); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aLoadState->LoadIsFromSessionHistory()" ") (" "Shouldn't be loading from an entry when calling InternalLoad " "from LoadURI" ")"); do { MOZ_CrashSequence(__null, 840); __attribute__ ((nomerge)) ::abort(); } while (false); } } while (false) |
840 | "from LoadURI")do { static_assert( mozilla::detail::AssertionConditionType< decltype(!aLoadState->LoadIsFromSessionHistory())>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(!aLoadState->LoadIsFromSessionHistory()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!aLoadState->LoadIsFromSessionHistory()" " (" "Shouldn't be loading from an entry when calling InternalLoad " "from LoadURI" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 840); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aLoadState->LoadIsFromSessionHistory()" ") (" "Shouldn't be loading from an entry when calling InternalLoad " "from LoadURI" ")"); do { MOZ_CrashSequence(__null, 840); __attribute__ ((nomerge)) ::abort(); } while (false); } } while (false); |
841 | |
842 | // If we have a system triggering principal, we can assume that this load was |
843 | // triggered by some UI in the browser chrome, such as the URL bar or |
844 | // bookmark bar. This should count as a user interaction for the current sh |
845 | // entry, so that the user may navigate back to the current entry, from the |
846 | // entry that is going to be added as part of this load. |
847 | nsCOMPtr<nsIPrincipal> triggeringPrincipal = |
848 | aLoadState->TriggeringPrincipal(); |
849 | if (triggeringPrincipal && triggeringPrincipal->IsSystemPrincipal()) { |
850 | if (mozilla::SessionHistoryInParent()) { |
851 | WindowContext* topWc = mBrowsingContext->GetTopWindowContext(); |
852 | if (topWc && !topWc->IsDiscarded()) { |
853 | MOZ_ALWAYS_SUCCEEDS(topWc->SetSHEntryHasUserInteraction(true))do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl (topWc->SetSHEntryHasUserInteraction(true))), 1)))), 1))) { } else { do { do { } while (false); MOZ_ReportCrash("" "NS_SUCCEEDED(topWc->SetSHEntryHasUserInteraction(true))" , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 853); AnnotateMozCrashReason ("MOZ_CRASH(" "NS_SUCCEEDED(topWc->SetSHEntryHasUserInteraction(true))" ")"); do { MOZ_CrashSequence(__null, 853); __attribute__((nomerge )) ::abort(); } while (false); } while (false); } } while (false ); |
854 | } |
855 | } else { |
856 | bool oshe = false; |
857 | nsCOMPtr<nsISHEntry> currentSHEntry; |
858 | GetCurrentSHEntry(getter_AddRefs(currentSHEntry), &oshe); |
859 | if (currentSHEntry) { |
860 | currentSHEntry->SetHasUserInteraction(true); |
861 | } |
862 | } |
863 | } |
864 | |
865 | rv = InternalLoad(aLoadState); |
866 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 866); return rv; } } while (false); |
867 | |
868 | if (aLoadState->GetOriginalURIString().isSome()) { |
869 | // Save URI string in case it's needed later when |
870 | // sending to search engine service in EndPageLoad() |
871 | mOriginalUriString = *aLoadState->GetOriginalURIString(); |
872 | } |
873 | |
874 | return NS_OK; |
875 | } |
876 | |
877 | bool nsDocShell::IsLoadingFromSessionHistory() { |
878 | return mActiveEntryIsLoadingFromSessionHistory; |
879 | } |
880 | |
881 | // StopDetector is modeled similarly to OnloadBlocker; it is a rather |
882 | // dummy nsIRequest implementation which can be added to an nsILoadGroup to |
883 | // detect Cancel calls. |
884 | class StopDetector final : public nsIRequest { |
885 | public: |
886 | StopDetector() = default; |
887 | |
888 | NS_DECL_ISUPPORTSpublic: virtual nsresult QueryInterface(const nsIID& aIID , void** aInstancePtr) override; virtual MozExternalRefCountType AddRef(void) override; virtual MozExternalRefCountType Release (void) override; using HasThreadSafeRefCnt = std::false_type; protected: nsAutoRefCnt mRefCnt; nsAutoOwningThread _mOwningThread ; public: |
889 | NS_DECL_NSIREQUESTvirtual nsresult GetName(nsACString& aName) override; virtual nsresult IsPending(bool *_retval) override; virtual nsresult GetStatus(nsresult *aStatus) override; virtual nsresult Cancel (nsresult aStatus) override; virtual nsresult Suspend(void) override ; virtual nsresult Resume(void) override; virtual nsresult GetLoadGroup (nsILoadGroup **aLoadGroup) override; virtual nsresult SetLoadGroup (nsILoadGroup *aLoadGroup) override; virtual nsresult GetLoadFlags (nsLoadFlags *aLoadFlags) override; virtual nsresult SetLoadFlags (nsLoadFlags aLoadFlags) override; virtual nsresult GetTRRMode (nsIRequest::TRRMode *_retval) override; virtual nsresult SetTRRMode (nsIRequest::TRRMode mode) override; virtual nsresult CancelWithReason (nsresult aStatus, const nsACString& aReason) override; virtual nsresult GetCanceledReason(nsACString& aCanceledReason) override ; virtual nsresult SetCanceledReason(const nsACString& aCanceledReason ) override; |
890 | |
891 | bool Canceled() { return mCanceled; } |
892 | |
893 | private: |
894 | ~StopDetector() = default; |
895 | |
896 | bool mCanceled = false; |
897 | }; |
898 | |
899 | NS_IMPL_ISUPPORTS(StopDetector, nsIRequest)MozExternalRefCountType StopDetector::AddRef(void) { static_assert (!std::is_destructible_v<StopDetector>, "Reference-counted class " "StopDetector" " should not have a public destructor. " "Make this class's destructor non-public" ); do { static_assert( mozilla::detail::AssertionConditionType <decltype(int32_t(mRefCnt) >= 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0" " (" "illegal refcnt" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 899); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0" ") (" "illegal refcnt" ")"); do { MOZ_CrashSequence(__null, 899 ); __attribute__((nomerge)) ::abort(); } while (false); } } while (false); do { static_assert( mozilla::detail::AssertionConditionType <decltype("StopDetector" != nullptr)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!("StopDetector" != nullptr))) , 0))) { do { } while (false); MOZ_ReportAssertionFailure("\"StopDetector\" != nullptr" " (" "Must specify a name" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 899); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"StopDetector\" != nullptr" ") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null , 899); __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread.AssertOwnership ("StopDetector" " not thread-safe"); nsrefcnt count = ++mRefCnt ; NS_LogAddRef((this), (count), ("StopDetector"), (uint32_t)( sizeof(*this))); return count; } MozExternalRefCountType StopDetector ::Release(void) { do { static_assert( mozilla::detail::AssertionConditionType <decltype(int32_t(mRefCnt) > 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) > 0))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0" " (" "dup release" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 899); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0" ") (" "dup release" ")"); do { MOZ_CrashSequence(__null, 899 ); __attribute__((nomerge)) ::abort(); } while (false); } } while (false); do { static_assert( mozilla::detail::AssertionConditionType <decltype("StopDetector" != nullptr)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!("StopDetector" != nullptr))) , 0))) { do { } while (false); MOZ_ReportAssertionFailure("\"StopDetector\" != nullptr" " (" "Must specify a name" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 899); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"StopDetector\" != nullptr" ") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null , 899); __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread.AssertOwnership ("StopDetector" " not thread-safe"); const char* const nametmp = "StopDetector"; nsrefcnt count = --mRefCnt; NS_LogRelease( (this), (count), (nametmp)); if (count == 0) { mRefCnt = 1; delete (this); return 0; } return count; } nsresult StopDetector::QueryInterface (const nsIID& aIID, void** aInstancePtr) { do { if (!(aInstancePtr )) { NS_DebugBreak(NS_DEBUG_ASSERTION, "QueryInterface requires a non-NULL destination!" , "aInstancePtr", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 899); MOZ_PretendNoReturn(); } } while (0); nsresult rv = NS_ERROR_FAILURE ; static_assert(1 > 0, "Need more arguments to NS_INTERFACE_TABLE" ); static const QITableEntry table[] = { {&mozilla::detail ::kImplementedIID<StopDetector, nsIRequest>, int32_t( reinterpret_cast <char*>(static_cast<nsIRequest*>((StopDetector*)0x1000 )) - reinterpret_cast<char*>((StopDetector*)0x1000))}, { &mozilla::detail::kImplementedIID<StopDetector, nsISupports >, int32_t(reinterpret_cast<char*>(static_cast<nsISupports *>( static_cast<nsIRequest*>((StopDetector*)0x1000)) ) - reinterpret_cast<char*>((StopDetector*)0x1000))}, { nullptr, 0 } } ; static_assert(std::size(table) > 1, "need at least 1 interface" ); rv = NS_TableDrivenQI(static_cast<void*>(this), aIID , aInstancePtr, table); return rv; } |
900 | |
901 | NS_IMETHODIMPnsresult |
902 | StopDetector::GetName(nsACString& aResult) { |
903 | aResult.AssignLiteral("about:stop-detector"); |
904 | return NS_OK; |
905 | } |
906 | |
907 | NS_IMETHODIMPnsresult |
908 | StopDetector::IsPending(bool* aRetVal) { |
909 | *aRetVal = true; |
910 | return NS_OK; |
911 | } |
912 | |
913 | NS_IMETHODIMPnsresult |
914 | StopDetector::GetStatus(nsresult* aStatus) { |
915 | *aStatus = NS_OK; |
916 | return NS_OK; |
917 | } |
918 | |
919 | NS_IMETHODIMPnsresult StopDetector::SetCanceledReason(const nsACString& aReason) { |
920 | return SetCanceledReasonImpl(aReason); |
921 | } |
922 | |
923 | NS_IMETHODIMPnsresult StopDetector::GetCanceledReason(nsACString& aReason) { |
924 | return GetCanceledReasonImpl(aReason); |
925 | } |
926 | |
927 | NS_IMETHODIMPnsresult StopDetector::CancelWithReason(nsresult aStatus, |
928 | const nsACString& aReason) { |
929 | return CancelWithReasonImpl(aStatus, aReason); |
930 | } |
931 | |
932 | NS_IMETHODIMPnsresult |
933 | StopDetector::Cancel(nsresult aStatus) { |
934 | mCanceled = true; |
935 | return NS_OK; |
936 | } |
937 | |
938 | NS_IMETHODIMPnsresult |
939 | StopDetector::Suspend(void) { return NS_OK; } |
940 | NS_IMETHODIMPnsresult |
941 | StopDetector::Resume(void) { return NS_OK; } |
942 | |
943 | NS_IMETHODIMPnsresult |
944 | StopDetector::GetLoadGroup(nsILoadGroup** aLoadGroup) { |
945 | *aLoadGroup = nullptr; |
946 | return NS_OK; |
947 | } |
948 | |
949 | NS_IMETHODIMPnsresult |
950 | StopDetector::SetLoadGroup(nsILoadGroup* aLoadGroup) { return NS_OK; } |
951 | |
952 | NS_IMETHODIMPnsresult |
953 | StopDetector::GetLoadFlags(nsLoadFlags* aLoadFlags) { |
954 | *aLoadFlags = nsIRequest::LOAD_NORMAL; |
955 | return NS_OK; |
956 | } |
957 | |
958 | NS_IMETHODIMPnsresult |
959 | StopDetector::GetTRRMode(nsIRequest::TRRMode* aTRRMode) { |
960 | return GetTRRModeImpl(aTRRMode); |
961 | } |
962 | |
963 | NS_IMETHODIMPnsresult |
964 | StopDetector::SetTRRMode(nsIRequest::TRRMode aTRRMode) { |
965 | return SetTRRModeImpl(aTRRMode); |
966 | } |
967 | |
968 | NS_IMETHODIMPnsresult |
969 | StopDetector::SetLoadFlags(nsLoadFlags aLoadFlags) { return NS_OK; } |
970 | |
971 | bool nsDocShell::MaybeHandleSubframeHistory( |
972 | nsDocShellLoadState* aLoadState, bool aContinueHandlingSubframeHistory) { |
973 | // First, verify if this is a subframe. |
974 | // Note, it is ok to rely on docshell here and not browsing context since when |
975 | // an iframe is created, it has first in-process docshell. |
976 | nsCOMPtr<nsIDocShellTreeItem> parentAsItem; |
977 | GetInProcessSameTypeParent(getter_AddRefs(parentAsItem)); |
978 | nsCOMPtr<nsIDocShell> parentDS(do_QueryInterface(parentAsItem)); |
979 | |
980 | if (!parentDS || parentDS == static_cast<nsIDocShell*>(this)) { |
981 | if (mBrowsingContext && mBrowsingContext->IsTop()) { |
982 | // This is the root docshell. If we got here while |
983 | // executing an onLoad Handler,this load will not go |
984 | // into session history. |
985 | // XXX Why is this code in a method which deals with iframes! |
986 | if (aLoadState->IsFormSubmission()) { |
987 | #ifdef DEBUG1 |
988 | if (!mEODForCurrentDocument) { |
989 | const MaybeDiscarded<BrowsingContext>& targetBC = |
990 | aLoadState->TargetBrowsingContext(); |
991 | MOZ_ASSERT_IF(GetBrowsingContext() == targetBC.get(),do { if (GetBrowsingContext() == targetBC.get()) { do { static_assert ( mozilla::detail::AssertionConditionType<decltype(aLoadState ->LoadType() == LOAD_NORMAL_REPLACE)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aLoadState->LoadType() == LOAD_NORMAL_REPLACE))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("aLoadState->LoadType() == LOAD_NORMAL_REPLACE", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 992); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->LoadType() == LOAD_NORMAL_REPLACE" ")"); do { MOZ_CrashSequence(__null, 992); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) |
992 | aLoadState->LoadType() == LOAD_NORMAL_REPLACE)do { if (GetBrowsingContext() == targetBC.get()) { do { static_assert ( mozilla::detail::AssertionConditionType<decltype(aLoadState ->LoadType() == LOAD_NORMAL_REPLACE)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aLoadState->LoadType() == LOAD_NORMAL_REPLACE))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("aLoadState->LoadType() == LOAD_NORMAL_REPLACE", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 992); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->LoadType() == LOAD_NORMAL_REPLACE" ")"); do { MOZ_CrashSequence(__null, 992); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); |
993 | } |
994 | #endif |
995 | } else { |
996 | bool inOnLoadHandler = false; |
997 | GetIsExecutingOnLoadHandler(&inOnLoadHandler); |
998 | if (inOnLoadHandler) { |
999 | aLoadState->SetLoadType(LOAD_NORMAL_REPLACE); |
1000 | } |
1001 | } |
1002 | } |
1003 | return false; |
1004 | } |
1005 | |
1006 | /* OK. It is a subframe. Checkout the parent's loadtype. If the parent was |
1007 | * loaded through a history mechanism, then get the SH entry for the child |
1008 | * from the parent. This is done to restore frameset navigation while going |
1009 | * back/forward. If the parent was loaded through any other loadType, set the |
1010 | * child's loadType too accordingly, so that session history does not get |
1011 | * confused. |
1012 | */ |
1013 | |
1014 | // Get the parent's load type |
1015 | uint32_t parentLoadType; |
1016 | parentDS->GetLoadType(&parentLoadType); |
1017 | |
1018 | if (!aContinueHandlingSubframeHistory) { |
1019 | if (mozilla::SessionHistoryInParent()) { |
1020 | if (nsDocShell::Cast(parentDS.get())->IsLoadingFromSessionHistory() && |
1021 | !GetCreatedDynamically()) { |
1022 | if (XRE_IsContentProcess()) { |
1023 | dom::ContentChild* contentChild = dom::ContentChild::GetSingleton(); |
1024 | nsCOMPtr<nsILoadGroup> loadGroup; |
1025 | GetLoadGroup(getter_AddRefs(loadGroup)); |
1026 | if (contentChild && loadGroup && !mCheckingSessionHistory) { |
1027 | RefPtr<Document> parentDoc = parentDS->GetDocument(); |
1028 | parentDoc->BlockOnload(); |
1029 | RefPtr<BrowsingContext> browsingContext = mBrowsingContext; |
1030 | Maybe<uint64_t> currentLoadIdentifier = |
1031 | mBrowsingContext->GetCurrentLoadIdentifier(); |
1032 | RefPtr<nsDocShellLoadState> loadState = aLoadState; |
1033 | bool isNavigating = mIsNavigating; |
1034 | RefPtr<StopDetector> stopDetector = new StopDetector(); |
1035 | loadGroup->AddRequest(stopDetector, nullptr); |
1036 | // Need to set mCheckingSessionHistory so that |
1037 | // GetIsAttemptingToNavigate() returns true. |
1038 | mCheckingSessionHistory = true; |
1039 | |
1040 | auto resolve = |
1041 | [currentLoadIdentifier, browsingContext, parentDoc, loadState, |
1042 | isNavigating, loadGroup, stopDetector]( |
1043 | mozilla::Maybe<LoadingSessionHistoryInfo>&& aResult) { |
1044 | RefPtr<nsDocShell> docShell = |
1045 | static_cast<nsDocShell*>(browsingContext->GetDocShell()); |
1046 | auto unblockParent = MakeScopeExit( |
1047 | [loadGroup, stopDetector, parentDoc, docShell]() { |
1048 | if (docShell) { |
1049 | docShell->mCheckingSessionHistory = false; |
1050 | } |
1051 | loadGroup->RemoveRequest(stopDetector, nullptr, NS_OK); |
1052 | parentDoc->UnblockOnload(false); |
1053 | }); |
1054 | |
1055 | if (!docShell || !docShell->mCheckingSessionHistory) { |
1056 | return; |
1057 | } |
1058 | |
1059 | if (stopDetector->Canceled()) { |
1060 | return; |
1061 | } |
1062 | if (currentLoadIdentifier == |
1063 | browsingContext->GetCurrentLoadIdentifier() && |
1064 | aResult.isSome()) { |
1065 | loadState->SetLoadingSessionHistoryInfo(aResult.value()); |
1066 | // This is an initial subframe load from the session |
1067 | // history, index doesn't need to be updated. |
1068 | loadState->SetLoadIsFromSessionHistory(0, false); |
1069 | } |
1070 | |
1071 | // We got the results back from the parent process, call |
1072 | // LoadURI again with the possibly updated data. |
1073 | docShell->LoadURI(loadState, isNavigating, true); |
1074 | }; |
1075 | auto reject = [loadGroup, stopDetector, browsingContext, |
1076 | parentDoc](mozilla::ipc::ResponseRejectReason) { |
1077 | RefPtr<nsDocShell> docShell = |
1078 | static_cast<nsDocShell*>(browsingContext->GetDocShell()); |
1079 | if (docShell) { |
1080 | docShell->mCheckingSessionHistory = false; |
1081 | } |
1082 | // In practise reject shouldn't be called ever. |
1083 | loadGroup->RemoveRequest(stopDetector, nullptr, NS_OK); |
1084 | parentDoc->UnblockOnload(false); |
1085 | }; |
1086 | contentChild->SendGetLoadingSessionHistoryInfoFromParent( |
1087 | mBrowsingContext, std::move(resolve), std::move(reject)); |
1088 | return true; |
1089 | } |
1090 | } else { |
1091 | Maybe<LoadingSessionHistoryInfo> info; |
1092 | mBrowsingContext->Canonical()->GetLoadingSessionHistoryInfoFromParent( |
1093 | info); |
1094 | if (info.isSome()) { |
1095 | aLoadState->SetLoadingSessionHistoryInfo(info.value()); |
1096 | // This is an initial subframe load from the session |
1097 | // history, index doesn't need to be updated. |
1098 | aLoadState->SetLoadIsFromSessionHistory(0, false); |
1099 | } |
1100 | } |
1101 | } |
1102 | } else { |
1103 | // Get the ShEntry for the child from the parent |
1104 | nsCOMPtr<nsISHEntry> currentSH; |
1105 | bool oshe = false; |
1106 | parentDS->GetCurrentSHEntry(getter_AddRefs(currentSH), &oshe); |
1107 | bool dynamicallyAddedChild = GetCreatedDynamically(); |
1108 | |
1109 | if (!dynamicallyAddedChild && !oshe && currentSH) { |
1110 | // Only use the old SHEntry, if we're sure enough that |
1111 | // it wasn't originally for some other frame. |
1112 | nsCOMPtr<nsISHEntry> shEntry; |
1113 | currentSH->GetChildSHEntryIfHasNoDynamicallyAddedChild( |
1114 | mBrowsingContext->ChildOffset(), getter_AddRefs(shEntry)); |
1115 | if (shEntry) { |
1116 | aLoadState->SetSHEntry(shEntry); |
1117 | } |
1118 | } |
1119 | } |
1120 | } |
1121 | |
1122 | // Make some decisions on the child frame's loadType based on the |
1123 | // parent's loadType, if the subframe hasn't loaded anything into it. |
1124 | // |
1125 | // In some cases privileged scripts may try to get the DOMWindow |
1126 | // reference of this docshell before the loading starts, causing the |
1127 | // initial about:blank content viewer being created and mCurrentURI being |
1128 | // set. To handle this case we check if mCurrentURI is about:blank and |
1129 | // currentSHEntry is null. |
1130 | bool oshe = false; |
1131 | nsCOMPtr<nsISHEntry> currentChildEntry; |
1132 | GetCurrentSHEntry(getter_AddRefs(currentChildEntry), &oshe); |
1133 | |
1134 | if (mCurrentURI && (!NS_IsAboutBlank(mCurrentURI) || currentChildEntry || |
1135 | mLoadingEntry || mActiveEntry)) { |
1136 | // This is a pre-existing subframe. If |
1137 | // 1. The load of this frame was not originally initiated by session |
1138 | // history directly (i.e. (!shEntry) condition succeeded, but it can |
1139 | // still be a history load on parent which causes this frame being |
1140 | // loaded), which we checked with the above assert, and |
1141 | // 2. mCurrentURI is not null, nor the initial about:blank, |
1142 | // it is possible that a parent's onLoadHandler or even self's |
1143 | // onLoadHandler is loading a new page in this child. Check parent's and |
1144 | // self's busy flag and if it is set, we don't want this onLoadHandler |
1145 | // load to get in to session history. |
1146 | BusyFlags parentBusy = parentDS->GetBusyFlags(); |
1147 | BusyFlags selfBusy = GetBusyFlags(); |
1148 | |
1149 | if (parentBusy & BUSY_FLAGS_BUSY || selfBusy & BUSY_FLAGS_BUSY) { |
1150 | aLoadState->SetLoadType(LOAD_NORMAL_REPLACE); |
1151 | aLoadState->ClearLoadIsFromSessionHistory(); |
1152 | } |
1153 | return false; |
1154 | } |
1155 | |
1156 | // This is a newly created frame. Check for exception cases first. |
1157 | // By default the subframe will inherit the parent's loadType. |
1158 | if (aLoadState->LoadIsFromSessionHistory() && |
1159 | (parentLoadType == LOAD_NORMAL || parentLoadType == LOAD_LINK)) { |
1160 | // The parent was loaded normally. In this case, this *brand new* |
1161 | // child really shouldn't have a SHEntry. If it does, it could be |
1162 | // because the parent is replacing an existing frame with a new frame, |
1163 | // in the onLoadHandler. We don't want this url to get into session |
1164 | // history. Clear off shEntry, and set load type to |
1165 | // LOAD_BYPASS_HISTORY. |
1166 | bool inOnLoadHandler = false; |
1167 | parentDS->GetIsExecutingOnLoadHandler(&inOnLoadHandler); |
1168 | if (inOnLoadHandler) { |
1169 | aLoadState->SetLoadType(LOAD_NORMAL_REPLACE); |
1170 | aLoadState->ClearLoadIsFromSessionHistory(); |
1171 | } |
1172 | } else if (parentLoadType == LOAD_REFRESH) { |
1173 | // Clear shEntry. For refresh loads, we have to load |
1174 | // what comes through the pipe, not what's in history. |
1175 | aLoadState->ClearLoadIsFromSessionHistory(); |
1176 | } else if ((parentLoadType == LOAD_BYPASS_HISTORY) || |
1177 | (aLoadState->LoadIsFromSessionHistory() && |
1178 | ((parentLoadType & LOAD_CMD_HISTORY) || |
1179 | (parentLoadType == LOAD_RELOAD_NORMAL) || |
1180 | (parentLoadType == LOAD_RELOAD_CHARSET_CHANGE) || |
1181 | (parentLoadType == LOAD_RELOAD_CHARSET_CHANGE_BYPASS_CACHE) || |
1182 | (parentLoadType == |
1183 | LOAD_RELOAD_CHARSET_CHANGE_BYPASS_PROXY_AND_CACHE)))) { |
1184 | // If the parent url, bypassed history or was loaded from |
1185 | // history, pass on the parent's loadType to the new child |
1186 | // frame too, so that the child frame will also |
1187 | // avoid getting into history. |
1188 | aLoadState->SetLoadType(parentLoadType); |
1189 | } else if (parentLoadType == LOAD_ERROR_PAGE) { |
1190 | // If the parent document is an error page, we don't |
1191 | // want to update global/session history. However, |
1192 | // this child frame is not an error page. |
1193 | aLoadState->SetLoadType(LOAD_BYPASS_HISTORY); |
1194 | } else if ((parentLoadType == LOAD_RELOAD_BYPASS_CACHE) || |
1195 | (parentLoadType == LOAD_RELOAD_BYPASS_PROXY) || |
1196 | (parentLoadType == LOAD_RELOAD_BYPASS_PROXY_AND_CACHE)) { |
1197 | // the new frame should inherit the parent's load type so that it also |
1198 | // bypasses the cache and/or proxy |
1199 | aLoadState->SetLoadType(parentLoadType); |
1200 | } |
1201 | |
1202 | return false; |
1203 | } |
1204 | |
1205 | /* |
1206 | * Reset state to a new content model within the current document and the |
1207 | * document viewer. Called by the document before initiating an out of band |
1208 | * document.write(). |
1209 | */ |
1210 | NS_IMETHODIMPnsresult |
1211 | nsDocShell::PrepareForNewContentModel() { |
1212 | // Clear out our form control state, because the state of controls |
1213 | // in the pre-open() document should not affect the state of |
1214 | // controls that are now going to be written. |
1215 | SetLayoutHistoryState(nullptr); |
1216 | mEODForCurrentDocument = false; |
1217 | return NS_OK; |
1218 | } |
1219 | |
1220 | NS_IMETHODIMPnsresult |
1221 | nsDocShell::FirePageHideNotification(bool aIsUnload) { |
1222 | FirePageHideNotificationInternal(aIsUnload, false); |
1223 | return NS_OK; |
1224 | } |
1225 | |
1226 | void nsDocShell::FirePageHideNotificationInternal( |
1227 | bool aIsUnload, bool aSkipCheckingDynEntries) { |
1228 | if (mDocumentViewer && !mFiredUnloadEvent) { |
1229 | // Keep an explicit reference since calling PageHide could release |
1230 | // mDocumentViewer |
1231 | nsCOMPtr<nsIDocumentViewer> viewer(mDocumentViewer); |
1232 | mFiredUnloadEvent = true; |
1233 | |
1234 | if (mTiming) { |
1235 | mTiming->NotifyUnloadEventStart(); |
1236 | } |
1237 | |
1238 | viewer->PageHide(aIsUnload); |
1239 | |
1240 | if (mTiming) { |
1241 | mTiming->NotifyUnloadEventEnd(); |
1242 | } |
1243 | |
1244 | AutoTArray<nsCOMPtr<nsIDocShell>, 8> kids; |
1245 | uint32_t n = mChildList.Length(); |
1246 | kids.SetCapacity(n); |
1247 | for (uint32_t i = 0; i < n; i++) { |
1248 | kids.AppendElement(do_QueryInterface(ChildAt(i))); |
1249 | } |
1250 | |
1251 | n = kids.Length(); |
1252 | for (uint32_t i = 0; i < n; ++i) { |
1253 | RefPtr<nsDocShell> child = static_cast<nsDocShell*>(kids[i].get()); |
1254 | if (child) { |
1255 | // Skip checking dynamic subframe entries in our children. |
1256 | child->FirePageHideNotificationInternal(aIsUnload, true); |
1257 | } |
1258 | } |
1259 | |
1260 | // If the document is unloading, remove all dynamic subframe entries. |
1261 | if (aIsUnload && !aSkipCheckingDynEntries) { |
1262 | RefPtr<ChildSHistory> rootSH = GetRootSessionHistory(); |
1263 | if (rootSH) { |
1264 | MOZ_LOG(do { const ::mozilla::LogModule* moz_real_module = gSHLog; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "nsDocShell %p unloading, remove dynamic subframe entries" , this); } } while (0) |
1265 | gSHLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gSHLog; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "nsDocShell %p unloading, remove dynamic subframe entries" , this); } } while (0) |
1266 | ("nsDocShell %p unloading, remove dynamic subframe entries", this))do { const ::mozilla::LogModule* moz_real_module = gSHLog; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "nsDocShell %p unloading, remove dynamic subframe entries" , this); } } while (0); |
1267 | if (mozilla::SessionHistoryInParent()) { |
1268 | if (mActiveEntry) { |
1269 | mBrowsingContext->RemoveDynEntriesFromActiveSessionHistoryEntry(); |
1270 | } |
1271 | MOZ_LOG(gSHLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gSHLog; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "nsDocShell %p unloading, no active entries" , this); } } while (0) |
1272 | ("nsDocShell %p unloading, no active entries", this))do { const ::mozilla::LogModule* moz_real_module = gSHLog; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "nsDocShell %p unloading, no active entries" , this); } } while (0); |
1273 | } else if (mOSHE) { |
1274 | int32_t index = rootSH->Index(); |
1275 | rootSH->LegacySHistory()->RemoveDynEntries(index, mOSHE); |
1276 | } |
1277 | } |
1278 | } |
1279 | |
1280 | // Now make sure our editor, if any, is detached before we go |
1281 | // any farther. |
1282 | DetachEditorFromWindow(); |
1283 | } |
1284 | } |
1285 | |
1286 | void nsDocShell::ThawFreezeNonRecursive(bool aThaw) { |
1287 | MOZ_ASSERT(mozilla::BFCacheInParent())do { static_assert( mozilla::detail::AssertionConditionType< decltype(mozilla::BFCacheInParent())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mozilla::BFCacheInParent())) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mozilla::BFCacheInParent()" , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 1287); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "mozilla::BFCacheInParent()" ")"); do { MOZ_CrashSequence (__null, 1287); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); |
1288 | |
1289 | if (!mScriptGlobal) { |
1290 | return; |
1291 | } |
1292 | |
1293 | if (RefPtr<nsGlobalWindowInner> inner = |
1294 | nsGlobalWindowInner::Cast(mScriptGlobal->GetCurrentInnerWindow())) { |
1295 | if (aThaw) { |
1296 | inner->Thaw(false); |
1297 | } else { |
1298 | inner->Freeze(false); |
1299 | } |
1300 | } |
1301 | } |
1302 | |
1303 | void nsDocShell::FirePageHideShowNonRecursive(bool aShow) { |
1304 | MOZ_ASSERT(mozilla::BFCacheInParent())do { static_assert( mozilla::detail::AssertionConditionType< decltype(mozilla::BFCacheInParent())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mozilla::BFCacheInParent())) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mozilla::BFCacheInParent()" , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 1304); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "mozilla::BFCacheInParent()" ")"); do { MOZ_CrashSequence (__null, 1304); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); |
1305 | |
1306 | if (!mDocumentViewer) { |
1307 | return; |
1308 | } |
1309 | |
1310 | // Emulate what non-SHIP BFCache does too. In pageshow case |
1311 | // add and remove a request and before that call SetCurrentURI to get |
1312 | // the location change notification. |
1313 | // For pagehide, set mFiredUnloadEvent to true, so that unload doesn't fire. |
1314 | nsCOMPtr<nsIDocumentViewer> viewer(mDocumentViewer); |
1315 | if (aShow) { |
1316 | viewer->SetIsHidden(false); |
1317 | mRefreshURIList = std::move(mBFCachedRefreshURIList); |
1318 | RefreshURIFromQueue(); |
1319 | mFiredUnloadEvent = false; |
1320 | RefPtr<Document> doc = viewer->GetDocument(); |
1321 | if (doc) { |
1322 | doc->NotifyActivityChanged(); |
1323 | nsCOMPtr<nsPIDOMWindowInner> inner = |
1324 | mScriptGlobal ? mScriptGlobal->GetCurrentInnerWindow() : nullptr; |
1325 | if (mBrowsingContext->IsTop()) { |
1326 | doc->NotifyPossibleTitleChange(false); |
1327 | doc->SetLoadingOrRestoredFromBFCacheTimeStampToNow(); |
1328 | if (inner) { |
1329 | // Now that we have found the inner window of the page restored |
1330 | // from the history, we have to make sure that |
1331 | // performance.navigation.type is 2. |
1332 | // Traditionally this type change has been done to the top level page |
1333 | // only. |
1334 | Performance* performance = inner->GetPerformance(); |
1335 | if (performance) { |
1336 | performance->GetDOMTiming()->NotifyRestoreStart(); |
1337 | } |
1338 | } |
1339 | } |
1340 | |
1341 | nsCOMPtr<nsIChannel> channel = doc->GetChannel(); |
1342 | if (channel) { |
1343 | SetLoadType(LOAD_HISTORY); |
1344 | mEODForCurrentDocument = false; |
1345 | mIsRestoringDocument = true; |
1346 | mLoadGroup->AddRequest(channel, nullptr); |
1347 | nsCOMPtr<nsIURI> uri; |
1348 | if (doc->FragmentDirective()) { |
1349 | // If we have fragment directives, then we've mutated the document |
1350 | // uri. Set the current URI from session history instead. |
1351 | if (mozilla::SessionHistoryInParent()) { |
1352 | uri = mActiveEntry ? mActiveEntry->GetURI() : nullptr; |
1353 | } else if (mOSHE) { |
1354 | uri = mOSHE->GetURI(); |
1355 | } |
1356 | } |
1357 | if (!uri) { |
1358 | uri = doc->GetDocumentURI(); |
1359 | } |
1360 | SetCurrentURI(uri, channel, |
1361 | /* aFireOnLocationChange */ true, |
1362 | /* aIsInitialAboutBlank */ false, |
1363 | /* aLocationFlags */ 0); |
1364 | mLoadGroup->RemoveRequest(channel, nullptr, NS_OK); |
1365 | mIsRestoringDocument = false; |
1366 | } |
1367 | RefPtr<PresShell> presShell = GetPresShell(); |
1368 | if (presShell) { |
1369 | presShell->Thaw(false); |
1370 | } |
1371 | |
1372 | if (inner) { |
1373 | inner->FireDelayedDOMEvents(false); |
1374 | } |
1375 | } |
1376 | } else if (!mFiredUnloadEvent) { |
1377 | // XXXBFCache check again that the page can enter bfcache. |
1378 | // XXXBFCache should mTiming->NotifyUnloadEventStart()/End() be called here? |
1379 | |
1380 | if (mRefreshURIList) { |
1381 | RefreshURIToQueue(); |
1382 | mBFCachedRefreshURIList = std::move(mRefreshURIList); |
1383 | } else { |
1384 | // If Stop was called, the list was moved to mSavedRefreshURIList after |
1385 | // calling SuspendRefreshURIs, which calls RefreshURIToQueue. |
1386 | mBFCachedRefreshURIList = std::move(mSavedRefreshURIList); |
1387 | } |
1388 | |
1389 | mFiredUnloadEvent = true; |
1390 | viewer->PageHide(false); |
1391 | |
1392 | RefPtr<PresShell> presShell = GetPresShell(); |
1393 | if (presShell) { |
1394 | presShell->Freeze(false); |
1395 | } |
1396 | } |
1397 | } |
1398 | |
1399 | nsresult nsDocShell::Dispatch(already_AddRefed<nsIRunnable>&& aRunnable) { |
1400 | nsCOMPtr<nsIRunnable> runnable(aRunnable); |
1401 | if (NS_WARN_IF(!GetWindow())NS_warn_if_impl(!GetWindow(), "!GetWindow()", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 1401)) { |
1402 | // Window should only be unavailable after destroyed. |
1403 | MOZ_ASSERT(mIsBeingDestroyed)do { static_assert( mozilla::detail::AssertionConditionType< decltype(mIsBeingDestroyed)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mIsBeingDestroyed))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mIsBeingDestroyed" , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 1403); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "mIsBeingDestroyed" ")"); do { MOZ_CrashSequence (__null, 1403); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); |
1404 | return NS_ERROR_FAILURE; |
1405 | } |
1406 | return SchedulerGroup::Dispatch(runnable.forget()); |
1407 | } |
1408 | |
1409 | NS_IMETHODIMPnsresult |
1410 | nsDocShell::DispatchLocationChangeEvent() { |
1411 | return Dispatch(NewRunnableMethod("nsDocShell::FireDummyOnLocationChange", |
1412 | this, |
1413 | &nsDocShell::FireDummyOnLocationChange)); |
1414 | } |
1415 | |
1416 | NS_IMETHODIMPnsresult |
1417 | nsDocShell::StartDelayedAutoplayMediaComponents() { |
1418 | RefPtr<nsPIDOMWindowOuter> outerWindow = GetWindow(); |
1419 | if (outerWindow) { |
1420 | outerWindow->ActivateMediaComponents(); |
1421 | } |
1422 | return NS_OK; |
1423 | } |
1424 | |
1425 | bool nsDocShell::MaybeInitTiming() { |
1426 | if (mTiming && !mBlankTiming) { |
1427 | return false; |
1428 | } |
1429 | |
1430 | bool canBeReset = false; |
1431 | |
1432 | if (mScriptGlobal && mBlankTiming) { |
1433 | nsPIDOMWindowInner* innerWin = mScriptGlobal->GetCurrentInnerWindow(); |
1434 | if (innerWin && innerWin->GetPerformance()) { |
1435 | mTiming = innerWin->GetPerformance()->GetDOMTiming(); |
1436 | mBlankTiming = false; |
1437 | } |
1438 | } |
1439 | |
1440 | if (!mTiming) { |
1441 | mTiming = new nsDOMNavigationTiming(this); |
1442 | canBeReset = true; |
1443 | } |
1444 | |
1445 | mTiming->NotifyNavigationStart( |
1446 | mBrowsingContext->IsActive() |
1447 | ? nsDOMNavigationTiming::DocShellState::eActive |
1448 | : nsDOMNavigationTiming::DocShellState::eInactive); |
1449 | |
1450 | return canBeReset; |
1451 | } |
1452 | |
1453 | void nsDocShell::MaybeResetInitTiming(bool aReset) { |
1454 | if (aReset) { |
1455 | mTiming = nullptr; |
1456 | } |
1457 | } |
1458 | |
1459 | nsDOMNavigationTiming* nsDocShell::GetNavigationTiming() const { |
1460 | return mTiming; |
1461 | } |
1462 | |
1463 | nsPresContext* nsDocShell::GetEldestPresContext() { |
1464 | nsIDocumentViewer* viewer = mDocumentViewer; |
1465 | while (viewer) { |
1466 | nsIDocumentViewer* prevViewer = viewer->GetPreviousViewer(); |
1467 | if (!prevViewer) { |
1468 | return viewer->GetPresContext(); |
1469 | } |
1470 | viewer = prevViewer; |
1471 | } |
1472 | |
1473 | return nullptr; |
1474 | } |
1475 | |
1476 | nsPresContext* nsDocShell::GetPresContext() { |
1477 | if (!mDocumentViewer) { |
1478 | return nullptr; |
1479 | } |
1480 | |
1481 | return mDocumentViewer->GetPresContext(); |
1482 | } |
1483 | |
1484 | PresShell* nsDocShell::GetPresShell() { |
1485 | nsPresContext* presContext = GetPresContext(); |
1486 | return presContext ? presContext->GetPresShell() : nullptr; |
1487 | } |
1488 | |
1489 | PresShell* nsDocShell::GetEldestPresShell() { |
1490 | nsPresContext* presContext = GetEldestPresContext(); |
1491 | |
1492 | if (presContext) { |
1493 | return presContext->GetPresShell(); |
1494 | } |
1495 | |
1496 | return nullptr; |
1497 | } |
1498 | |
1499 | NS_IMETHODIMPnsresult |
1500 | nsDocShell::GetDocViewer(nsIDocumentViewer** aDocumentViewer) { |
1501 | NS_ENSURE_ARG_POINTER(aDocumentViewer)do { if ((__builtin_expect(!!(!(aDocumentViewer)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aDocumentViewer" ") failed" , nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 1501); return NS_ERROR_INVALID_POINTER; } } while (false); |
1502 | |
1503 | *aDocumentViewer = mDocumentViewer; |
1504 | NS_IF_ADDREF(*aDocumentViewer)ns_if_addref(*aDocumentViewer); |
1505 | return NS_OK; |
1506 | } |
1507 | |
1508 | NS_IMETHODIMPnsresult |
1509 | nsDocShell::GetOuterWindowID(uint64_t* aWindowID) { |
1510 | *aWindowID = mContentWindowID; |
1511 | return NS_OK; |
1512 | } |
1513 | |
1514 | NS_IMETHODIMPnsresult |
1515 | nsDocShell::SetChromeEventHandler(EventTarget* aChromeEventHandler) { |
1516 | mChromeEventHandler = aChromeEventHandler; |
1517 | |
1518 | if (mScriptGlobal) { |
1519 | mScriptGlobal->SetChromeEventHandler(mChromeEventHandler); |
1520 | } |
1521 | |
1522 | return NS_OK; |
1523 | } |
1524 | |
1525 | NS_IMETHODIMPnsresult |
1526 | nsDocShell::GetChromeEventHandler(EventTarget** aChromeEventHandler) { |
1527 | NS_ENSURE_ARG_POINTER(aChromeEventHandler)do { if ((__builtin_expect(!!(!(aChromeEventHandler)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aChromeEventHandler" ") failed", nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 1527); return NS_ERROR_INVALID_POINTER; } } while (false); |
1528 | RefPtr<EventTarget> handler = mChromeEventHandler; |
1529 | handler.forget(aChromeEventHandler); |
1530 | return NS_OK; |
1531 | } |
1532 | |
1533 | NS_IMETHODIMPnsresult |
1534 | nsDocShell::SetCurrentURIForSessionStore(nsIURI* aURI) { |
1535 | // Note that securityUI will set STATE_IS_INSECURE, even if |
1536 | // the scheme of |aURI| is "https". |
1537 | SetCurrentURI(aURI, nullptr, |
1538 | /* aFireOnLocationChange */ |
1539 | true, |
1540 | /* aIsInitialAboutBlank */ |
1541 | false, |
1542 | /* aLocationFlags */ |
1543 | nsIWebProgressListener::LOCATION_CHANGE_SESSION_STORE); |
1544 | return NS_OK; |
1545 | } |
1546 | |
1547 | bool nsDocShell::SetCurrentURI(nsIURI* aURI, nsIRequest* aRequest, |
1548 | bool aFireOnLocationChange, |
1549 | bool aIsInitialAboutBlank, |
1550 | uint32_t aLocationFlags) { |
1551 | MOZ_ASSERT(!mIsBeingDestroyed)do { static_assert( mozilla::detail::AssertionConditionType< decltype(!mIsBeingDestroyed)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!mIsBeingDestroyed))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!mIsBeingDestroyed" , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 1551); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "!mIsBeingDestroyed" ")"); do { MOZ_CrashSequence (__null, 1551); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); |
1552 | |
1553 | MOZ_LOG(gDocShellLeakLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gDocShellLeakLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "DOCSHELL %p SetCurrentURI %s\n", this, aURI ? aURI->GetSpecOrDefault().get() : ""); } } while (0) |
1554 | ("DOCSHELL %p SetCurrentURI %s\n", this,do { const ::mozilla::LogModule* moz_real_module = gDocShellLeakLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "DOCSHELL %p SetCurrentURI %s\n", this, aURI ? aURI->GetSpecOrDefault().get() : ""); } } while (0) |
1555 | aURI ? aURI->GetSpecOrDefault().get() : ""))do { const ::mozilla::LogModule* moz_real_module = gDocShellLeakLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "DOCSHELL %p SetCurrentURI %s\n", this, aURI ? aURI->GetSpecOrDefault().get() : ""); } } while (0); |
1556 | |
1557 | // We don't want to send a location change when we're displaying an error |
1558 | // page, and we don't want to change our idea of "current URI" either |
1559 | if (mLoadType == LOAD_ERROR_PAGE) { |
1560 | return false; |
1561 | } |
1562 | |
1563 | bool uriIsEqual = false; |
1564 | if (!mCurrentURI || !aURI || |
1565 | NS_FAILED(mCurrentURI->Equals(aURI, &uriIsEqual))((bool)(__builtin_expect(!!(NS_FAILED_impl(mCurrentURI->Equals (aURI, &uriIsEqual))), 0))) || !uriIsEqual) { |
1566 | mTitleValidForCurrentURI = false; |
1567 | } |
1568 | |
1569 | SetCurrentURIInternal(aURI); |
1570 | |
1571 | #ifdef DEBUG1 |
1572 | mLastOpenedURI = aURI; |
1573 | #endif |
1574 | |
1575 | if (!NS_IsAboutBlank(mCurrentURI)) { |
1576 | mHasLoadedNonBlankURI = true; |
1577 | } |
1578 | |
1579 | // Don't fire onLocationChange when creating a subframe's initial about:blank |
1580 | // document, as this can happen when it's not safe for us to run script. |
1581 | if (aIsInitialAboutBlank && !mHasLoadedNonBlankURI && |
1582 | !mBrowsingContext->IsTop()) { |
1583 | MOZ_ASSERT(!aRequest && aLocationFlags == 0)do { static_assert( mozilla::detail::AssertionConditionType< decltype(!aRequest && aLocationFlags == 0)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(!aRequest && aLocationFlags == 0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!aRequest && aLocationFlags == 0" , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 1583); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "!aRequest && aLocationFlags == 0" ")" ); do { MOZ_CrashSequence(__null, 1583); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1584 | return false; |
1585 | } |
1586 | |
1587 | MOZ_ASSERT(nsContentUtils::IsSafeToRunScript())do { static_assert( mozilla::detail::AssertionConditionType< decltype(nsContentUtils::IsSafeToRunScript())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(nsContentUtils::IsSafeToRunScript ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("nsContentUtils::IsSafeToRunScript()", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 1587); AnnotateMozCrashReason("MOZ_ASSERT" "(" "nsContentUtils::IsSafeToRunScript()" ")"); do { MOZ_CrashSequence(__null, 1587); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1588 | |
1589 | if (aFireOnLocationChange) { |
1590 | FireOnLocationChange(this, aRequest, aURI, aLocationFlags); |
1591 | } |
1592 | return !aFireOnLocationChange; |
1593 | } |
1594 | |
1595 | void nsDocShell::SetCurrentURIInternal(nsIURI* aURI) { |
1596 | mCurrentURI = aURI; |
1597 | if (mBrowsingContext) { |
1598 | mBrowsingContext->ClearCachedValuesOfLocations(); |
1599 | } |
1600 | } |
1601 | |
1602 | NS_IMETHODIMPnsresult |
1603 | nsDocShell::GetCharset(nsACString& aCharset) { |
1604 | aCharset.Truncate(); |
1605 | |
1606 | PresShell* presShell = GetPresShell(); |
1607 | NS_ENSURE_TRUE(presShell, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(presShell)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "presShell" ") failed", nullptr , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 1607); return NS_ERROR_FAILURE; } } while (false); |
1608 | Document* doc = presShell->GetDocument(); |
1609 | NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(doc)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING , "NS_ENSURE_TRUE(" "doc" ") failed", nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 1609); return NS_ERROR_FAILURE; } } while (false); |
1610 | doc->GetDocumentCharacterSet()->Name(aCharset); |
1611 | return NS_OK; |
1612 | } |
1613 | |
1614 | NS_IMETHODIMPnsresult |
1615 | nsDocShell::ForceEncodingDetection() { |
1616 | nsCOMPtr<nsIDocumentViewer> viewer; |
1617 | GetDocViewer(getter_AddRefs(viewer)); |
1618 | if (!viewer) { |
1619 | return NS_OK; |
1620 | } |
1621 | |
1622 | Document* doc = viewer->GetDocument(); |
1623 | if (!doc || doc->WillIgnoreCharsetOverride()) { |
1624 | return NS_OK; |
1625 | } |
1626 | |
1627 | mForcedAutodetection = true; |
1628 | |
1629 | nsIURI* uri = doc->GetOriginalURI(); |
1630 | bool isFileURL = uri && uri->SchemeIs("file"); |
1631 | |
1632 | int32_t charsetSource = doc->GetDocumentCharacterSetSource(); |
1633 | auto encoding = doc->GetDocumentCharacterSet(); |
1634 | // AsHTMLDocument is valid, because we called |
1635 | // WillIgnoreCharsetOverride() above. |
1636 | if (doc->AsHTMLDocument()->IsPlainText()) { |
1637 | switch (charsetSource) { |
1638 | case kCharsetFromInitialAutoDetectionASCII: |
1639 | // Deliberately no final version |
1640 | LOGCHARSETMENU(("TEXT:UnlabeledAscii"))do { const ::mozilla::LogModule* moz_real_module = gCharsetMenuLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print (moz_real_module, mozilla::LogLevel::Debug, "TEXT:UnlabeledAscii" ); } } while (0); |
1641 | break; |
1642 | case kCharsetFromInitialAutoDetectionWouldNotHaveBeenUTF8Generic: |
1643 | case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8Generic: |
1644 | case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8GenericInitialWasASCII: |
1645 | case kCharsetFromInitialAutoDetectionWouldNotHaveBeenUTF8Content: |
1646 | case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8Content: |
1647 | case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8ContentInitialWasASCII: |
1648 | LOGCHARSETMENU(("TEXT:UnlabeledNonUtf8"))do { const ::mozilla::LogModule* moz_real_module = gCharsetMenuLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print (moz_real_module, mozilla::LogLevel::Debug, "TEXT:UnlabeledNonUtf8" ); } } while (0); |
1649 | break; |
1650 | case kCharsetFromInitialAutoDetectionWouldNotHaveBeenUTF8DependedOnTLD: |
1651 | case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8DependedOnTLD: |
1652 | case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8DependedOnTLDInitialWasASCII: |
1653 | LOGCHARSETMENU(("TEXT:UnlabeledNonUtf8TLD"))do { const ::mozilla::LogModule* moz_real_module = gCharsetMenuLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print (moz_real_module, mozilla::LogLevel::Debug, "TEXT:UnlabeledNonUtf8TLD" ); } } while (0); |
1654 | break; |
1655 | case kCharsetFromInitialAutoDetectionWouldHaveBeenUTF8: |
1656 | case kCharsetFromFinalAutoDetectionWouldHaveBeenUTF8InitialWasASCII: |
1657 | LOGCHARSETMENU(("TEXT:UnlabeledUtf8"))do { const ::mozilla::LogModule* moz_real_module = gCharsetMenuLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print (moz_real_module, mozilla::LogLevel::Debug, "TEXT:UnlabeledUtf8" ); } } while (0); |
1658 | break; |
1659 | case kCharsetFromChannel: |
1660 | if (encoding == UTF_8_ENCODING) { |
1661 | LOGCHARSETMENU(("TEXT:ChannelUtf8"))do { const ::mozilla::LogModule* moz_real_module = gCharsetMenuLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print (moz_real_module, mozilla::LogLevel::Debug, "TEXT:ChannelUtf8" ); } } while (0); |
1662 | } else { |
1663 | LOGCHARSETMENU(("TEXT:ChannelNonUtf8"))do { const ::mozilla::LogModule* moz_real_module = gCharsetMenuLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print (moz_real_module, mozilla::LogLevel::Debug, "TEXT:ChannelNonUtf8" ); } } while (0); |
1664 | } |
1665 | break; |
1666 | default: |
1667 | LOGCHARSETMENU(("TEXT:Bug"))do { const ::mozilla::LogModule* moz_real_module = gCharsetMenuLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print (moz_real_module, mozilla::LogLevel::Debug, "TEXT:Bug"); } } while (0); |
1668 | break; |
1669 | } |
1670 | } else { |
1671 | switch (charsetSource) { |
1672 | case kCharsetFromInitialAutoDetectionASCII: |
1673 | // Deliberately no final version |
1674 | LOGCHARSETMENU(("HTML:UnlabeledAscii"))do { const ::mozilla::LogModule* moz_real_module = gCharsetMenuLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print (moz_real_module, mozilla::LogLevel::Debug, "HTML:UnlabeledAscii" ); } } while (0); |
1675 | break; |
1676 | case kCharsetFromInitialAutoDetectionWouldNotHaveBeenUTF8Generic: |
1677 | case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8Generic: |
1678 | case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8GenericInitialWasASCII: |
1679 | case kCharsetFromInitialAutoDetectionWouldNotHaveBeenUTF8Content: |
1680 | case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8Content: |
1681 | case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8ContentInitialWasASCII: |
1682 | LOGCHARSETMENU(("HTML:UnlabeledNonUtf8"))do { const ::mozilla::LogModule* moz_real_module = gCharsetMenuLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print (moz_real_module, mozilla::LogLevel::Debug, "HTML:UnlabeledNonUtf8" ); } } while (0); |
1683 | break; |
1684 | case kCharsetFromInitialAutoDetectionWouldNotHaveBeenUTF8DependedOnTLD: |
1685 | case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8DependedOnTLD: |
1686 | case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8DependedOnTLDInitialWasASCII: |
1687 | LOGCHARSETMENU(("HTML:UnlabeledNonUtf8TLD"))do { const ::mozilla::LogModule* moz_real_module = gCharsetMenuLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print (moz_real_module, mozilla::LogLevel::Debug, "HTML:UnlabeledNonUtf8TLD" ); } } while (0); |
1688 | break; |
1689 | case kCharsetFromInitialAutoDetectionWouldHaveBeenUTF8: |
1690 | case kCharsetFromFinalAutoDetectionWouldHaveBeenUTF8InitialWasASCII: |
1691 | LOGCHARSETMENU(("HTML:UnlabeledUtf8"))do { const ::mozilla::LogModule* moz_real_module = gCharsetMenuLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print (moz_real_module, mozilla::LogLevel::Debug, "HTML:UnlabeledUtf8" ); } } while (0); |
1692 | break; |
1693 | case kCharsetFromChannel: |
1694 | if (encoding == UTF_8_ENCODING) { |
1695 | LOGCHARSETMENU(("HTML:ChannelUtf8"))do { const ::mozilla::LogModule* moz_real_module = gCharsetMenuLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print (moz_real_module, mozilla::LogLevel::Debug, "HTML:ChannelUtf8" ); } } while (0); |
1696 | } else { |
1697 | LOGCHARSETMENU(("HTML:ChannelNonUtf8"))do { const ::mozilla::LogModule* moz_real_module = gCharsetMenuLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print (moz_real_module, mozilla::LogLevel::Debug, "HTML:ChannelNonUtf8" ); } } while (0); |
1698 | } |
1699 | break; |
1700 | case kCharsetFromXmlDeclaration: |
1701 | case kCharsetFromMetaTag: |
1702 | if (isFileURL) { |
1703 | LOGCHARSETMENU(("HTML:LocalLabeled"))do { const ::mozilla::LogModule* moz_real_module = gCharsetMenuLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print (moz_real_module, mozilla::LogLevel::Debug, "HTML:LocalLabeled" ); } } while (0); |
1704 | } else if (encoding == UTF_8_ENCODING) { |
1705 | LOGCHARSETMENU(("HTML:MetaUtf8"))do { const ::mozilla::LogModule* moz_real_module = gCharsetMenuLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print (moz_real_module, mozilla::LogLevel::Debug, "HTML:MetaUtf8"); } } while (0); |
1706 | } else { |
1707 | LOGCHARSETMENU(("HTML:MetaNonUtf8"))do { const ::mozilla::LogModule* moz_real_module = gCharsetMenuLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print (moz_real_module, mozilla::LogLevel::Debug, "HTML:MetaNonUtf8" ); } } while (0); |
1708 | } |
1709 | break; |
1710 | default: |
1711 | LOGCHARSETMENU(("HTML:Bug"))do { const ::mozilla::LogModule* moz_real_module = gCharsetMenuLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print (moz_real_module, mozilla::LogLevel::Debug, "HTML:Bug"); } } while (0); |
1712 | break; |
1713 | } |
1714 | } |
1715 | return NS_OK; |
1716 | } |
1717 | |
1718 | void nsDocShell::SetParentCharset(const Encoding*& aCharset, |
1719 | int32_t aCharsetSource, |
1720 | nsIPrincipal* aPrincipal) { |
1721 | mParentCharset = aCharset; |
1722 | mParentCharsetSource = aCharsetSource; |
1723 | mParentCharsetPrincipal = aPrincipal; |
1724 | } |
1725 | |
1726 | void nsDocShell::GetParentCharset(const Encoding*& aCharset, |
1727 | int32_t* aCharsetSource, |
1728 | nsIPrincipal** aPrincipal) { |
1729 | aCharset = mParentCharset; |
1730 | *aCharsetSource = mParentCharsetSource; |
1731 | NS_IF_ADDREF(*aPrincipal = mParentCharsetPrincipal)ns_if_addref(*aPrincipal = mParentCharsetPrincipal); |
1732 | } |
1733 | |
1734 | NS_IMETHODIMPnsresult |
1735 | nsDocShell::GetHasTrackingContentBlocked(Promise** aPromise) { |
1736 | MOZ_ASSERT(aPromise)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aPromise)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aPromise))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aPromise", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 1736); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPromise" ")" ); do { MOZ_CrashSequence(__null, 1736); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1737 | |
1738 | ErrorResult rv; |
1739 | RefPtr<Document> doc(GetDocument()); |
1740 | RefPtr<Promise> retPromise = Promise::Create(doc->GetOwnerGlobal(), rv); |
1741 | if (NS_WARN_IF(rv.Failed())NS_warn_if_impl(rv.Failed(), "rv.Failed()", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 1741)) { |
1742 | return rv.StealNSResult(); |
1743 | } |
1744 | |
1745 | // Retrieve the document's content blocking events from the parent process. |
1746 | RefPtr<Document::GetContentBlockingEventsPromise> promise = |
1747 | doc->GetContentBlockingEvents(); |
1748 | if (promise) { |
1749 | promise->Then( |
1750 | GetCurrentSerialEventTarget(), __func__, |
1751 | [retPromise](const Document::GetContentBlockingEventsPromise:: |
1752 | ResolveOrRejectValue& aValue) { |
1753 | if (aValue.IsResolve()) { |
1754 | bool has = aValue.ResolveValue() & |
1755 | nsIWebProgressListener::STATE_BLOCKED_TRACKING_CONTENT; |
1756 | retPromise->MaybeResolve(has); |
1757 | } else { |
1758 | retPromise->MaybeResolve(false); |
1759 | } |
1760 | }); |
1761 | } else { |
1762 | retPromise->MaybeResolve(false); |
1763 | } |
1764 | |
1765 | retPromise.forget(aPromise); |
1766 | return NS_OK; |
1767 | } |
1768 | |
1769 | NS_IMETHODIMPnsresult |
1770 | nsDocShell::GetCssErrorReportingEnabled(bool* aEnabled) { |
1771 | MOZ_ASSERT(aEnabled)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aEnabled)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aEnabled))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aEnabled", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 1771); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aEnabled" ")" ); do { MOZ_CrashSequence(__null, 1771); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1772 | *aEnabled = mCSSErrorReportingEnabled; |
1773 | return NS_OK; |
1774 | } |
1775 | |
1776 | NS_IMETHODIMPnsresult |
1777 | nsDocShell::SetCssErrorReportingEnabled(bool aEnabled) { |
1778 | mCSSErrorReportingEnabled = aEnabled; |
1779 | return NS_OK; |
1780 | } |
1781 | |
1782 | NS_IMETHODIMPnsresult |
1783 | nsDocShell::GetUsePrivateBrowsing(bool* aUsePrivateBrowsing) { |
1784 | NS_ENSURE_ARG_POINTER(aUsePrivateBrowsing)do { if ((__builtin_expect(!!(!(aUsePrivateBrowsing)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aUsePrivateBrowsing" ") failed", nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 1784); return NS_ERROR_INVALID_POINTER; } } while (false); |
1785 | return mBrowsingContext->GetUsePrivateBrowsing(aUsePrivateBrowsing); |
1786 | } |
1787 | |
1788 | void nsDocShell::NotifyPrivateBrowsingChanged() { |
1789 | MOZ_ASSERT(!mIsBeingDestroyed)do { static_assert( mozilla::detail::AssertionConditionType< decltype(!mIsBeingDestroyed)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!mIsBeingDestroyed))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!mIsBeingDestroyed" , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 1789); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "!mIsBeingDestroyed" ")"); do { MOZ_CrashSequence (__null, 1789); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); |
1790 | |
1791 | nsTObserverArray<nsWeakPtr>::ForwardIterator iter(mPrivacyObservers); |
1792 | while (iter.HasMore()) { |
1793 | nsWeakPtr ref = iter.GetNext(); |
1794 | nsCOMPtr<nsIPrivacyTransitionObserver> obs = do_QueryReferent(ref); |
1795 | if (!obs) { |
1796 | iter.Remove(); |
1797 | } else { |
1798 | obs->PrivateModeChanged(UsePrivateBrowsing()); |
1799 | } |
1800 | } |
1801 | } |
1802 | |
1803 | NS_IMETHODIMPnsresult |
1804 | nsDocShell::SetUsePrivateBrowsing(bool aUsePrivateBrowsing) { |
1805 | return mBrowsingContext->SetUsePrivateBrowsing(aUsePrivateBrowsing); |
1806 | } |
1807 | |
1808 | NS_IMETHODIMPnsresult |
1809 | nsDocShell::SetPrivateBrowsing(bool aUsePrivateBrowsing) { |
1810 | return mBrowsingContext->SetPrivateBrowsing(aUsePrivateBrowsing); |
1811 | } |
1812 | |
1813 | NS_IMETHODIMPnsresult |
1814 | nsDocShell::GetHasLoadedNonBlankURI(bool* aResult) { |
1815 | NS_ENSURE_ARG_POINTER(aResult)do { if ((__builtin_expect(!!(!(aResult)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aResult" ") failed", nullptr , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 1815); return NS_ERROR_INVALID_POINTER; } } while (false); |
1816 | |
1817 | *aResult = mHasLoadedNonBlankURI; |
1818 | return NS_OK; |
1819 | } |
1820 | |
1821 | NS_IMETHODIMPnsresult |
1822 | nsDocShell::GetUseRemoteTabs(bool* aUseRemoteTabs) { |
1823 | NS_ENSURE_ARG_POINTER(aUseRemoteTabs)do { if ((__builtin_expect(!!(!(aUseRemoteTabs)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aUseRemoteTabs" ") failed" , nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 1823); return NS_ERROR_INVALID_POINTER; } } while (false); |
1824 | return mBrowsingContext->GetUseRemoteTabs(aUseRemoteTabs); |
1825 | } |
1826 | |
1827 | NS_IMETHODIMPnsresult |
1828 | nsDocShell::SetRemoteTabs(bool aUseRemoteTabs) { |
1829 | return mBrowsingContext->SetRemoteTabs(aUseRemoteTabs); |
1830 | } |
1831 | |
1832 | NS_IMETHODIMPnsresult |
1833 | nsDocShell::GetUseRemoteSubframes(bool* aUseRemoteSubframes) { |
1834 | NS_ENSURE_ARG_POINTER(aUseRemoteSubframes)do { if ((__builtin_expect(!!(!(aUseRemoteSubframes)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aUseRemoteSubframes" ") failed", nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 1834); return NS_ERROR_INVALID_POINTER; } } while (false); |
1835 | return mBrowsingContext->GetUseRemoteSubframes(aUseRemoteSubframes); |
1836 | } |
1837 | |
1838 | NS_IMETHODIMPnsresult |
1839 | nsDocShell::SetRemoteSubframes(bool aUseRemoteSubframes) { |
1840 | return mBrowsingContext->SetRemoteSubframes(aUseRemoteSubframes); |
1841 | } |
1842 | |
1843 | NS_IMETHODIMPnsresult |
1844 | nsDocShell::AddWeakPrivacyTransitionObserver( |
1845 | nsIPrivacyTransitionObserver* aObserver) { |
1846 | nsWeakPtr weakObs = do_GetWeakReference(aObserver); |
1847 | if (!weakObs) { |
1848 | return NS_ERROR_NOT_AVAILABLE; |
1849 | } |
1850 | mPrivacyObservers.AppendElement(weakObs); |
1851 | return NS_OK; |
1852 | } |
1853 | |
1854 | NS_IMETHODIMPnsresult |
1855 | nsDocShell::AddWeakReflowObserver(nsIReflowObserver* aObserver) { |
1856 | nsWeakPtr weakObs = do_GetWeakReference(aObserver); |
1857 | if (!weakObs) { |
1858 | return NS_ERROR_FAILURE; |
1859 | } |
1860 | mReflowObservers.AppendElement(weakObs); |
1861 | return NS_OK; |
1862 | } |
1863 | |
1864 | NS_IMETHODIMPnsresult |
1865 | nsDocShell::RemoveWeakReflowObserver(nsIReflowObserver* aObserver) { |
1866 | nsWeakPtr obs = do_GetWeakReference(aObserver); |
1867 | return mReflowObservers.RemoveElement(obs) ? NS_OK : NS_ERROR_FAILURE; |
1868 | } |
1869 | |
1870 | NS_IMETHODIMPnsresult |
1871 | nsDocShell::NotifyReflowObservers(bool aInterruptible, |
1872 | DOMHighResTimeStamp aStart, |
1873 | DOMHighResTimeStamp aEnd) { |
1874 | nsTObserverArray<nsWeakPtr>::ForwardIterator iter(mReflowObservers); |
1875 | while (iter.HasMore()) { |
1876 | nsWeakPtr ref = iter.GetNext(); |
1877 | nsCOMPtr<nsIReflowObserver> obs = do_QueryReferent(ref); |
1878 | if (!obs) { |
1879 | iter.Remove(); |
1880 | } else if (aInterruptible) { |
1881 | obs->ReflowInterruptible(aStart, aEnd); |
1882 | } else { |
1883 | obs->Reflow(aStart, aEnd); |
1884 | } |
1885 | } |
1886 | return NS_OK; |
1887 | } |
1888 | |
1889 | NS_IMETHODIMPnsresult |
1890 | nsDocShell::GetAllowMetaRedirects(bool* aReturn) { |
1891 | NS_ENSURE_ARG_POINTER(aReturn)do { if ((__builtin_expect(!!(!(aReturn)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aReturn" ") failed", nullptr , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 1891); return NS_ERROR_INVALID_POINTER; } } while (false); |
1892 | |
1893 | *aReturn = mAllowMetaRedirects; |
1894 | return NS_OK; |
1895 | } |
1896 | |
1897 | NS_IMETHODIMPnsresult |
1898 | nsDocShell::SetAllowMetaRedirects(bool aValue) { |
1899 | mAllowMetaRedirects = aValue; |
1900 | return NS_OK; |
1901 | } |
1902 | |
1903 | NS_IMETHODIMPnsresult |
1904 | nsDocShell::GetAllowSubframes(bool* aAllowSubframes) { |
1905 | NS_ENSURE_ARG_POINTER(aAllowSubframes)do { if ((__builtin_expect(!!(!(aAllowSubframes)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aAllowSubframes" ") failed" , nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 1905); return NS_ERROR_INVALID_POINTER; } } while (false); |
1906 | |
1907 | *aAllowSubframes = mAllowSubframes; |
1908 | return NS_OK; |
1909 | } |
1910 | |
1911 | NS_IMETHODIMPnsresult |
1912 | nsDocShell::SetAllowSubframes(bool aAllowSubframes) { |
1913 | mAllowSubframes = aAllowSubframes; |
1914 | return NS_OK; |
1915 | } |
1916 | |
1917 | NS_IMETHODIMPnsresult |
1918 | nsDocShell::GetAllowImages(bool* aAllowImages) { |
1919 | NS_ENSURE_ARG_POINTER(aAllowImages)do { if ((__builtin_expect(!!(!(aAllowImages)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aAllowImages" ") failed" , nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 1919); return NS_ERROR_INVALID_POINTER; } } while (false); |
1920 | |
1921 | *aAllowImages = mAllowImages; |
1922 | return NS_OK; |
1923 | } |
1924 | |
1925 | NS_IMETHODIMPnsresult |
1926 | nsDocShell::SetAllowImages(bool aAllowImages) { |
1927 | mAllowImages = aAllowImages; |
1928 | return NS_OK; |
1929 | } |
1930 | |
1931 | NS_IMETHODIMPnsresult |
1932 | nsDocShell::GetAllowMedia(bool* aAllowMedia) { |
1933 | *aAllowMedia = mAllowMedia; |
1934 | return NS_OK; |
1935 | } |
1936 | |
1937 | NS_IMETHODIMPnsresult |
1938 | nsDocShell::SetAllowMedia(bool aAllowMedia) { |
1939 | mAllowMedia = aAllowMedia; |
1940 | |
1941 | // Mute or unmute audio contexts attached to the inner window. |
1942 | if (mScriptGlobal) { |
1943 | if (nsPIDOMWindowInner* innerWin = mScriptGlobal->GetCurrentInnerWindow()) { |
1944 | if (aAllowMedia) { |
1945 | innerWin->UnmuteAudioContexts(); |
1946 | } else { |
1947 | innerWin->MuteAudioContexts(); |
1948 | } |
1949 | } |
1950 | } |
1951 | |
1952 | return NS_OK; |
1953 | } |
1954 | |
1955 | NS_IMETHODIMPnsresult |
1956 | nsDocShell::GetAllowDNSPrefetch(bool* aAllowDNSPrefetch) { |
1957 | *aAllowDNSPrefetch = mAllowDNSPrefetch; |
1958 | return NS_OK; |
1959 | } |
1960 | |
1961 | NS_IMETHODIMPnsresult |
1962 | nsDocShell::SetAllowDNSPrefetch(bool aAllowDNSPrefetch) { |
1963 | mAllowDNSPrefetch = aAllowDNSPrefetch; |
1964 | return NS_OK; |
1965 | } |
1966 | |
1967 | NS_IMETHODIMPnsresult |
1968 | nsDocShell::GetAllowWindowControl(bool* aAllowWindowControl) { |
1969 | *aAllowWindowControl = mAllowWindowControl; |
1970 | return NS_OK; |
1971 | } |
1972 | |
1973 | NS_IMETHODIMPnsresult |
1974 | nsDocShell::SetAllowWindowControl(bool aAllowWindowControl) { |
1975 | mAllowWindowControl = aAllowWindowControl; |
1976 | return NS_OK; |
1977 | } |
1978 | |
1979 | NS_IMETHODIMPnsresult |
1980 | nsDocShell::GetAllowContentRetargeting(bool* aAllowContentRetargeting) { |
1981 | *aAllowContentRetargeting = mBrowsingContext->GetAllowContentRetargeting(); |
1982 | return NS_OK; |
1983 | } |
1984 | |
1985 | NS_IMETHODIMPnsresult |
1986 | nsDocShell::SetAllowContentRetargeting(bool aAllowContentRetargeting) { |
1987 | BrowsingContext::Transaction txn; |
1988 | txn.SetAllowContentRetargeting(aAllowContentRetargeting); |
1989 | txn.SetAllowContentRetargetingOnChildren(aAllowContentRetargeting); |
1990 | return txn.Commit(mBrowsingContext); |
1991 | } |
1992 | |
1993 | NS_IMETHODIMPnsresult |
1994 | nsDocShell::GetAllowContentRetargetingOnChildren( |
1995 | bool* aAllowContentRetargetingOnChildren) { |
1996 | *aAllowContentRetargetingOnChildren = |
1997 | mBrowsingContext->GetAllowContentRetargetingOnChildren(); |
1998 | return NS_OK; |
1999 | } |
2000 | |
2001 | NS_IMETHODIMPnsresult |
2002 | nsDocShell::SetAllowContentRetargetingOnChildren( |
2003 | bool aAllowContentRetargetingOnChildren) { |
2004 | return mBrowsingContext->SetAllowContentRetargetingOnChildren( |
2005 | aAllowContentRetargetingOnChildren); |
2006 | } |
2007 | |
2008 | NS_IMETHODIMPnsresult |
2009 | nsDocShell::GetMayEnableCharacterEncodingMenu( |
2010 | bool* aMayEnableCharacterEncodingMenu) { |
2011 | *aMayEnableCharacterEncodingMenu = false; |
2012 | if (!mDocumentViewer) { |
2013 | return NS_OK; |
2014 | } |
2015 | Document* doc = mDocumentViewer->GetDocument(); |
2016 | if (!doc) { |
2017 | return NS_OK; |
2018 | } |
2019 | if (doc->WillIgnoreCharsetOverride()) { |
2020 | return NS_OK; |
2021 | } |
2022 | |
2023 | *aMayEnableCharacterEncodingMenu = true; |
2024 | return NS_OK; |
2025 | } |
2026 | |
2027 | NS_IMETHODIMPnsresult |
2028 | nsDocShell::GetAllDocShellsInSubtree(int32_t aItemType, |
2029 | DocShellEnumeratorDirection aDirection, |
2030 | nsTArray<RefPtr<nsIDocShell>>& aResult) { |
2031 | aResult.Clear(); |
2032 | |
2033 | nsDocShellEnumerator docShellEnum( |
2034 | (aDirection == ENUMERATE_FORWARDS) |
2035 | ? nsDocShellEnumerator::EnumerationDirection::Forwards |
2036 | : nsDocShellEnumerator::EnumerationDirection::Backwards, |
2037 | aItemType, *this); |
2038 | |
2039 | nsresult rv = docShellEnum.BuildDocShellArray(aResult); |
2040 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
2041 | return rv; |
2042 | } |
2043 | |
2044 | return NS_OK; |
2045 | } |
2046 | |
2047 | NS_IMETHODIMPnsresult |
2048 | nsDocShell::GetAppType(AppType* aAppType) { |
2049 | *aAppType = mAppType; |
2050 | return NS_OK; |
2051 | } |
2052 | |
2053 | NS_IMETHODIMPnsresult |
2054 | nsDocShell::SetAppType(AppType aAppType) { |
2055 | mAppType = aAppType; |
2056 | return NS_OK; |
2057 | } |
2058 | |
2059 | NS_IMETHODIMPnsresult |
2060 | nsDocShell::GetAllowAuth(bool* aAllowAuth) { |
2061 | *aAllowAuth = mAllowAuth; |
2062 | return NS_OK; |
2063 | } |
2064 | |
2065 | NS_IMETHODIMPnsresult |
2066 | nsDocShell::SetAllowAuth(bool aAllowAuth) { |
2067 | mAllowAuth = aAllowAuth; |
2068 | return NS_OK; |
2069 | } |
2070 | |
2071 | NS_IMETHODIMPnsresult |
2072 | nsDocShell::GetZoom(float* aZoom) { |
2073 | NS_ENSURE_ARG_POINTER(aZoom)do { if ((__builtin_expect(!!(!(aZoom)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aZoom" ") failed", nullptr , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 2073); return NS_ERROR_INVALID_POINTER; } } while (false); |
2074 | *aZoom = 1.0f; |
2075 | return NS_OK; |
2076 | } |
2077 | |
2078 | NS_IMETHODIMPnsresult |
2079 | nsDocShell::SetZoom(float aZoom) { return NS_ERROR_NOT_IMPLEMENTED; } |
2080 | |
2081 | NS_IMETHODIMPnsresult |
2082 | nsDocShell::GetBusyFlags(BusyFlags* aBusyFlags) { |
2083 | NS_ENSURE_ARG_POINTER(aBusyFlags)do { if ((__builtin_expect(!!(!(aBusyFlags)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aBusyFlags" ") failed", nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 2083); return NS_ERROR_INVALID_POINTER; } } while (false); |
2084 | |
2085 | *aBusyFlags = mBusyFlags; |
2086 | return NS_OK; |
2087 | } |
2088 | |
2089 | NS_IMETHODIMPnsresult |
2090 | nsDocShell::GetLoadURIDelegate(nsILoadURIDelegate** aLoadURIDelegate) { |
2091 | nsCOMPtr<nsILoadURIDelegate> delegate = GetLoadURIDelegate(); |
2092 | delegate.forget(aLoadURIDelegate); |
2093 | return NS_OK; |
2094 | } |
2095 | |
2096 | already_AddRefed<nsILoadURIDelegate> nsDocShell::GetLoadURIDelegate() { |
2097 | if (nsCOMPtr<nsILoadURIDelegate> result = |
2098 | do_QueryActor("LoadURIDelegate", GetDocument())) { |
2099 | return result.forget(); |
2100 | } |
2101 | |
2102 | return nullptr; |
2103 | } |
2104 | |
2105 | NS_IMETHODIMPnsresult |
2106 | nsDocShell::GetUseErrorPages(bool* aUseErrorPages) { |
2107 | *aUseErrorPages = mBrowsingContext->GetUseErrorPages(); |
2108 | return NS_OK; |
2109 | } |
2110 | |
2111 | NS_IMETHODIMPnsresult |
2112 | nsDocShell::SetUseErrorPages(bool aUseErrorPages) { |
2113 | return mBrowsingContext->SetUseErrorPages(aUseErrorPages); |
2114 | } |
2115 | |
2116 | NS_IMETHODIMPnsresult |
2117 | nsDocShell::GetPreviousEntryIndex(int32_t* aPreviousEntryIndex) { |
2118 | *aPreviousEntryIndex = mPreviousEntryIndex; |
2119 | return NS_OK; |
2120 | } |
2121 | |
2122 | NS_IMETHODIMPnsresult |
2123 | nsDocShell::GetLoadedEntryIndex(int32_t* aLoadedEntryIndex) { |
2124 | *aLoadedEntryIndex = mLoadedEntryIndex; |
2125 | return NS_OK; |
2126 | } |
2127 | |
2128 | NS_IMETHODIMPnsresult |
2129 | nsDocShell::HistoryPurged(int32_t aNumEntries) { |
2130 | // These indices are used for fastback cache eviction, to determine |
2131 | // which session history entries are candidates for content viewer |
2132 | // eviction. We need to adjust by the number of entries that we |
2133 | // just purged from history, so that we look at the right session history |
2134 | // entries during eviction. |
2135 | mPreviousEntryIndex = std::max(-1, mPreviousEntryIndex - aNumEntries); |
2136 | mLoadedEntryIndex = std::max(0, mLoadedEntryIndex - aNumEntries); |
2137 | |
2138 | for (auto* child : mChildList.ForwardRange()) { |
2139 | nsCOMPtr<nsIDocShell> shell = do_QueryObject(child); |
2140 | if (shell) { |
2141 | shell->HistoryPurged(aNumEntries); |
2142 | } |
2143 | } |
2144 | |
2145 | return NS_OK; |
2146 | } |
2147 | |
2148 | nsresult nsDocShell::HistoryEntryRemoved(int32_t aIndex) { |
2149 | // These indices are used for fastback cache eviction, to determine |
2150 | // which session history entries are candidates for content viewer |
2151 | // eviction. We need to adjust by the number of entries that we |
2152 | // just purged from history, so that we look at the right session history |
2153 | // entries during eviction. |
2154 | if (aIndex == mPreviousEntryIndex) { |
2155 | mPreviousEntryIndex = -1; |
2156 | } else if (aIndex < mPreviousEntryIndex) { |
2157 | --mPreviousEntryIndex; |
2158 | } |
2159 | if (mLoadedEntryIndex == aIndex) { |
2160 | mLoadedEntryIndex = 0; |
2161 | } else if (aIndex < mLoadedEntryIndex) { |
2162 | --mLoadedEntryIndex; |
2163 | } |
2164 | |
2165 | for (auto* child : mChildList.ForwardRange()) { |
2166 | nsCOMPtr<nsIDocShell> shell = do_QueryObject(child); |
2167 | if (shell) { |
2168 | static_cast<nsDocShell*>(shell.get())->HistoryEntryRemoved(aIndex); |
2169 | } |
2170 | } |
2171 | |
2172 | return NS_OK; |
2173 | } |
2174 | |
2175 | nsresult nsDocShell::Now(DOMHighResTimeStamp* aWhen) { |
2176 | *aWhen = (TimeStamp::Now() - TimeStamp::ProcessCreation()).ToMilliseconds(); |
2177 | return NS_OK; |
2178 | } |
2179 | |
2180 | NS_IMETHODIMPnsresult |
2181 | nsDocShell::SetWindowDraggingAllowed(bool aValue) { |
2182 | RefPtr<nsDocShell> parent; |
2183 | if (!aValue && mItemType == typeChrome && |
2184 | !(parent = GetInProcessParentDocshell())) { |
2185 | // Window dragging is always allowed for top level |
2186 | // chrome docshells. |
2187 | return NS_ERROR_FAILURE; |
2188 | } |
2189 | mWindowDraggingAllowed = aValue; |
2190 | return NS_OK; |
2191 | } |
2192 | |
2193 | NS_IMETHODIMPnsresult |
2194 | nsDocShell::GetWindowDraggingAllowed(bool* aValue) { |
2195 | // window dragging regions in CSS (-moz-window-drag:drag) |
2196 | // can be slow. Default behavior is to only allow it for |
2197 | // chrome top level windows. |
2198 | RefPtr<nsDocShell> parent; |
2199 | if (mItemType == typeChrome && !(parent = GetInProcessParentDocshell())) { |
2200 | // Top level chrome window |
2201 | *aValue = true; |
2202 | } else { |
2203 | *aValue = mWindowDraggingAllowed; |
2204 | } |
2205 | return NS_OK; |
2206 | } |
2207 | |
2208 | NS_IMETHODIMPnsresult |
2209 | nsDocShell::GetCurrentDocumentChannel(nsIChannel** aResult) { |
2210 | NS_IF_ADDREF(*aResult = GetCurrentDocChannel())ns_if_addref(*aResult = GetCurrentDocChannel()); |
2211 | return NS_OK; |
2212 | } |
2213 | |
2214 | nsIChannel* nsDocShell::GetCurrentDocChannel() { |
2215 | if (mDocumentViewer) { |
2216 | Document* doc = mDocumentViewer->GetDocument(); |
2217 | if (doc) { |
2218 | return doc->GetChannel(); |
2219 | } |
2220 | } |
2221 | return nullptr; |
2222 | } |
2223 | |
2224 | NS_IMETHODIMPnsresult |
2225 | nsDocShell::AddWeakScrollObserver(nsIScrollObserver* aObserver) { |
2226 | nsWeakPtr weakObs = do_GetWeakReference(aObserver); |
2227 | if (!weakObs) { |
2228 | return NS_ERROR_FAILURE; |
2229 | } |
2230 | mScrollObservers.AppendElement(weakObs); |
2231 | return NS_OK; |
2232 | } |
2233 | |
2234 | NS_IMETHODIMPnsresult |
2235 | nsDocShell::RemoveWeakScrollObserver(nsIScrollObserver* aObserver) { |
2236 | nsWeakPtr obs = do_GetWeakReference(aObserver); |
2237 | return mScrollObservers.RemoveElement(obs) ? NS_OK : NS_ERROR_FAILURE; |
2238 | } |
2239 | |
2240 | void nsDocShell::NotifyAsyncPanZoomStarted() { |
2241 | nsTObserverArray<nsWeakPtr>::ForwardIterator iter(mScrollObservers); |
2242 | while (iter.HasMore()) { |
2243 | nsWeakPtr ref = iter.GetNext(); |
2244 | nsCOMPtr<nsIScrollObserver> obs = do_QueryReferent(ref); |
2245 | if (obs) { |
2246 | obs->AsyncPanZoomStarted(); |
2247 | } else { |
2248 | iter.Remove(); |
2249 | } |
2250 | } |
2251 | } |
2252 | |
2253 | void nsDocShell::NotifyAsyncPanZoomStopped() { |
2254 | nsTObserverArray<nsWeakPtr>::ForwardIterator iter(mScrollObservers); |
2255 | while (iter.HasMore()) { |
2256 | nsWeakPtr ref = iter.GetNext(); |
2257 | nsCOMPtr<nsIScrollObserver> obs = do_QueryReferent(ref); |
2258 | if (obs) { |
2259 | obs->AsyncPanZoomStopped(); |
2260 | } else { |
2261 | iter.Remove(); |
2262 | } |
2263 | } |
2264 | } |
2265 | |
2266 | NS_IMETHODIMPnsresult |
2267 | nsDocShell::NotifyScrollObservers() { |
2268 | nsTObserverArray<nsWeakPtr>::ForwardIterator iter(mScrollObservers); |
2269 | while (iter.HasMore()) { |
2270 | nsWeakPtr ref = iter.GetNext(); |
2271 | nsCOMPtr<nsIScrollObserver> obs = do_QueryReferent(ref); |
2272 | if (obs) { |
2273 | obs->ScrollPositionChanged(); |
2274 | } else { |
2275 | iter.Remove(); |
2276 | } |
2277 | } |
2278 | return NS_OK; |
2279 | } |
2280 | |
2281 | //***************************************************************************** |
2282 | // nsDocShell::nsIDocShellTreeItem |
2283 | //***************************************************************************** |
2284 | |
2285 | NS_IMETHODIMPnsresult |
2286 | nsDocShell::GetName(nsAString& aName) { |
2287 | aName = mBrowsingContext->Name(); |
2288 | return NS_OK; |
2289 | } |
2290 | |
2291 | NS_IMETHODIMPnsresult |
2292 | nsDocShell::SetName(const nsAString& aName) { |
2293 | return mBrowsingContext->SetName(aName); |
2294 | } |
2295 | |
2296 | NS_IMETHODIMPnsresult |
2297 | nsDocShell::NameEquals(const nsAString& aName, bool* aResult) { |
2298 | NS_ENSURE_ARG_POINTER(aResult)do { if ((__builtin_expect(!!(!(aResult)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aResult" ") failed", nullptr , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 2298); return NS_ERROR_INVALID_POINTER; } } while (false); |
2299 | *aResult = mBrowsingContext->NameEquals(aName); |
2300 | return NS_OK; |
2301 | } |
2302 | |
2303 | NS_IMETHODIMPnsresult |
2304 | nsDocShell::GetCustomUserAgent(nsAString& aCustomUserAgent) { |
2305 | mBrowsingContext->GetCustomUserAgent(aCustomUserAgent); |
2306 | return NS_OK; |
2307 | } |
2308 | |
2309 | NS_IMETHODIMPnsresult |
2310 | nsDocShell::SetCustomUserAgent(const nsAString& aCustomUserAgent) { |
2311 | if (mWillChangeProcess) { |
2312 | NS_WARNING("SetCustomUserAgent: Process is changing. Ignoring set")NS_DebugBreak(NS_DEBUG_WARNING, "SetCustomUserAgent: Process is changing. Ignoring set" , nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 2312); |
2313 | return NS_ERROR_FAILURE; |
2314 | } |
2315 | |
2316 | return mBrowsingContext->SetCustomUserAgent(aCustomUserAgent); |
2317 | } |
2318 | |
2319 | NS_IMETHODIMPnsresult |
2320 | nsDocShell::ClearCachedPlatform() { |
2321 | nsCOMPtr<nsPIDOMWindowInner> win = |
2322 | mScriptGlobal ? mScriptGlobal->GetCurrentInnerWindow() : nullptr; |
2323 | if (win) { |
2324 | Navigator* navigator = win->Navigator(); |
2325 | if (navigator) { |
2326 | navigator->ClearPlatformCache(); |
2327 | } |
2328 | } |
2329 | |
2330 | return NS_OK; |
2331 | } |
2332 | |
2333 | NS_IMETHODIMPnsresult |
2334 | nsDocShell::ClearCachedUserAgent() { |
2335 | nsCOMPtr<nsPIDOMWindowInner> win = |
2336 | mScriptGlobal ? mScriptGlobal->GetCurrentInnerWindow() : nullptr; |
2337 | if (win) { |
2338 | Navigator* navigator = win->Navigator(); |
2339 | if (navigator) { |
2340 | navigator->ClearUserAgentCache(); |
2341 | } |
2342 | } |
2343 | |
2344 | return NS_OK; |
2345 | } |
2346 | |
2347 | /* virtual */ |
2348 | int32_t nsDocShell::ItemType() { return mItemType; } |
2349 | |
2350 | NS_IMETHODIMPnsresult |
2351 | nsDocShell::GetItemType(int32_t* aItemType) { |
2352 | NS_ENSURE_ARG_POINTER(aItemType)do { if ((__builtin_expect(!!(!(aItemType)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aItemType" ") failed", nullptr , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 2352); return NS_ERROR_INVALID_POINTER; } } while (false); |
2353 | |
2354 | MOZ_DIAGNOSTIC_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType< decltype((mBrowsingContext->IsContent() ? typeContent : typeChrome ) == mItemType)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!((mBrowsingContext->IsContent () ? typeContent : typeChrome) == mItemType))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("(mBrowsingContext->IsContent() ? typeContent : typeChrome) == mItemType" , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 2355); AnnotateMozCrashReason ("MOZ_DIAGNOSTIC_ASSERT" "(" "(mBrowsingContext->IsContent() ? typeContent : typeChrome) == mItemType" ")"); do { MOZ_CrashSequence(__null, 2355); __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
2355 | (mBrowsingContext->IsContent() ? typeContent : typeChrome) == mItemType)do { static_assert( mozilla::detail::AssertionConditionType< decltype((mBrowsingContext->IsContent() ? typeContent : typeChrome ) == mItemType)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!((mBrowsingContext->IsContent () ? typeContent : typeChrome) == mItemType))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("(mBrowsingContext->IsContent() ? typeContent : typeChrome) == mItemType" , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 2355); AnnotateMozCrashReason ("MOZ_DIAGNOSTIC_ASSERT" "(" "(mBrowsingContext->IsContent() ? typeContent : typeChrome) == mItemType" ")"); do { MOZ_CrashSequence(__null, 2355); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2356 | *aItemType = mItemType; |
2357 | return NS_OK; |
2358 | } |
2359 | |
2360 | NS_IMETHODIMPnsresult |
2361 | nsDocShell::GetInProcessParent(nsIDocShellTreeItem** aParent) { |
2362 | if (!mParent) { |
2363 | *aParent = nullptr; |
2364 | } else { |
2365 | CallQueryInterface(mParent, aParent); |
2366 | } |
2367 | // Note that in the case when the parent is not an nsIDocShellTreeItem we |
2368 | // don't want to throw; we just want to return null. |
2369 | return NS_OK; |
2370 | } |
2371 | |
2372 | // With Fission, related nsDocShell objects may exist in a different process. In |
2373 | // that case, this method will return `nullptr`, despite a parent nsDocShell |
2374 | // object existing. |
2375 | // |
2376 | // Prefer using `BrowsingContext::Parent()`, which will succeed even if the |
2377 | // parent entry is not in the current process, and handle the case where the |
2378 | // parent nsDocShell is inaccessible. |
2379 | already_AddRefed<nsDocShell> nsDocShell::GetInProcessParentDocshell() { |
2380 | nsCOMPtr<nsIDocShell> docshell = do_QueryInterface(GetAsSupports(mParent)); |
2381 | return docshell.forget().downcast<nsDocShell>(); |
2382 | } |
2383 | |
2384 | void nsDocShell::MaybeCreateInitialClientSource(nsIPrincipal* aPrincipal) { |
2385 | MOZ_ASSERT(!mIsBeingDestroyed)do { static_assert( mozilla::detail::AssertionConditionType< decltype(!mIsBeingDestroyed)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!mIsBeingDestroyed))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!mIsBeingDestroyed" , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 2385); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "!mIsBeingDestroyed" ")"); do { MOZ_CrashSequence (__null, 2385); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); |
2386 | |
2387 | // If there is an existing document then there is no need to create |
2388 | // a client for a future initial about:blank document. |
2389 | if (mScriptGlobal && mScriptGlobal->GetCurrentInnerWindow() && |
2390 | mScriptGlobal->GetCurrentInnerWindow()->GetExtantDoc()) { |
2391 | MOZ_DIAGNOSTIC_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType< decltype(mScriptGlobal->GetCurrentInnerWindow()->GetClientInfo ().isSome())>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(mScriptGlobal->GetCurrentInnerWindow ()->GetClientInfo().isSome()))), 0))) { do { } while (false ); MOZ_ReportAssertionFailure("mScriptGlobal->GetCurrentInnerWindow()->GetClientInfo().isSome()" , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 2392); AnnotateMozCrashReason ("MOZ_DIAGNOSTIC_ASSERT" "(" "mScriptGlobal->GetCurrentInnerWindow()->GetClientInfo().isSome()" ")"); do { MOZ_CrashSequence(__null, 2392); __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
2392 | mScriptGlobal->GetCurrentInnerWindow()->GetClientInfo().isSome())do { static_assert( mozilla::detail::AssertionConditionType< decltype(mScriptGlobal->GetCurrentInnerWindow()->GetClientInfo ().isSome())>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(mScriptGlobal->GetCurrentInnerWindow ()->GetClientInfo().isSome()))), 0))) { do { } while (false ); MOZ_ReportAssertionFailure("mScriptGlobal->GetCurrentInnerWindow()->GetClientInfo().isSome()" , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 2392); AnnotateMozCrashReason ("MOZ_DIAGNOSTIC_ASSERT" "(" "mScriptGlobal->GetCurrentInnerWindow()->GetClientInfo().isSome()" ")"); do { MOZ_CrashSequence(__null, 2392); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2393 | MOZ_DIAGNOSTIC_ASSERT(!mInitialClientSource)do { static_assert( mozilla::detail::AssertionConditionType< decltype(!mInitialClientSource)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!mInitialClientSource))), 0) )) { do { } while (false); MOZ_ReportAssertionFailure("!mInitialClientSource" , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 2393); AnnotateMozCrashReason ("MOZ_DIAGNOSTIC_ASSERT" "(" "!mInitialClientSource" ")"); do { MOZ_CrashSequence(__null, 2393); __attribute__((nomerge)) :: abort(); } while (false); } } while (false); |
2394 | return; |
2395 | } |
2396 | |
2397 | // Don't recreate the initial client source. We call this multiple times |
2398 | // when DoChannelLoad() is called before CreateAboutBlankDocumentViewer. |
2399 | if (mInitialClientSource) { |
2400 | return; |
2401 | } |
2402 | |
2403 | // Don't pre-allocate the client when we are sandboxed. The inherited |
2404 | // principal does not take sandboxing into account. |
2405 | // TODO: Refactor sandboxing principal code out so we can use it here. |
2406 | if (!aPrincipal && mBrowsingContext->GetSandboxFlags()) { |
2407 | return; |
2408 | } |
2409 | |
2410 | // We cannot get inherited foreign partitioned principal here. Instead, we |
2411 | // directly check which principal we want to inherit for the service worker. |
2412 | nsIPrincipal* principal = |
2413 | aPrincipal |
2414 | ? aPrincipal |
2415 | : GetInheritedPrincipal( |
2416 | false, StoragePrincipalHelper:: |
2417 | ShouldUsePartitionPrincipalForServiceWorker(this)); |
2418 | |
2419 | // Sometimes there is no principal available when we are called from |
2420 | // CreateAboutBlankDocumentViewer. For example, sometimes the principal |
2421 | // is only extracted from the load context after the document is created |
2422 | // in Document::ResetToURI(). Ideally we would do something similar |
2423 | // here, but for now lets just avoid the issue by not preallocating the |
2424 | // client. |
2425 | if (!principal) { |
2426 | return; |
2427 | } |
2428 | |
2429 | nsCOMPtr<nsPIDOMWindowOuter> win = GetWindow(); |
2430 | if (!win) { |
2431 | return; |
2432 | } |
2433 | |
2434 | mInitialClientSource = ClientManager::CreateSource( |
2435 | ClientType::Window, GetMainThreadSerialEventTarget(), principal); |
2436 | MOZ_DIAGNOSTIC_ASSERT(mInitialClientSource)do { static_assert( mozilla::detail::AssertionConditionType< decltype(mInitialClientSource)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mInitialClientSource))), 0)) ) { do { } while (false); MOZ_ReportAssertionFailure("mInitialClientSource" , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 2436); AnnotateMozCrashReason ("MOZ_DIAGNOSTIC_ASSERT" "(" "mInitialClientSource" ")"); do { MOZ_CrashSequence(__null, 2436); __attribute__((nomerge)) :: abort(); } while (false); } } while (false); |
2437 | |
2438 | // Mark the initial client as execution ready, but owned by the docshell. |
2439 | // If the client is actually used this will cause ClientSource to force |
2440 | // the creation of the initial about:blank by calling |
2441 | // nsDocShell::GetDocument(). |
2442 | mInitialClientSource->DocShellExecutionReady(this); |
2443 | |
2444 | // Next, check to see if the parent is controlled. |
2445 | nsCOMPtr<nsIDocShell> parent = GetInProcessParentDocshell(); |
2446 | nsPIDOMWindowOuter* parentOuter = parent ? parent->GetWindow() : nullptr; |
2447 | nsPIDOMWindowInner* parentInner = |
2448 | parentOuter ? parentOuter->GetCurrentInnerWindow() : nullptr; |
2449 | if (!parentInner) { |
2450 | return; |
2451 | } |
2452 | |
2453 | nsCOMPtr<nsIURI> uri; |
2454 | MOZ_ALWAYS_SUCCEEDS(NS_NewURI(getter_AddRefs(uri), "about:blank"_ns))do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl (NS_NewURI(getter_AddRefs(uri), "about:blank"_ns))), 1)))), 1 ))) { } else { do { do { } while (false); MOZ_ReportCrash("" "NS_SUCCEEDED(NS_NewURI(getter_AddRefs(uri), \"about:blank\"_ns))" , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 2454); AnnotateMozCrashReason ("MOZ_CRASH(" "NS_SUCCEEDED(NS_NewURI(getter_AddRefs(uri), \"about:blank\"_ns))" ")"); do { MOZ_CrashSequence(__null, 2454); __attribute__((nomerge )) ::abort(); } while (false); } while (false); } } while (false ); |
2455 | |
2456 | // We're done if there is no parent controller or if this docshell |
2457 | // is not permitted to control for some reason. |
2458 | Maybe<ServiceWorkerDescriptor> controller(parentInner->GetController()); |
2459 | if (controller.isNothing() || |
2460 | !ServiceWorkerAllowedToControlWindow(principal, uri)) { |
2461 | return; |
2462 | } |
2463 | |
2464 | mInitialClientSource->InheritController(controller.ref()); |
2465 | } |
2466 | |
2467 | Maybe<ClientInfo> nsDocShell::GetInitialClientInfo() const { |
2468 | if (mInitialClientSource) { |
2469 | Maybe<ClientInfo> result; |
2470 | result.emplace(mInitialClientSource->Info()); |
2471 | return result; |
2472 | } |
2473 | |
2474 | nsPIDOMWindowInner* innerWindow = |
2475 | mScriptGlobal ? mScriptGlobal->GetCurrentInnerWindow() : nullptr; |
2476 | Document* doc = innerWindow ? innerWindow->GetExtantDoc() : nullptr; |
2477 | |
2478 | if (!doc || !doc->IsInitialDocument()) { |
2479 | return Maybe<ClientInfo>(); |
2480 | } |
2481 | |
2482 | return innerWindow->GetClientInfo(); |
2483 | } |
2484 | |
2485 | nsresult nsDocShell::SetDocLoaderParent(nsDocLoader* aParent) { |
2486 | bool wasFrame = IsSubframe(); |
2487 | |
2488 | nsresult rv = nsDocLoader::SetDocLoaderParent(aParent); |
2489 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 2489); return rv; } } while (false); |
2490 | |
2491 | nsCOMPtr<nsISupportsPriority> priorityGroup = do_QueryInterface(mLoadGroup); |
2492 | if (wasFrame != IsSubframe() && priorityGroup) { |
2493 | priorityGroup->AdjustPriority(wasFrame ? -1 : 1); |
2494 | } |
2495 | |
2496 | // Curse ambiguous nsISupports inheritance! |
2497 | nsISupports* parent = GetAsSupports(aParent); |
2498 | |
2499 | // If parent is another docshell, we inherit all their flags for |
2500 | // allowing plugins, scripting etc. |
2501 | bool value; |
2502 | nsCOMPtr<nsIDocShell> parentAsDocShell(do_QueryInterface(parent)); |
2503 | |
2504 | if (parentAsDocShell) { |
2505 | if (mAllowMetaRedirects && |
2506 | NS_SUCCEEDED(parentAsDocShell->GetAllowMetaRedirects(&value))((bool)(__builtin_expect(!!(!NS_FAILED_impl(parentAsDocShell-> GetAllowMetaRedirects(&value))), 1)))) { |
2507 | SetAllowMetaRedirects(value); |
2508 | } |
2509 | if (mAllowSubframes && |
2510 | NS_SUCCEEDED(parentAsDocShell->GetAllowSubframes(&value))((bool)(__builtin_expect(!!(!NS_FAILED_impl(parentAsDocShell-> GetAllowSubframes(&value))), 1)))) { |
2511 | SetAllowSubframes(value); |
2512 | } |
2513 | if (mAllowImages && |
2514 | NS_SUCCEEDED(parentAsDocShell->GetAllowImages(&value))((bool)(__builtin_expect(!!(!NS_FAILED_impl(parentAsDocShell-> GetAllowImages(&value))), 1)))) { |
2515 | SetAllowImages(value); |
2516 | } |
2517 | SetAllowMedia(parentAsDocShell->GetAllowMedia() && mAllowMedia); |
2518 | if (mAllowWindowControl && |
2519 | NS_SUCCEEDED(parentAsDocShell->GetAllowWindowControl(&value))((bool)(__builtin_expect(!!(!NS_FAILED_impl(parentAsDocShell-> GetAllowWindowControl(&value))), 1)))) { |
2520 | SetAllowWindowControl(value); |
2521 | } |
2522 | if (NS_FAILED(parentAsDocShell->GetAllowDNSPrefetch(&value))((bool)(__builtin_expect(!!(NS_FAILED_impl(parentAsDocShell-> GetAllowDNSPrefetch(&value))), 0)))) { |
2523 | value = false; |
2524 | } |
2525 | SetAllowDNSPrefetch(mAllowDNSPrefetch && value); |
2526 | } |
2527 | |
2528 | nsCOMPtr<nsIURIContentListener> parentURIListener(do_GetInterface(parent)); |
2529 | if (parentURIListener) { |
2530 | mContentListener->SetParentContentListener(parentURIListener); |
2531 | } |
2532 | |
2533 | return NS_OK; |
2534 | } |
2535 | |
2536 | void nsDocShell::MaybeRestoreWindowName() { |
2537 | if (!StaticPrefs::privacy_window_name_update_enabled()) { |
2538 | return; |
2539 | } |
2540 | |
2541 | // We only restore window.name for the top-level content. |
2542 | if (!mBrowsingContext->IsTopContent()) { |
2543 | return; |
2544 | } |
2545 | |
2546 | nsAutoString name; |
2547 | |
2548 | // Following implements https://html.spec.whatwg.org/#history-traversal: |
2549 | // Step 4.4. Check if the loading entry has a name. |
2550 | |
2551 | if (mLSHE) { |
2552 | mLSHE->GetName(name); |
2553 | } |
2554 | |
2555 | if (mLoadingEntry) { |
2556 | name = mLoadingEntry->mInfo.GetName(); |
2557 | } |
2558 | |
2559 | if (name.IsEmpty()) { |
2560 | return; |
2561 | } |
2562 | |
2563 | // Step 4.4.1. Set the name to the browsing context. |
2564 | Unused << mBrowsingContext->SetName(name); |
2565 | |
2566 | // Step 4.4.2. Clear the name of all entries that are contiguous and |
2567 | // same-origin with the loading entry. |
2568 | if (mLSHE) { |
2569 | nsSHistory::WalkContiguousEntries( |
2570 | mLSHE, [](nsISHEntry* aEntry) { aEntry->SetName(EmptyString()); }); |
2571 | } |
2572 | |
2573 | if (mLoadingEntry) { |
2574 | // Clear the name of the session entry in the child side. For parent side, |
2575 | // the clearing will be done when we commit the history to the parent. |
2576 | mLoadingEntry->mInfo.SetName(EmptyString()); |
2577 | } |
2578 | } |
2579 | |
2580 | void nsDocShell::StoreWindowNameToSHEntries() { |
2581 | MOZ_ASSERT(mBrowsingContext->IsTopContent())do { static_assert( mozilla::detail::AssertionConditionType< decltype(mBrowsingContext->IsTopContent())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mBrowsingContext->IsTopContent ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("mBrowsingContext->IsTopContent()", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 2581); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mBrowsingContext->IsTopContent()" ")"); do { MOZ_CrashSequence(__null, 2581); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2582 | |
2583 | nsAutoString name; |
2584 | mBrowsingContext->GetName(name); |
2585 | |
2586 | if (mOSHE) { |
2587 | nsSHistory::WalkContiguousEntries( |
2588 | mOSHE, [&](nsISHEntry* aEntry) { aEntry->SetName(name); }); |
2589 | } |
2590 | |
2591 | if (mozilla::SessionHistoryInParent()) { |
2592 | if (XRE_IsParentProcess()) { |
2593 | SessionHistoryEntry* entry = |
2594 | mBrowsingContext->Canonical()->GetActiveSessionHistoryEntry(); |
2595 | if (entry) { |
2596 | nsSHistory::WalkContiguousEntries( |
2597 | entry, [&](nsISHEntry* aEntry) { aEntry->SetName(name); }); |
2598 | } |
2599 | } else { |
2600 | // Ask parent process to store the name in entries. |
2601 | mozilla::Unused |
2602 | << ContentChild::GetSingleton() |
2603 | ->SendSessionHistoryEntryStoreWindowNameInContiguousEntries( |
2604 | mBrowsingContext, name); |
2605 | } |
2606 | } |
2607 | } |
2608 | |
2609 | NS_IMETHODIMPnsresult |
2610 | nsDocShell::GetInProcessSameTypeParent(nsIDocShellTreeItem** aParent) { |
2611 | if (BrowsingContext* parentBC = mBrowsingContext->GetParent()) { |
2612 | *aParent = do_AddRef(parentBC->GetDocShell()).take(); |
2613 | } |
2614 | return NS_OK; |
2615 | } |
2616 | |
2617 | NS_IMETHODIMPnsresult |
2618 | nsDocShell::GetInProcessRootTreeItem(nsIDocShellTreeItem** aRootTreeItem) { |
2619 | NS_ENSURE_ARG_POINTER(aRootTreeItem)do { if ((__builtin_expect(!!(!(aRootTreeItem)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aRootTreeItem" ") failed" , nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 2619); return NS_ERROR_INVALID_POINTER; } } while (false); |
2620 | |
2621 | RefPtr<nsDocShell> root = this; |
2622 | RefPtr<nsDocShell> parent = root->GetInProcessParentDocshell(); |
2623 | while (parent) { |
2624 | root = parent; |
2625 | parent = root->GetInProcessParentDocshell(); |
2626 | } |
2627 | |
2628 | root.forget(aRootTreeItem); |
2629 | return NS_OK; |
2630 | } |
2631 | |
2632 | NS_IMETHODIMPnsresult |
2633 | nsDocShell::GetInProcessSameTypeRootTreeItem( |
2634 | nsIDocShellTreeItem** aRootTreeItem) { |
2635 | NS_ENSURE_ARG_POINTER(aRootTreeItem)do { if ((__builtin_expect(!!(!(aRootTreeItem)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aRootTreeItem" ") failed" , nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 2635); return NS_ERROR_INVALID_POINTER; } } while (false); |
2636 | *aRootTreeItem = static_cast<nsIDocShellTreeItem*>(this); |
2637 | |
2638 | nsCOMPtr<nsIDocShellTreeItem> parent; |
2639 | NS_ENSURE_SUCCESS(GetInProcessSameTypeParent(getter_AddRefs(parent)),do { nsresult __rv = GetInProcessSameTypeParent(getter_AddRefs (parent)); if (((bool)(__builtin_expect(!!(NS_FAILED_impl(__rv )), 0)))) { const char* name = mozilla::GetStaticErrorName(__rv ); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "GetInProcessSameTypeParent(getter_AddRefs(parent))" , "NS_ERROR_FAILURE", static_cast<uint32_t>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""); NS_DebugBreak (NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 2640); return NS_ERROR_FAILURE; } } while (false) |
2640 | NS_ERROR_FAILURE)do { nsresult __rv = GetInProcessSameTypeParent(getter_AddRefs (parent)); if (((bool)(__builtin_expect(!!(NS_FAILED_impl(__rv )), 0)))) { const char* name = mozilla::GetStaticErrorName(__rv ); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "GetInProcessSameTypeParent(getter_AddRefs(parent))" , "NS_ERROR_FAILURE", static_cast<uint32_t>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""); NS_DebugBreak (NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 2640); return NS_ERROR_FAILURE; } } while (false); |
2641 | while (parent) { |
2642 | *aRootTreeItem = parent; |
2643 | NS_ENSURE_SUCCESS(do { nsresult __rv = (*aRootTreeItem)->GetInProcessSameTypeParent (getter_AddRefs(parent)); if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "(*aRootTreeItem)->GetInProcessSameTypeParent(getter_AddRefs(parent))" , "NS_ERROR_FAILURE", static_cast<uint32_t>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""); NS_DebugBreak (NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 2645); return NS_ERROR_FAILURE; } } while (false) |
2644 | (*aRootTreeItem)->GetInProcessSameTypeParent(getter_AddRefs(parent)),do { nsresult __rv = (*aRootTreeItem)->GetInProcessSameTypeParent (getter_AddRefs(parent)); if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "(*aRootTreeItem)->GetInProcessSameTypeParent(getter_AddRefs(parent))" , "NS_ERROR_FAILURE", static_cast<uint32_t>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""); NS_DebugBreak (NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 2645); return NS_ERROR_FAILURE; } } while (false) |
2645 | NS_ERROR_FAILURE)do { nsresult __rv = (*aRootTreeItem)->GetInProcessSameTypeParent (getter_AddRefs(parent)); if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "(*aRootTreeItem)->GetInProcessSameTypeParent(getter_AddRefs(parent))" , "NS_ERROR_FAILURE", static_cast<uint32_t>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""); NS_DebugBreak (NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 2645); return NS_ERROR_FAILURE; } } while (false); |
2646 | } |
2647 | NS_ADDREF(*aRootTreeItem)(*aRootTreeItem)->AddRef(); |
2648 | return NS_OK; |
2649 | } |
2650 | |
2651 | NS_IMETHODIMPnsresult |
2652 | nsDocShell::GetTreeOwner(nsIDocShellTreeOwner** aTreeOwner) { |
2653 | NS_ENSURE_ARG_POINTER(aTreeOwner)do { if ((__builtin_expect(!!(!(aTreeOwner)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aTreeOwner" ") failed", nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 2653); return NS_ERROR_INVALID_POINTER; } } while (false); |
2654 | |
2655 | *aTreeOwner = mTreeOwner; |
2656 | NS_IF_ADDREF(*aTreeOwner)ns_if_addref(*aTreeOwner); |
2657 | return NS_OK; |
2658 | } |
2659 | |
2660 | NS_IMETHODIMPnsresult |
2661 | nsDocShell::SetTreeOwner(nsIDocShellTreeOwner* aTreeOwner) { |
2662 | if (mIsBeingDestroyed && aTreeOwner) { |
2663 | return NS_ERROR_FAILURE; |
2664 | } |
2665 | |
2666 | // Don't automatically set the progress based on the tree owner for frames |
2667 | if (!IsSubframe()) { |
2668 | nsCOMPtr<nsIWebProgress> webProgress = |
2669 | do_QueryInterface(GetAsSupports(this)); |
2670 | |
2671 | if (webProgress) { |
2672 | nsCOMPtr<nsIWebProgressListener> oldListener = |
2673 | do_QueryInterface(mTreeOwner); |
2674 | nsCOMPtr<nsIWebProgressListener> newListener = |
2675 | do_QueryInterface(aTreeOwner); |
2676 | |
2677 | if (oldListener) { |
2678 | webProgress->RemoveProgressListener(oldListener); |
2679 | } |
2680 | |
2681 | if (newListener) { |
2682 | webProgress->AddProgressListener(newListener, |
2683 | nsIWebProgress::NOTIFY_ALL); |
2684 | } |
2685 | } |
2686 | } |
2687 | |
2688 | mTreeOwner = aTreeOwner; // Weak reference per API |
2689 | |
2690 | for (auto* childDocLoader : mChildList.ForwardRange()) { |
2691 | nsCOMPtr<nsIDocShellTreeItem> child = do_QueryObject(childDocLoader); |
2692 | NS_ENSURE_TRUE(child, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(child)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "child" ") failed", nullptr , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 2692); return NS_ERROR_FAILURE; } } while (false); |
2693 | |
2694 | if (child->ItemType() == mItemType) { |
2695 | child->SetTreeOwner(aTreeOwner); |
2696 | } |
2697 | } |
2698 | |
2699 | // If we're in the content process and have had a TreeOwner set on us, extract |
2700 | // our BrowserChild actor. If we've already had our BrowserChild set, assert |
2701 | // that it hasn't changed. |
2702 | if (mTreeOwner && XRE_IsContentProcess()) { |
2703 | nsCOMPtr<nsIBrowserChild> newBrowserChild = do_GetInterface(mTreeOwner); |
2704 | MOZ_ASSERT(newBrowserChild,do { static_assert( mozilla::detail::AssertionConditionType< decltype(newBrowserChild)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(newBrowserChild))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("newBrowserChild" " (" "No BrowserChild actor for tree owner in Content!" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 2705); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "newBrowserChild" ") (" "No BrowserChild actor for tree owner in Content!" ")"); do { MOZ_CrashSequence(__null, 2705); __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
2705 | "No BrowserChild actor for tree owner in Content!")do { static_assert( mozilla::detail::AssertionConditionType< decltype(newBrowserChild)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(newBrowserChild))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("newBrowserChild" " (" "No BrowserChild actor for tree owner in Content!" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 2705); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "newBrowserChild" ") (" "No BrowserChild actor for tree owner in Content!" ")"); do { MOZ_CrashSequence(__null, 2705); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2706 | |
2707 | if (mBrowserChild) { |
2708 | nsCOMPtr<nsIBrowserChild> oldBrowserChild = |
2709 | do_QueryReferent(mBrowserChild); |
2710 | MOZ_RELEASE_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType< decltype(oldBrowserChild == newBrowserChild)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(oldBrowserChild == newBrowserChild ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "oldBrowserChild == newBrowserChild" " (" "Cannot change BrowserChild during nsDocShell lifetime!" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 2712 ); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "oldBrowserChild == newBrowserChild" ") (" "Cannot change BrowserChild during nsDocShell lifetime!" ")"); do { MOZ_CrashSequence(__null, 2712); __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
2711 | oldBrowserChild == newBrowserChild,do { static_assert( mozilla::detail::AssertionConditionType< decltype(oldBrowserChild == newBrowserChild)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(oldBrowserChild == newBrowserChild ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "oldBrowserChild == newBrowserChild" " (" "Cannot change BrowserChild during nsDocShell lifetime!" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 2712 ); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "oldBrowserChild == newBrowserChild" ") (" "Cannot change BrowserChild during nsDocShell lifetime!" ")"); do { MOZ_CrashSequence(__null, 2712); __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
2712 | "Cannot change BrowserChild during nsDocShell lifetime!")do { static_assert( mozilla::detail::AssertionConditionType< decltype(oldBrowserChild == newBrowserChild)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(oldBrowserChild == newBrowserChild ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "oldBrowserChild == newBrowserChild" " (" "Cannot change BrowserChild during nsDocShell lifetime!" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 2712 ); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "oldBrowserChild == newBrowserChild" ") (" "Cannot change BrowserChild during nsDocShell lifetime!" ")"); do { MOZ_CrashSequence(__null, 2712); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2713 | } else { |
2714 | mBrowserChild = do_GetWeakReference(newBrowserChild); |
2715 | } |
2716 | } |
2717 | |
2718 | return NS_OK; |
2719 | } |
2720 | |
2721 | NS_IMETHODIMPnsresult |
2722 | nsDocShell::GetHistoryID(nsID& aID) { |
2723 | aID = mBrowsingContext->GetHistoryID(); |
2724 | return NS_OK; |
2725 | } |
2726 | |
2727 | const nsID& nsDocShell::HistoryID() { return mBrowsingContext->GetHistoryID(); } |
2728 | |
2729 | NS_IMETHODIMPnsresult |
2730 | nsDocShell::GetIsInUnload(bool* aIsInUnload) { |
2731 | *aIsInUnload = mFiredUnloadEvent; |
2732 | return NS_OK; |
2733 | } |
2734 | |
2735 | NS_IMETHODIMPnsresult |
2736 | nsDocShell::GetInProcessChildCount(int32_t* aChildCount) { |
2737 | NS_ENSURE_ARG_POINTER(aChildCount)do { if ((__builtin_expect(!!(!(aChildCount)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aChildCount" ") failed" , nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 2737); return NS_ERROR_INVALID_POINTER; } } while (false); |
2738 | *aChildCount = mChildList.Length(); |
2739 | return NS_OK; |
2740 | } |
2741 | |
2742 | NS_IMETHODIMPnsresult |
2743 | nsDocShell::AddChild(nsIDocShellTreeItem* aChild) { |
2744 | NS_ENSURE_ARG_POINTER(aChild)do { if ((__builtin_expect(!!(!(aChild)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aChild" ") failed", nullptr , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 2744); return NS_ERROR_INVALID_POINTER; } } while (false); |
2745 | |
2746 | RefPtr<nsDocLoader> childAsDocLoader = GetAsDocLoader(aChild); |
2747 | NS_ENSURE_TRUE(childAsDocLoader, NS_ERROR_UNEXPECTED)do { if ((__builtin_expect(!!(!(childAsDocLoader)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "childAsDocLoader" ") failed" , nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 2747); return NS_ERROR_UNEXPECTED; } } while (false); |
2748 | |
2749 | // Make sure we're not creating a loop in the docshell tree |
2750 | nsDocLoader* ancestor = this; |
2751 | do { |
2752 | if (childAsDocLoader == ancestor) { |
2753 | return NS_ERROR_ILLEGAL_VALUE; |
2754 | } |
2755 | ancestor = ancestor->GetParent(); |
2756 | } while (ancestor); |
2757 | |
2758 | // Make sure to remove the child from its current parent. |
2759 | nsDocLoader* childsParent = childAsDocLoader->GetParent(); |
2760 | if (childsParent) { |
2761 | nsresult rv = childsParent->RemoveChildLoader(childAsDocLoader); |
2762 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 2762); return rv; } } while (false); |
2763 | } |
2764 | |
2765 | // Make sure to clear the treeowner in case this child is a different type |
2766 | // from us. |
2767 | aChild->SetTreeOwner(nullptr); |
2768 | |
2769 | nsresult res = AddChildLoader(childAsDocLoader); |
2770 | NS_ENSURE_SUCCESS(res, res)do { nsresult __rv = res; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "res", "res", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 2770); return res; } } while (false); |
2771 | NS_ASSERTION(!mChildList.IsEmpty(),do { if (!(!mChildList.IsEmpty())) { NS_DebugBreak(NS_DEBUG_ASSERTION , "child list must not be empty after a successful add", "!mChildList.IsEmpty()" , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 2772); MOZ_PretendNoReturn (); } } while (0) |
2772 | "child list must not be empty after a successful add")do { if (!(!mChildList.IsEmpty())) { NS_DebugBreak(NS_DEBUG_ASSERTION , "child list must not be empty after a successful add", "!mChildList.IsEmpty()" , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 2772); MOZ_PretendNoReturn (); } } while (0); |
2773 | |
2774 | /* Set the child's global history if the parent has one */ |
2775 | if (mBrowsingContext->GetUseGlobalHistory()) { |
2776 | // childDocShell->SetUseGlobalHistory(true); |
2777 | // this should be set through BC inherit |
2778 | MOZ_ASSERT(aChild->GetBrowsingContext()->GetUseGlobalHistory())do { static_assert( mozilla::detail::AssertionConditionType< decltype(aChild->GetBrowsingContext()->GetUseGlobalHistory ())>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(aChild->GetBrowsingContext()->GetUseGlobalHistory ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("aChild->GetBrowsingContext()->GetUseGlobalHistory()", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 2778); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "aChild->GetBrowsingContext()->GetUseGlobalHistory()" ")"); do { MOZ_CrashSequence(__null, 2778); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2779 | } |
2780 | |
2781 | if (aChild->ItemType() != mItemType) { |
2782 | return NS_OK; |
2783 | } |
2784 | |
2785 | aChild->SetTreeOwner(mTreeOwner); |
2786 | |
2787 | nsCOMPtr<nsIDocShell> childAsDocShell(do_QueryInterface(aChild)); |
2788 | if (!childAsDocShell) { |
2789 | return NS_OK; |
2790 | } |
2791 | |
2792 | // charset, style-disabling, and zoom will be inherited in SetupNewViewer() |
2793 | |
2794 | // Now take this document's charset and set the child's parentCharset field |
2795 | // to it. We'll later use that field, in the loading process, for the |
2796 | // charset choosing algorithm. |
2797 | // If we fail, at any point, we just return NS_OK. |
2798 | // This code has some performance impact. But this will be reduced when |
2799 | // the current charset will finally be stored as an Atom, avoiding the |
2800 | // alias resolution extra look-up. |
2801 | |
2802 | // we are NOT going to propagate the charset is this Chrome's docshell |
2803 | if (mItemType == nsIDocShellTreeItem::typeChrome) { |
2804 | return NS_OK; |
2805 | } |
2806 | |
2807 | // get the parent's current charset |
2808 | if (!mDocumentViewer) { |
2809 | return NS_OK; |
2810 | } |
2811 | Document* doc = mDocumentViewer->GetDocument(); |
2812 | if (!doc) { |
2813 | return NS_OK; |
2814 | } |
2815 | |
2816 | const Encoding* parentCS = doc->GetDocumentCharacterSet(); |
2817 | int32_t charsetSource = doc->GetDocumentCharacterSetSource(); |
2818 | // set the child's parentCharset |
2819 | childAsDocShell->SetParentCharset(parentCS, charsetSource, |
2820 | doc->NodePrincipal()); |
2821 | |
2822 | // printf("### 1 >>> Adding child. Parent CS = %s. ItemType = %d.\n", |
2823 | // NS_LossyConvertUTF16toASCII(parentCS).get(), mItemType); |
2824 | |
2825 | return NS_OK; |
2826 | } |
2827 | |
2828 | NS_IMETHODIMPnsresult |
2829 | nsDocShell::RemoveChild(nsIDocShellTreeItem* aChild) { |
2830 | NS_ENSURE_ARG_POINTER(aChild)do { if ((__builtin_expect(!!(!(aChild)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aChild" ") failed", nullptr , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 2830); return NS_ERROR_INVALID_POINTER; } } while (false); |
2831 | |
2832 | RefPtr<nsDocLoader> childAsDocLoader = GetAsDocLoader(aChild); |
2833 | NS_ENSURE_TRUE(childAsDocLoader, NS_ERROR_UNEXPECTED)do { if ((__builtin_expect(!!(!(childAsDocLoader)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "childAsDocLoader" ") failed" , nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 2833); return NS_ERROR_UNEXPECTED; } } while (false); |
2834 | |
2835 | nsresult rv = RemoveChildLoader(childAsDocLoader); |
2836 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 2836); return rv; } } while (false); |
2837 | |
2838 | aChild->SetTreeOwner(nullptr); |
2839 | |
2840 | return nsDocLoader::AddDocLoaderAsChildOfRoot(childAsDocLoader); |
2841 | } |
2842 | |
2843 | NS_IMETHODIMPnsresult |
2844 | nsDocShell::GetInProcessChildAt(int32_t aIndex, nsIDocShellTreeItem** aChild) { |
2845 | NS_ENSURE_ARG_POINTER(aChild)do { if ((__builtin_expect(!!(!(aChild)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aChild" ") failed", nullptr , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 2845); return NS_ERROR_INVALID_POINTER; } } while (false); |
2846 | |
2847 | RefPtr<nsDocShell> child = GetInProcessChildAt(aIndex); |
2848 | NS_ENSURE_TRUE(child, NS_ERROR_UNEXPECTED)do { if ((__builtin_expect(!!(!(child)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "child" ") failed", nullptr , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 2848); return NS_ERROR_UNEXPECTED; } } while (false); |
2849 | |
2850 | child.forget(aChild); |
2851 | |
2852 | return NS_OK; |
2853 | } |
2854 | |
2855 | nsDocShell* nsDocShell::GetInProcessChildAt(int32_t aIndex) { |
2856 | #ifdef DEBUG1 |
2857 | if (aIndex < 0) { |
2858 | NS_WARNING("Negative index passed to GetChildAt")NS_DebugBreak(NS_DEBUG_WARNING, "Negative index passed to GetChildAt" , nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 2858); |
2859 | } else if (static_cast<uint32_t>(aIndex) >= mChildList.Length()) { |
2860 | NS_WARNING("Too large an index passed to GetChildAt")NS_DebugBreak(NS_DEBUG_WARNING, "Too large an index passed to GetChildAt" , nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 2860); |
2861 | } |
2862 | #endif |
2863 | |
2864 | nsIDocumentLoader* child = ChildAt(aIndex); |
2865 | |
2866 | // child may be nullptr here. |
2867 | return static_cast<nsDocShell*>(child); |
2868 | } |
2869 | |
2870 | nsresult nsDocShell::AddChildSHEntry(nsISHEntry* aCloneRef, |
2871 | nsISHEntry* aNewEntry, |
2872 | int32_t aChildOffset, uint32_t aLoadType, |
2873 | bool aCloneChildren) { |
2874 | MOZ_ASSERT(!mozilla::SessionHistoryInParent())do { static_assert( mozilla::detail::AssertionConditionType< decltype(!mozilla::SessionHistoryInParent())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!mozilla::SessionHistoryInParent ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("!mozilla::SessionHistoryInParent()", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 2874); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()" ")"); do { MOZ_CrashSequence(__null, 2874); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2875 | nsresult rv = NS_OK; |
2876 | |
2877 | if (mLSHE && aLoadType != LOAD_PUSHSTATE) { |
2878 | /* You get here if you are currently building a |
2879 | * hierarchy ie.,you just visited a frameset page |
2880 | */ |
2881 | if (NS_FAILED(mLSHE->ReplaceChild(aNewEntry))((bool)(__builtin_expect(!!(NS_FAILED_impl(mLSHE->ReplaceChild (aNewEntry))), 0)))) { |
2882 | rv = mLSHE->AddChild(aNewEntry, aChildOffset); |
2883 | } |
2884 | } else if (!aCloneRef) { |
2885 | /* This is an initial load in some subframe. Just append it if we can */ |
2886 | if (mOSHE) { |
2887 | rv = mOSHE->AddChild(aNewEntry, aChildOffset, UseRemoteSubframes()); |
2888 | } |
2889 | } else { |
2890 | RefPtr<ChildSHistory> shistory = GetRootSessionHistory(); |
2891 | if (shistory) { |
2892 | rv = shistory->LegacySHistory()->AddNestedSHEntry( |
2893 | aCloneRef, aNewEntry, mBrowsingContext->Top(), aCloneChildren); |
2894 | } |
2895 | } |
2896 | return rv; |
2897 | } |
2898 | |
2899 | nsresult nsDocShell::AddChildSHEntryToParent(nsISHEntry* aNewEntry, |
2900 | int32_t aChildOffset, |
2901 | bool aCloneChildren) { |
2902 | MOZ_ASSERT(!mozilla::SessionHistoryInParent())do { static_assert( mozilla::detail::AssertionConditionType< decltype(!mozilla::SessionHistoryInParent())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!mozilla::SessionHistoryInParent ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("!mozilla::SessionHistoryInParent()", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 2902); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()" ")"); do { MOZ_CrashSequence(__null, 2902); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2903 | /* You will get here when you are in a subframe and |
2904 | * a new url has been loaded on you. |
2905 | * The mOSHE in this subframe will be the previous url's |
2906 | * mOSHE. This mOSHE will be used as the identification |
2907 | * for this subframe in the CloneAndReplace function. |
2908 | */ |
2909 | |
2910 | // In this case, we will end up calling AddEntry, which increases the |
2911 | // current index by 1 |
2912 | RefPtr<ChildSHistory> rootSH = GetRootSessionHistory(); |
2913 | if (rootSH) { |
2914 | mPreviousEntryIndex = rootSH->Index(); |
2915 | } |
2916 | |
2917 | nsresult rv; |
2918 | // XXX(farre): this is not Fission safe, expect errors. This never |
2919 | // get's executed once session history in the parent is enabled. |
2920 | nsCOMPtr<nsIDocShell> parent = do_QueryInterface(GetAsSupports(mParent), &rv); |
2921 | NS_WARNING_ASSERTION(do { if (!(parent || !UseRemoteSubframes())) { NS_DebugBreak( NS_DEBUG_WARNING, "Failed to add child session history entry! This will be resolved once " "session history in the parent is enabled.", "parent || !UseRemoteSubframes()" , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 2924); } } while (false) |
2922 | parent || !UseRemoteSubframes(),do { if (!(parent || !UseRemoteSubframes())) { NS_DebugBreak( NS_DEBUG_WARNING, "Failed to add child session history entry! This will be resolved once " "session history in the parent is enabled.", "parent || !UseRemoteSubframes()" , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 2924); } } while (false) |
2923 | "Failed to add child session history entry! This will be resolved once "do { if (!(parent || !UseRemoteSubframes())) { NS_DebugBreak( NS_DEBUG_WARNING, "Failed to add child session history entry! This will be resolved once " "session history in the parent is enabled.", "parent || !UseRemoteSubframes()" , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 2924); } } while (false) |
2924 | "session history in the parent is enabled.")do { if (!(parent || !UseRemoteSubframes())) { NS_DebugBreak( NS_DEBUG_WARNING, "Failed to add child session history entry! This will be resolved once " "session history in the parent is enabled.", "parent || !UseRemoteSubframes()" , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 2924); } } while (false); |
2925 | if (parent) { |
2926 | rv = nsDocShell::Cast(parent)->AddChildSHEntry( |
2927 | mOSHE, aNewEntry, aChildOffset, mLoadType, aCloneChildren); |
2928 | } |
2929 | |
2930 | if (rootSH) { |
2931 | mLoadedEntryIndex = rootSH->Index(); |
2932 | |
2933 | if (MOZ_UNLIKELY(MOZ_LOG_TEST(gPageCacheLog, LogLevel::Verbose))(__builtin_expect(!!((__builtin_expect(!!(mozilla::detail::log_test (gPageCacheLog, LogLevel::Verbose)), 0))), 0))) { |
2934 | MOZ_LOG(gPageCacheLog, LogLevel::Verbose,do { const ::mozilla::LogModule* moz_real_module = gPageCacheLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Verbose)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Verbose, "Previous index: %d, Loaded index: %d", mPreviousEntryIndex , mLoadedEntryIndex); } } while (0) |
2935 | ("Previous index: %d, Loaded index: %d", mPreviousEntryIndex,do { const ::mozilla::LogModule* moz_real_module = gPageCacheLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Verbose)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Verbose, "Previous index: %d, Loaded index: %d", mPreviousEntryIndex , mLoadedEntryIndex); } } while (0) |
2936 | mLoadedEntryIndex))do { const ::mozilla::LogModule* moz_real_module = gPageCacheLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Verbose)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Verbose, "Previous index: %d, Loaded index: %d", mPreviousEntryIndex , mLoadedEntryIndex); } } while (0); |
2937 | } |
2938 | } |
2939 | |
2940 | return rv; |
2941 | } |
2942 | |
2943 | NS_IMETHODIMPnsresult |
2944 | nsDocShell::GetCurrentSHEntry(nsISHEntry** aEntry, bool* aOSHE) { |
2945 | *aOSHE = false; |
2946 | *aEntry = nullptr; |
2947 | if (mLSHE) { |
2948 | NS_ADDREF(*aEntry = mLSHE)(*aEntry = mLSHE)->AddRef(); |
2949 | } else if (mOSHE) { |
2950 | NS_ADDREF(*aEntry = mOSHE)(*aEntry = mOSHE)->AddRef(); |
2951 | *aOSHE = true; |
2952 | } |
2953 | return NS_OK; |
2954 | } |
2955 | |
2956 | NS_IMETHODIMPnsresult nsDocShell::SynchronizeLayoutHistoryState() { |
2957 | if (mActiveEntry && mActiveEntry->GetLayoutHistoryState() && |
2958 | mBrowsingContext) { |
2959 | if (XRE_IsContentProcess()) { |
2960 | dom::ContentChild* contentChild = dom::ContentChild::GetSingleton(); |
2961 | if (contentChild) { |
2962 | contentChild->SendSynchronizeLayoutHistoryState( |
2963 | mBrowsingContext, mActiveEntry->GetLayoutHistoryState()); |
2964 | } |
2965 | } else { |
2966 | SessionHistoryEntry* entry = |
2967 | mBrowsingContext->Canonical()->GetActiveSessionHistoryEntry(); |
2968 | if (entry) { |
2969 | entry->SetLayoutHistoryState(mActiveEntry->GetLayoutHistoryState()); |
2970 | } |
2971 | } |
2972 | if (mLoadingEntry && |
2973 | mLoadingEntry->mInfo.SharedId() == mActiveEntry->SharedId()) { |
2974 | mLoadingEntry->mInfo.SetLayoutHistoryState( |
2975 | mActiveEntry->GetLayoutHistoryState()); |
2976 | } |
2977 | } |
2978 | |
2979 | return NS_OK; |
2980 | } |
2981 | |
2982 | void nsDocShell::SetLoadGroupDefaultLoadFlags(nsLoadFlags aLoadFlags) { |
2983 | if (mLoadGroup) { |
2984 | mLoadGroup->SetDefaultLoadFlags(aLoadFlags); |
2985 | } else { |
2986 | NS_WARNING(NS_DebugBreak(NS_DEBUG_WARNING, "nsDocShell::SetLoadGroupDefaultLoadFlags has no loadGroup to " "propagate the mode to", nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 2988) |
2987 | "nsDocShell::SetLoadGroupDefaultLoadFlags has no loadGroup to "NS_DebugBreak(NS_DEBUG_WARNING, "nsDocShell::SetLoadGroupDefaultLoadFlags has no loadGroup to " "propagate the mode to", nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 2988) |
2988 | "propagate the mode to")NS_DebugBreak(NS_DEBUG_WARNING, "nsDocShell::SetLoadGroupDefaultLoadFlags has no loadGroup to " "propagate the mode to", nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 2988); |
2989 | } |
2990 | } |
2991 | |
2992 | nsIScriptGlobalObject* nsDocShell::GetScriptGlobalObject() { |
2993 | NS_ENSURE_SUCCESS(EnsureScriptEnvironment(), nullptr)do { nsresult __rv = EnsureScriptEnvironment(); if (((bool)(__builtin_expect (!!(NS_FAILED_impl(__rv)), 0)))) { const char* name = mozilla ::GetStaticErrorName(__rv); mozilla::SmprintfPointer msg = mozilla ::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "EnsureScriptEnvironment()", "nullptr", static_cast <uint32_t>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 2993); return nullptr; } } while (false); |
2994 | return mScriptGlobal; |
2995 | } |
2996 | |
2997 | Document* nsDocShell::GetDocument() { |
2998 | NS_ENSURE_SUCCESS(EnsureDocumentViewer(), nullptr)do { nsresult __rv = EnsureDocumentViewer(); if (((bool)(__builtin_expect (!!(NS_FAILED_impl(__rv)), 0)))) { const char* name = mozilla ::GetStaticErrorName(__rv); mozilla::SmprintfPointer msg = mozilla ::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "EnsureDocumentViewer()", "nullptr", static_cast <uint32_t>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 2998); return nullptr; } } while (false); |
2999 | return mDocumentViewer->GetDocument(); |
3000 | } |
3001 | |
3002 | Document* nsDocShell::GetExtantDocument() { |
3003 | return mDocumentViewer ? mDocumentViewer->GetDocument() : nullptr; |
3004 | } |
3005 | |
3006 | nsPIDOMWindowOuter* nsDocShell::GetWindow() { |
3007 | if (NS_FAILED(EnsureScriptEnvironment())((bool)(__builtin_expect(!!(NS_FAILED_impl(EnsureScriptEnvironment ())), 0)))) { |
3008 | return nullptr; |
3009 | } |
3010 | return mScriptGlobal; |
3011 | } |
3012 | |
3013 | NS_IMETHODIMPnsresult |
3014 | nsDocShell::GetDomWindow(mozIDOMWindowProxy** aWindow) { |
3015 | NS_ENSURE_ARG_POINTER(aWindow)do { if ((__builtin_expect(!!(!(aWindow)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aWindow" ") failed", nullptr , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 3015); return NS_ERROR_INVALID_POINTER; } } while (false); |
3016 | |
3017 | nsresult rv = EnsureScriptEnvironment(); |
3018 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 3018); return rv; } } while (false); |
3019 | |
3020 | RefPtr<nsGlobalWindowOuter> window = mScriptGlobal; |
3021 | window.forget(aWindow); |
3022 | return NS_OK; |
3023 | } |
3024 | |
3025 | NS_IMETHODIMPnsresult |
3026 | nsDocShell::GetMessageManager(ContentFrameMessageManager** aMessageManager) { |
3027 | RefPtr<ContentFrameMessageManager> mm; |
3028 | if (RefPtr<BrowserChild> browserChild = BrowserChild::GetFrom(this)) { |
3029 | mm = browserChild->GetMessageManager(); |
3030 | } else if (nsPIDOMWindowOuter* win = GetWindow()) { |
3031 | mm = win->GetMessageManager(); |
3032 | } |
3033 | mm.forget(aMessageManager); |
3034 | return NS_OK; |
3035 | } |
3036 | |
3037 | NS_IMETHODIMPnsresult |
3038 | nsDocShell::GetIsNavigating(bool* aOut) { |
3039 | *aOut = mIsNavigating; |
3040 | return NS_OK; |
3041 | } |
3042 | |
3043 | void nsDocShell::ClearFrameHistory(nsISHEntry* aEntry) { |
3044 | MOZ_ASSERT(!mozilla::SessionHistoryInParent())do { static_assert( mozilla::detail::AssertionConditionType< decltype(!mozilla::SessionHistoryInParent())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!mozilla::SessionHistoryInParent ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("!mozilla::SessionHistoryInParent()", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 3044); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()" ")"); do { MOZ_CrashSequence(__null, 3044); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3045 | RefPtr<ChildSHistory> rootSH = GetRootSessionHistory(); |
3046 | if (!rootSH || !aEntry) { |
3047 | return; |
3048 | } |
3049 | |
3050 | rootSH->LegacySHistory()->RemoveFrameEntries(aEntry); |
3051 | } |
3052 | |
3053 | //------------------------------------- |
3054 | //-- Helper Method for Print discovery |
3055 | //------------------------------------- |
3056 | bool nsDocShell::NavigationBlockedByPrinting(bool aDisplayErrorDialog) { |
3057 | if (!mBrowsingContext->Top()->GetIsPrinting()) { |
3058 | return false; |
3059 | } |
3060 | if (aDisplayErrorDialog) { |
3061 | DisplayLoadError(NS_ERROR_DOCUMENT_IS_PRINTMODE, nullptr, nullptr, nullptr); |
3062 | } |
3063 | return true; |
3064 | } |
3065 | |
3066 | bool nsDocShell::IsNavigationAllowed(bool aDisplayPrintErrorDialog, |
3067 | bool aCheckIfUnloadFired) { |
3068 | bool isAllowed = !NavigationBlockedByPrinting(aDisplayPrintErrorDialog) && |
3069 | (!aCheckIfUnloadFired || !mFiredUnloadEvent); |
3070 | if (!isAllowed) { |
3071 | return false; |
3072 | } |
3073 | if (!mDocumentViewer) { |
3074 | return true; |
3075 | } |
3076 | bool firingBeforeUnload; |
3077 | mDocumentViewer->GetBeforeUnloadFiring(&firingBeforeUnload); |
3078 | return !firingBeforeUnload; |
3079 | } |
3080 | |
3081 | //***************************************************************************** |
3082 | // nsDocShell::nsIWebNavigation |
3083 | //***************************************************************************** |
3084 | |
3085 | NS_IMETHODIMPnsresult |
3086 | nsDocShell::GetCanGoBack(bool* aCanGoBack) { |
3087 | *aCanGoBack = false; |
3088 | if (!IsNavigationAllowed(false)) { |
3089 | return NS_OK; // JS may not handle returning of an error code |
3090 | } |
3091 | RefPtr<ChildSHistory> rootSH = GetRootSessionHistory(); |
3092 | if (rootSH) { |
3093 | *aCanGoBack = rootSH->CanGo( |
3094 | -1, StaticPrefs::browser_navigation_requireUserInteraction()); |
3095 | MOZ_LOG(gSHLog, LogLevel::Verbose,do { const ::mozilla::LogModule* moz_real_module = gSHLog; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Verbose)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Verbose, "nsDocShell %p CanGoBack()->%d", this , *aCanGoBack); } } while (0) |
3096 | ("nsDocShell %p CanGoBack()->%d", this, *aCanGoBack))do { const ::mozilla::LogModule* moz_real_module = gSHLog; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Verbose)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Verbose, "nsDocShell %p CanGoBack()->%d", this , *aCanGoBack); } } while (0); |
3097 | |
3098 | return NS_OK; |
3099 | } |
3100 | return NS_ERROR_FAILURE; |
3101 | } |
3102 | |
3103 | NS_IMETHODIMPnsresult |
3104 | nsDocShell::GetCanGoBackIgnoringUserInteraction(bool* aCanGoBack) { |
3105 | *aCanGoBack = false; |
3106 | if (!IsNavigationAllowed(false)) { |
3107 | return NS_OK; // JS may not handle returning of an error code |
3108 | } |
3109 | RefPtr<ChildSHistory> rootSH = GetRootSessionHistory(); |
3110 | if (rootSH) { |
3111 | *aCanGoBack = rootSH->CanGo(-1, false); |
3112 | MOZ_LOG(gSHLog, LogLevel::Verbose,do { const ::mozilla::LogModule* moz_real_module = gSHLog; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Verbose)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Verbose, "nsDocShell %p CanGoBackIgnoringUserInteraction()->%d" , this, *aCanGoBack); } } while (0) |
3113 | ("nsDocShell %p CanGoBackIgnoringUserInteraction()->%d", this,do { const ::mozilla::LogModule* moz_real_module = gSHLog; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Verbose)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Verbose, "nsDocShell %p CanGoBackIgnoringUserInteraction()->%d" , this, *aCanGoBack); } } while (0) |
3114 | *aCanGoBack))do { const ::mozilla::LogModule* moz_real_module = gSHLog; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Verbose)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Verbose, "nsDocShell %p CanGoBackIgnoringUserInteraction()->%d" , this, *aCanGoBack); } } while (0); |
3115 | |
3116 | return NS_OK; |
3117 | } |
3118 | return NS_ERROR_FAILURE; |
3119 | } |
3120 | |
3121 | NS_IMETHODIMPnsresult |
3122 | nsDocShell::GetCanGoForward(bool* aCanGoForward) { |
3123 | *aCanGoForward = false; |
3124 | if (!IsNavigationAllowed(false)) { |
3125 | return NS_OK; // JS may not handle returning of an error code |
3126 | } |
3127 | RefPtr<ChildSHistory> rootSH = GetRootSessionHistory(); |
3128 | if (rootSH) { |
3129 | *aCanGoForward = rootSH->CanGo( |
3130 | 1, StaticPrefs::browser_navigation_requireUserInteraction()); |
3131 | MOZ_LOG(gSHLog, LogLevel::Verbose,do { const ::mozilla::LogModule* moz_real_module = gSHLog; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Verbose)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Verbose, "nsDocShell %p CanGoForward()->%d", this , *aCanGoForward); } } while (0) |
3132 | ("nsDocShell %p CanGoForward()->%d", this, *aCanGoForward))do { const ::mozilla::LogModule* moz_real_module = gSHLog; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Verbose)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Verbose, "nsDocShell %p CanGoForward()->%d", this , *aCanGoForward); } } while (0); |
3133 | return NS_OK; |
3134 | } |
3135 | return NS_ERROR_FAILURE; |
3136 | } |
3137 | |
3138 | NS_IMETHODIMPnsresult |
3139 | nsDocShell::GoBack(bool aRequireUserInteraction, bool aUserActivation) { |
3140 | if (!IsNavigationAllowed()) { |
3141 | return NS_OK; // JS may not handle returning of an error code |
3142 | } |
3143 | |
3144 | auto cleanupIsNavigating = MakeScopeExit([&]() { mIsNavigating = false; }); |
3145 | mIsNavigating = true; |
3146 | |
3147 | RefPtr<ChildSHistory> rootSH = GetRootSessionHistory(); |
3148 | NS_ENSURE_TRUE(rootSH, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(rootSH)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "rootSH" ") failed", nullptr , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 3148); return NS_ERROR_FAILURE; } } while (false); |
3149 | ErrorResult rv; |
3150 | rootSH->Go(-1, aRequireUserInteraction, aUserActivation, rv); |
3151 | return rv.StealNSResult(); |
3152 | } |
3153 | |
3154 | NS_IMETHODIMPnsresult |
3155 | nsDocShell::GoForward(bool aRequireUserInteraction, bool aUserActivation) { |
3156 | if (!IsNavigationAllowed()) { |
3157 | return NS_OK; // JS may not handle returning of an error code |
3158 | } |
3159 | |
3160 | auto cleanupIsNavigating = MakeScopeExit([&]() { mIsNavigating = false; }); |
3161 | mIsNavigating = true; |
3162 | |
3163 | RefPtr<ChildSHistory> rootSH = GetRootSessionHistory(); |
3164 | NS_ENSURE_TRUE(rootSH, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(rootSH)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "rootSH" ") failed", nullptr , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 3164); return NS_ERROR_FAILURE; } } while (false); |
3165 | ErrorResult rv; |
3166 | rootSH->Go(1, aRequireUserInteraction, aUserActivation, rv); |
3167 | return rv.StealNSResult(); |
3168 | } |
3169 | |
3170 | // XXX(nika): We may want to stop exposing this API in the child process? Going |
3171 | // to a specific index from multiple different processes could definitely race. |
3172 | NS_IMETHODIMPnsresult |
3173 | nsDocShell::GotoIndex(int32_t aIndex, bool aUserActivation) { |
3174 | if (!IsNavigationAllowed()) { |
3175 | return NS_OK; // JS may not handle returning of an error code |
3176 | } |
3177 | |
3178 | auto cleanupIsNavigating = MakeScopeExit([&]() { mIsNavigating = false; }); |
3179 | mIsNavigating = true; |
3180 | |
3181 | RefPtr<ChildSHistory> rootSH = GetRootSessionHistory(); |
3182 | NS_ENSURE_TRUE(rootSH, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(rootSH)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "rootSH" ") failed", nullptr , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 3182); return NS_ERROR_FAILURE; } } while (false); |
3183 | |
3184 | ErrorResult rv; |
3185 | rootSH->GotoIndex(aIndex, aIndex - rootSH->Index(), false, aUserActivation, |
3186 | rv); |
3187 | return rv.StealNSResult(); |
3188 | } |
3189 | |
3190 | nsresult nsDocShell::LoadURI(nsIURI* aURI, |
3191 | const LoadURIOptions& aLoadURIOptions) { |
3192 | if (!IsNavigationAllowed()) { |
3193 | return NS_OK; // JS may not handle returning of an error code |
3194 | } |
3195 | RefPtr<nsDocShellLoadState> loadState; |
3196 | nsresult rv = nsDocShellLoadState::CreateFromLoadURIOptions( |
3197 | mBrowsingContext, aURI, aLoadURIOptions, getter_AddRefs(loadState)); |
3198 | MOZ_ASSERT(rv != NS_ERROR_MALFORMED_URI)do { static_assert( mozilla::detail::AssertionConditionType< decltype(rv != NS_ERROR_MALFORMED_URI)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(rv != NS_ERROR_MALFORMED_URI ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "rv != NS_ERROR_MALFORMED_URI", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 3198); AnnotateMozCrashReason("MOZ_ASSERT" "(" "rv != NS_ERROR_MALFORMED_URI" ")"); do { MOZ_CrashSequence(__null, 3198); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3199 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || !loadState) { |
3200 | return NS_ERROR_FAILURE; |
3201 | } |
3202 | |
3203 | return LoadURI(loadState, true); |
3204 | } |
3205 | |
3206 | NS_IMETHODIMPnsresult |
3207 | nsDocShell::LoadURIFromScript(nsIURI* aURI, |
3208 | JS::Handle<JS::Value> aLoadURIOptions, |
3209 | JSContext* aCx) { |
3210 | // generate dictionary for aLoadURIOptions and forward call |
3211 | LoadURIOptions loadURIOptions; |
3212 | if (!loadURIOptions.Init(aCx, aLoadURIOptions)) { |
3213 | return NS_ERROR_INVALID_ARG; |
3214 | } |
3215 | return LoadURI(aURI, loadURIOptions); |
3216 | } |
3217 | |
3218 | nsresult nsDocShell::FixupAndLoadURIString( |
3219 | const nsAString& aURIString, const LoadURIOptions& aLoadURIOptions) { |
3220 | if (!IsNavigationAllowed()) { |
3221 | return NS_OK; // JS may not handle returning of an error code |
3222 | } |
3223 | |
3224 | RefPtr<nsDocShellLoadState> loadState; |
3225 | nsresult rv = nsDocShellLoadState::CreateFromLoadURIOptions( |
3226 | mBrowsingContext, aURIString, aLoadURIOptions, getter_AddRefs(loadState)); |
3227 | |
3228 | uint32_t loadFlags = aLoadURIOptions.mLoadFlags; |
3229 | if (NS_ERROR_MALFORMED_URI == rv) { |
3230 | MOZ_LOG(gSHLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gSHLog; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "Creating an active entry on nsDocShell %p to %s (because " "we're showing an error page)", this, NS_ConvertUTF16toUTF8( aURIString).get()); } } while (0) |
3231 | ("Creating an active entry on nsDocShell %p to %s (because "do { const ::mozilla::LogModule* moz_real_module = gSHLog; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "Creating an active entry on nsDocShell %p to %s (because " "we're showing an error page)", this, NS_ConvertUTF16toUTF8( aURIString).get()); } } while (0) |
3232 | "we're showing an error page)",do { const ::mozilla::LogModule* moz_real_module = gSHLog; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "Creating an active entry on nsDocShell %p to %s (because " "we're showing an error page)", this, NS_ConvertUTF16toUTF8( aURIString).get()); } } while (0) |
3233 | this, NS_ConvertUTF16toUTF8(aURIString).get()))do { const ::mozilla::LogModule* moz_real_module = gSHLog; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "Creating an active entry on nsDocShell %p to %s (because " "we're showing an error page)", this, NS_ConvertUTF16toUTF8( aURIString).get()); } } while (0); |
3234 | |
3235 | // We need to store a session history entry. We don't have a valid URI, so |
3236 | // we use about:blank instead. |
3237 | nsCOMPtr<nsIURI> uri; |
3238 | MOZ_ALWAYS_SUCCEEDS(NS_NewURI(getter_AddRefs(uri), "about:blank"_ns))do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl (NS_NewURI(getter_AddRefs(uri), "about:blank"_ns))), 1)))), 1 ))) { } else { do { do { } while (false); MOZ_ReportCrash("" "NS_SUCCEEDED(NS_NewURI(getter_AddRefs(uri), \"about:blank\"_ns))" , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 3238); AnnotateMozCrashReason ("MOZ_CRASH(" "NS_SUCCEEDED(NS_NewURI(getter_AddRefs(uri), \"about:blank\"_ns))" ")"); do { MOZ_CrashSequence(__null, 3238); __attribute__((nomerge )) ::abort(); } while (false); } while (false); } } while (false ); |
3239 | nsCOMPtr<nsIPrincipal> triggeringPrincipal; |
3240 | if (aLoadURIOptions.mTriggeringPrincipal) { |
3241 | triggeringPrincipal = aLoadURIOptions.mTriggeringPrincipal; |
3242 | } else { |
3243 | triggeringPrincipal = nsContentUtils::GetSystemPrincipal(); |
3244 | } |
3245 | if (mozilla::SessionHistoryInParent()) { |
3246 | UniquePtr<SessionHistoryInfo> previousActiveEntry(mActiveEntry.release()); |
3247 | mActiveEntry = MakeUnique<SessionHistoryInfo>( |
3248 | uri, triggeringPrincipal, nullptr, nullptr, nullptr, |
3249 | nsLiteralCString("text/html")); |
3250 | mBrowsingContext->SetActiveSessionHistoryEntry( |
3251 | Nothing(), mActiveEntry.get(), previousActiveEntry.get(), |
3252 | MAKE_LOAD_TYPE(LOAD_NORMAL, loadFlags)((LOAD_NORMAL) | ((loadFlags) << 16)), |
3253 | /* aUpdatedCacheKey = */ 0); |
3254 | } |
3255 | if (DisplayLoadError(rv, nullptr, PromiseFlatStringTPromiseFlatString<char16_t>(aURIString).get(), |
3256 | nullptr) && |
3257 | (loadFlags & LOAD_FLAGS_ERROR_LOAD_CHANGES_RV) != 0) { |
3258 | return NS_ERROR_LOAD_SHOWED_ERRORPAGE; |
3259 | } |
3260 | } |
3261 | |
3262 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || !loadState) { |
3263 | return NS_ERROR_FAILURE; |
3264 | } |
3265 | |
3266 | return LoadURI(loadState, true); |
3267 | } |
3268 | |
3269 | NS_IMETHODIMPnsresult |
3270 | nsDocShell::FixupAndLoadURIStringFromScript( |
3271 | const nsAString& aURIString, JS::Handle<JS::Value> aLoadURIOptions, |
3272 | JSContext* aCx) { |
3273 | // generate dictionary for aLoadURIOptions and forward call |
3274 | LoadURIOptions loadURIOptions; |
3275 | if (!loadURIOptions.Init(aCx, aLoadURIOptions)) { |
3276 | return NS_ERROR_INVALID_ARG; |
3277 | } |
3278 | return FixupAndLoadURIString(aURIString, loadURIOptions); |
3279 | } |
3280 | |
3281 | void nsDocShell::UnblockEmbedderLoadEventForFailure(bool aFireFrameErrorEvent) { |
3282 | // If we're not in a content frame, or are at a BrowsingContext tree boundary, |
3283 | // such as the content-chrome boundary, don't fire the error event. |
3284 | if (mBrowsingContext->IsTopContent() || mBrowsingContext->IsChrome()) { |
3285 | return; |
3286 | } |
3287 | |
3288 | // If embedder is same-process, then unblocking the load event is already |
3289 | // handled by nsDocLoader. Fire the error event on our embedder element if |
3290 | // requested. |
3291 | // |
3292 | // XXX: Bug 1440212 is looking into potentially changing this behaviour to act |
3293 | // more like the remote case when in-process. |
3294 | RefPtr<Element> element = mBrowsingContext->GetEmbedderElement(); |
3295 | if (element) { |
3296 | if (aFireFrameErrorEvent) { |
3297 | if (RefPtr<nsFrameLoaderOwner> flo = do_QueryObject(element)) { |
3298 | if (RefPtr<nsFrameLoader> fl = flo->GetFrameLoader()) { |
3299 | fl->FireErrorEvent(); |
3300 | } |
3301 | } |
3302 | } |
3303 | return; |
3304 | } |
3305 | |
3306 | // If we have a cross-process parent document, we must notify it that we no |
3307 | // longer block its load event. This is necessary for OOP sub-documents |
3308 | // because error documents do not result in a call to |
3309 | // SendMaybeFireEmbedderLoadEvents via any of the normal call paths. |
3310 | // (Obviously, we must do this before any of the returns below.) |
3311 | RefPtr<BrowserChild> browserChild = BrowserChild::GetFrom(this); |
3312 | if (browserChild && |
3313 | !mBrowsingContext->GetParentWindowContext()->IsInProcess()) { |
3314 | mozilla::Unused << browserChild->SendMaybeFireEmbedderLoadEvents( |
3315 | aFireFrameErrorEvent ? EmbedderElementEventType::ErrorEvent |
3316 | : EmbedderElementEventType::NoEvent); |
3317 | } |
3318 | } |
3319 | |
3320 | NS_IMETHODIMPnsresult |
3321 | nsDocShell::DisplayLoadError(nsresult aError, nsIURI* aURI, |
3322 | const char16_t* aURL, nsIChannel* aFailedChannel, |
3323 | bool* aDisplayedErrorPage) { |
3324 | MOZ_LOG(gDocShellLeakLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gDocShellLeakLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "DOCSHELL %p DisplayLoadError %s\n", this, aURI ? aURI->GetSpecOrDefault().get() : ""); } } while (0 ) |
3325 | ("DOCSHELL %p DisplayLoadError %s\n", this,do { const ::mozilla::LogModule* moz_real_module = gDocShellLeakLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "DOCSHELL %p DisplayLoadError %s\n", this, aURI ? aURI->GetSpecOrDefault().get() : ""); } } while (0 ) |
3326 | aURI ? aURI->GetSpecOrDefault().get() : ""))do { const ::mozilla::LogModule* moz_real_module = gDocShellLeakLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "DOCSHELL %p DisplayLoadError %s\n", this, aURI ? aURI->GetSpecOrDefault().get() : ""); } } while (0 ); |
3327 | |
3328 | *aDisplayedErrorPage = false; |
3329 | // Get prompt and string bundle services |
3330 | nsCOMPtr<nsIPrompt> prompter; |
3331 | nsCOMPtr<nsIStringBundle> stringBundle; |
3332 | GetPromptAndStringBundle(getter_AddRefs(prompter), |
3333 | getter_AddRefs(stringBundle)); |
3334 | |
3335 | NS_ENSURE_TRUE(stringBundle, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(stringBundle)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "stringBundle" ") failed" , nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 3335); return NS_ERROR_FAILURE; } } while (false); |
3336 | NS_ENSURE_TRUE(prompter, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(prompter)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "prompter" ") failed", nullptr , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 3336); return NS_ERROR_FAILURE; } } while (false); |
3337 | |
3338 | const char* error = nullptr; |
3339 | // The key used to select the appropriate error message from the properties |
3340 | // file. |
3341 | const char* errorDescriptionID = nullptr; |
3342 | AutoTArray<nsString, 3> formatStrs; |
3343 | bool addHostPort = false; |
3344 | bool isBadStsCertError = false; |
3345 | nsresult rv = NS_OK; |
3346 | nsAutoString messageStr; |
3347 | nsAutoCString cssClass; |
3348 | nsAutoCString errorPage; |
3349 | |
3350 | errorPage.AssignLiteral("neterror"); |
3351 | |
3352 | // Turn the error code into a human readable error message. |
3353 | if (NS_ERROR_UNKNOWN_PROTOCOL == aError) { |
3354 | NS_ENSURE_ARG_POINTER(aURI)do { if ((__builtin_expect(!!(!(aURI)), 0))) { NS_DebugBreak( NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aURI" ") failed", nullptr , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 3354); return NS_ERROR_INVALID_POINTER; } } while (false); |
3355 | |
3356 | // Extract the schemes into a comma delimited list. |
3357 | nsAutoCString scheme; |
3358 | aURI->GetScheme(scheme); |
3359 | CopyASCIItoUTF16(scheme, *formatStrs.AppendElement()); |
3360 | nsCOMPtr<nsINestedURI> nestedURI = do_QueryInterface(aURI); |
3361 | while (nestedURI) { |
3362 | nsCOMPtr<nsIURI> tempURI; |
3363 | nsresult rv2; |
3364 | rv2 = nestedURI->GetInnerURI(getter_AddRefs(tempURI)); |
3365 | if (NS_SUCCEEDED(rv2)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv2)), 1))) && tempURI) { |
3366 | tempURI->GetScheme(scheme); |
3367 | formatStrs[0].AppendLiteral(", "); |
3368 | AppendASCIItoUTF16(scheme, formatStrs[0]); |
3369 | } |
3370 | nestedURI = do_QueryInterface(tempURI); |
3371 | } |
3372 | error = "unknownProtocolFound"; |
3373 | } else if (NS_ERROR_NET_EMPTY_RESPONSE == aError) { |
3374 | NS_ENSURE_ARG_POINTER(aURI)do { if ((__builtin_expect(!!(!(aURI)), 0))) { NS_DebugBreak( NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aURI" ") failed", nullptr , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 3374); return NS_ERROR_INVALID_POINTER; } } while (false); |
3375 | error = "httpErrorPage"; |
3376 | } else if (NS_ERROR_NET_ERROR_RESPONSE == aError) { |
3377 | NS_ENSURE_ARG_POINTER(aURI)do { if ((__builtin_expect(!!(!(aURI)), 0))) { NS_DebugBreak( NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aURI" ") failed", nullptr , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 3377); return NS_ERROR_INVALID_POINTER; } } while (false); |
3378 | error = "serverError"; |
3379 | } else if (NS_ERROR_FILE_NOT_FOUND == aError) { |
3380 | NS_ENSURE_ARG_POINTER(aURI)do { if ((__builtin_expect(!!(!(aURI)), 0))) { NS_DebugBreak( NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aURI" ") failed", nullptr , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 3380); return NS_ERROR_INVALID_POINTER; } } while (false); |
3381 | error = "fileNotFound"; |
3382 | } else if (NS_ERROR_FILE_ACCESS_DENIED == aError) { |
3383 | NS_ENSURE_ARG_POINTER(aURI)do { if ((__builtin_expect(!!(!(aURI)), 0))) { NS_DebugBreak( NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aURI" ") failed", nullptr , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 3383); return NS_ERROR_INVALID_POINTER; } } while (false); |
3384 | error = "fileAccessDenied"; |
3385 | } else if (NS_ERROR_UNKNOWN_HOST == aError) { |
3386 | NS_ENSURE_ARG_POINTER(aURI)do { if ((__builtin_expect(!!(!(aURI)), 0))) { NS_DebugBreak( NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aURI" ") failed", nullptr , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 3386); return NS_ERROR_INVALID_POINTER; } } while (false); |
3387 | // Get the host |
3388 | nsAutoCString host; |
3389 | nsCOMPtr<nsIURI> innermostURI = NS_GetInnermostURI(aURI); |
3390 | innermostURI->GetHost(host); |
3391 | CopyUTF8toUTF16(host, *formatStrs.AppendElement()); |
3392 | errorDescriptionID = "dnsNotFound2"; |
3393 | error = "dnsNotFound"; |
3394 | } else if (NS_ERROR_CONNECTION_REFUSED == aError || |
3395 | NS_ERROR_PROXY_BAD_GATEWAY == aError) { |
3396 | NS_ENSURE_ARG_POINTER(aURI)do { if ((__builtin_expect(!!(!(aURI)), 0))) { NS_DebugBreak( NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aURI" ") failed", nullptr , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 3396); return NS_ERROR_INVALID_POINTER; } } while (false); |
3397 | addHostPort = true; |
3398 | error = "connectionFailure"; |
3399 | } else if (NS_ERROR_NET_INTERRUPT == aError) { |
3400 | NS_ENSURE_ARG_POINTER(aURI)do { if ((__builtin_expect(!!(!(aURI)), 0))) { NS_DebugBreak( NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aURI" ") failed", nullptr , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 3400); return NS_ERROR_INVALID_POINTER; } } while (false); |
3401 | addHostPort = true; |
3402 | error = "netInterrupt"; |
3403 | } else if (NS_ERROR_NET_TIMEOUT == aError || |
3404 | NS_ERROR_PROXY_GATEWAY_TIMEOUT == aError || |
3405 | NS_ERROR_NET_TIMEOUT_EXTERNAL == aError) { |
3406 | NS_ENSURE_ARG_POINTER(aURI)do { if ((__builtin_expect(!!(!(aURI)), 0))) { NS_DebugBreak( NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aURI" ") failed", nullptr , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 3406); return NS_ERROR_INVALID_POINTER; } } while (false); |
3407 | // Get the host |
3408 | nsAutoCString host; |
3409 | aURI->GetHost(host); |
3410 | CopyUTF8toUTF16(host, *formatStrs.AppendElement()); |
3411 | error = "netTimeout"; |
3412 | } else if (NS_ERROR_CSP_FRAME_ANCESTOR_VIOLATION == aError || |
3413 | NS_ERROR_CSP_FORM_ACTION_VIOLATION == aError) { |
3414 | // CSP error |
3415 | cssClass.AssignLiteral("neterror"); |
3416 | error = "cspBlocked"; |
3417 | } else if (NS_ERROR_XFO_VIOLATION == aError) { |
3418 | // XFO error |
3419 | cssClass.AssignLiteral("neterror"); |
3420 | error = "xfoBlocked"; |
3421 | } else if (NS_ERROR_GET_MODULE(aError) == NS_ERROR_MODULE_SECURITY21) { |
3422 | nsCOMPtr<nsINSSErrorsService> nsserr = |
3423 | do_GetService(NS_NSS_ERRORS_SERVICE_CONTRACTID"@mozilla.org/nss_errors_service;1"); |
3424 | |
3425 | uint32_t errorClass; |
3426 | if (!nsserr || NS_FAILED(nsserr->GetErrorClass(aError, &errorClass))((bool)(__builtin_expect(!!(NS_FAILED_impl(nsserr->GetErrorClass (aError, &errorClass))), 0)))) { |
3427 | errorClass = nsINSSErrorsService::ERROR_CLASS_SSL_PROTOCOL; |
3428 | } |
3429 | |
3430 | nsCOMPtr<nsITransportSecurityInfo> tsi; |
3431 | if (aFailedChannel) { |
3432 | aFailedChannel->GetSecurityInfo(getter_AddRefs(tsi)); |
3433 | } |
3434 | if (tsi) { |
3435 | uint32_t securityState; |
3436 | tsi->GetSecurityState(&securityState); |
3437 | if (securityState & nsIWebProgressListener::STATE_USES_SSL_3) { |
3438 | error = "sslv3Used"; |
Value stored to 'error' is never read | |
3439 | addHostPort = true; |
3440 | } else if (securityState & |
3441 | nsIWebProgressListener::STATE_USES_WEAK_CRYPTO) { |
3442 | error = "weakCryptoUsed"; |
3443 | addHostPort = true; |
3444 | } |
3445 | } else { |
3446 | // No channel, let's obtain the generic error message |
3447 | if (nsserr) { |
3448 | nsserr->GetErrorMessage(aError, messageStr); |
3449 | } |
3450 | } |
3451 | // We don't have a message string here anymore but DisplayLoadError |
3452 | // requires a non-empty messageStr. |
3453 | messageStr.Truncate(); |
3454 | messageStr.AssignLiteral(u" "); |
3455 | if (errorClass == nsINSSErrorsService::ERROR_CLASS_BAD_CERT) { |
3456 | error = "nssBadCert"; |
3457 | |
3458 | // If this is an HTTP Strict Transport Security host or a pinned host |
3459 | // and the certificate is bad, don't allow overrides (RFC 6797 section |
3460 | // 12.1). |
3461 | bool isStsHost = false; |
3462 | bool isPinnedHost = false; |
3463 | OriginAttributes attrsForHSTS; |
3464 | if (aFailedChannel) { |
3465 | StoragePrincipalHelper::GetOriginAttributesForHSTS(aFailedChannel, |
3466 | attrsForHSTS); |
3467 | } else { |
3468 | attrsForHSTS = GetOriginAttributes(); |
3469 | } |
3470 | |
3471 | if (XRE_IsParentProcess()) { |
3472 | nsCOMPtr<nsISiteSecurityService> sss = |
3473 | do_GetService(NS_SSSERVICE_CONTRACTID"@mozilla.org/ssservice;1", &rv); |
3474 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 3474); return rv; } } while (false); |
3475 | rv = sss->IsSecureURI(aURI, attrsForHSTS, &isStsHost); |
3476 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 3476); return rv; } } while (false); |
3477 | } else { |
3478 | mozilla::dom::ContentChild* cc = |
3479 | mozilla::dom::ContentChild::GetSingleton(); |
3480 | cc->SendIsSecureURI(aURI, attrsForHSTS, &isStsHost); |
3481 | } |
3482 | nsCOMPtr<nsIPublicKeyPinningService> pkps = |
3483 | do_GetService(NS_PKPSERVICE_CONTRACTID"@mozilla.org/security/publickeypinningservice;1", &rv); |
3484 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 3484); return rv; } } while (false); |
3485 | rv = pkps->HostHasPins(aURI, &isPinnedHost); |
3486 | |
3487 | if (Preferences::GetBool("browser.xul.error_pages.expert_bad_cert", |
3488 | false)) { |
3489 | cssClass.AssignLiteral("expertBadCert"); |
3490 | } |
3491 | |
3492 | // HSTS/pinning takes precedence over the expert bad cert pref. We |
3493 | // never want to show the "Add Exception" button for these sites. |
3494 | // In the future we should differentiate between an HSTS host and a |
3495 | // pinned host and display a more informative message to the user. |
3496 | if (isStsHost || isPinnedHost) { |
3497 | isBadStsCertError = true; |
3498 | cssClass.AssignLiteral("badStsCert"); |
3499 | } |
3500 | |
3501 | errorPage.Assign("certerror"); |
3502 | } else { |
3503 | error = "nssFailure2"; |
3504 | } |
3505 | } else if (NS_ERROR_PHISHING_URI == aError || |
3506 | NS_ERROR_MALWARE_URI == aError || |
3507 | NS_ERROR_UNWANTED_URI == aError || |
3508 | NS_ERROR_HARMFUL_URI == aError) { |
3509 | nsAutoCString host; |
3510 | aURI->GetHost(host); |
3511 | CopyUTF8toUTF16(host, *formatStrs.AppendElement()); |
3512 | |
3513 | // Malware and phishing detectors may want to use an alternate error |
3514 | // page, but if the pref's not set, we'll fall back on the standard page |
3515 | nsAutoCString alternateErrorPage; |
3516 | nsresult rv = Preferences::GetCString("urlclassifier.alternate_error_page", |
3517 | alternateErrorPage); |
3518 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) { |
3519 | errorPage.Assign(alternateErrorPage); |
3520 | } |
3521 | |
3522 | if (NS_ERROR_PHISHING_URI == aError) { |
3523 | error = "deceptiveBlocked"; |
3524 | } else if (NS_ERROR_MALWARE_URI == aError) { |
3525 | error = "malwareBlocked"; |
3526 | } else if (NS_ERROR_UNWANTED_URI == aError) { |
3527 | error = "unwantedBlocked"; |
3528 | } else if (NS_ERROR_HARMFUL_URI == aError) { |
3529 | error = "harmfulBlocked"; |
3530 | } |
3531 | |
3532 | cssClass.AssignLiteral("blacklist"); |
3533 | } else if (NS_ERROR_CONTENT_CRASHED == aError) { |
3534 | errorPage.AssignLiteral("tabcrashed"); |
3535 | error = "tabcrashed"; |
3536 | |
3537 | RefPtr<EventTarget> handler = mChromeEventHandler; |
3538 | if (handler) { |
3539 | nsCOMPtr<Element> element = do_QueryInterface(handler); |
3540 | element->GetAttribute(u"crashedPageTitle"_ns, messageStr); |
3541 | } |
3542 | |
3543 | // DisplayLoadError requires a non-empty messageStr to proceed and call |
3544 | // LoadErrorPage. If the page doesn't have a title, we will use a blank |
3545 | // space which will be trimmed and thus treated as empty by the front-end. |
3546 | if (messageStr.IsEmpty()) { |
3547 | messageStr.AssignLiteral(u" "); |
3548 | } |
3549 | } else if (NS_ERROR_FRAME_CRASHED == aError) { |
3550 | errorPage.AssignLiteral("framecrashed"); |
3551 | error = "framecrashed"; |
3552 | messageStr.AssignLiteral(u" "); |
3553 | } else if (NS_ERROR_BUILDID_MISMATCH == aError) { |
3554 | errorPage.AssignLiteral("restartrequired"); |
3555 | error = "restartrequired"; |
3556 | |
3557 | // DisplayLoadError requires a non-empty messageStr to proceed and call |
3558 | // LoadErrorPage. If the page doesn't have a title, we will use a blank |
3559 | // space which will be trimmed and thus treated as empty by the front-end. |
3560 | if (messageStr.IsEmpty()) { |
3561 | messageStr.AssignLiteral(u" "); |
3562 | } |
3563 | } else { |
3564 | // Errors requiring simple formatting |
3565 | switch (aError) { |
3566 | case NS_ERROR_MALFORMED_URI: |
3567 | // URI is malformed |
3568 | error = "malformedURI"; |
3569 | errorDescriptionID = "malformedURI2"; |
3570 | break; |
3571 | case NS_ERROR_REDIRECT_LOOP: |
3572 | // Doc failed to load because the server generated too many redirects |
3573 | error = "redirectLoop"; |
3574 | break; |
3575 | case NS_ERROR_UNKNOWN_SOCKET_TYPE: |
3576 | // Doc failed to load because PSM is not installed |
3577 | error = "unknownSocketType"; |
3578 | break; |
3579 | case NS_ERROR_NET_RESET: |
3580 | // Doc failed to load because the server kept reseting the connection |
3581 | // before we could read any data from it |
3582 | error = "netReset"; |
3583 | break; |
3584 | case NS_ERROR_DOCUMENT_NOT_CACHED: |
3585 | // Doc failed to load because the cache does not contain a copy of |
3586 | // the document. |
3587 | error = "notCached"; |
3588 | break; |
3589 | case NS_ERROR_OFFLINE: |
3590 | // Doc failed to load because we are offline. |
3591 | error = "netOffline"; |
3592 | break; |
3593 | case NS_ERROR_DOCUMENT_IS_PRINTMODE: |
3594 | // Doc navigation attempted while Printing or Print Preview |
3595 | error = "isprinting"; |
3596 | break; |
3597 | case NS_ERROR_PORT_ACCESS_NOT_ALLOWED: |
3598 | // Port blocked for security reasons |
3599 | addHostPort = true; |
3600 | error = "deniedPortAccess"; |
3601 | break; |
3602 | case NS_ERROR_UNKNOWN_PROXY_HOST: |
3603 | // Proxy hostname could not be resolved. |
3604 | error = "proxyResolveFailure"; |
3605 | break; |
3606 | case NS_ERROR_PROXY_CONNECTION_REFUSED: |
3607 | case NS_ERROR_PROXY_FORBIDDEN: |
3608 | case NS_ERROR_PROXY_NOT_IMPLEMENTED: |
3609 | case NS_ERROR_PROXY_AUTHENTICATION_FAILED: |
3610 | case NS_ERROR_PROXY_TOO_MANY_REQUESTS: |
3611 | // Proxy connection was refused. |
3612 | error = "proxyConnectFailure"; |
3613 | break; |
3614 | case NS_ERROR_INVALID_CONTENT_ENCODING: |
3615 | // Bad Content Encoding. |
3616 | error = "contentEncodingError"; |
3617 | break; |
3618 | case NS_ERROR_UNSAFE_CONTENT_TYPE: |
3619 | // Channel refused to load from an unrecognized content type. |
3620 | error = "unsafeContentType"; |
3621 | break; |
3622 | case NS_ERROR_CORRUPTED_CONTENT: |
3623 | // Broken Content Detected. e.g. Content-MD5 check failure. |
3624 | error = "corruptedContentErrorv2"; |
3625 | break; |
3626 | case NS_ERROR_INTERCEPTION_FAILED: |
3627 | // ServiceWorker intercepted request, but something went wrong. |
3628 | error = "corruptedContentErrorv2"; |
3629 | break; |
3630 | case NS_ERROR_NET_INADEQUATE_SECURITY: |
3631 | // Server negotiated bad TLS for HTTP/2. |
3632 | error = "inadequateSecurityError"; |
3633 | addHostPort = true; |
3634 | break; |
3635 | case NS_ERROR_BLOCKED_BY_POLICY: |
3636 | // Page blocked by policy |
3637 | error = "blockedByPolicy"; |
3638 | break; |
3639 | case NS_ERROR_DOM_COOP_FAILED: |
3640 | error = "blockedByCOOP"; |
3641 | errorDescriptionID = "blockedByCORP"; |
3642 | break; |
3643 | case NS_ERROR_DOM_COEP_FAILED: |
3644 | error = "blockedByCOEP"; |
3645 | errorDescriptionID = "blockedByCORP"; |
3646 | break; |
3647 | case NS_ERROR_DOM_INVALID_HEADER_VALUE: |
3648 | error = "invalidHeaderValue"; |
3649 | break; |
3650 | case NS_ERROR_NET_HTTP2_SENT_GOAWAY: |
3651 | case NS_ERROR_NET_HTTP3_PROTOCOL_ERROR: |
3652 | // HTTP/2 or HTTP/3 stack detected a protocol error |
3653 | error = "networkProtocolError"; |
3654 | break; |
3655 | case NS_ERROR_BASIC_HTTP_AUTH_DISABLED: |
3656 | error = "basicHttpAuthDisabled"; |
3657 | break; |
3658 | default: |
3659 | break; |
3660 | } |
3661 | } |
3662 | |
3663 | nsresult delegateErrorCode = aError; |
3664 | // If the HTTPS-Only Mode upgraded this request and the upgrade might have |
3665 | // caused this error, we replace the error-page with about:httpsonlyerror |
3666 | if (nsHTTPSOnlyUtils::CouldBeHttpsOnlyError(aFailedChannel, aError)) { |
3667 | errorPage.AssignLiteral("httpsonlyerror"); |
3668 | delegateErrorCode = NS_ERROR_HTTPS_ONLY; |
3669 | } else if (isBadStsCertError) { |
3670 | delegateErrorCode = NS_ERROR_BAD_HSTS_CERT; |
3671 | } |
3672 | |
3673 | if (nsCOMPtr<nsILoadURIDelegate> loadURIDelegate = GetLoadURIDelegate()) { |
3674 | nsCOMPtr<nsIURI> errorPageURI; |
3675 | rv = loadURIDelegate->HandleLoadError( |
3676 | aURI, delegateErrorCode, NS_ERROR_GET_MODULE(delegateErrorCode), |
3677 | getter_AddRefs(errorPageURI)); |
3678 | // If the docshell is going away there's no point in showing an error page. |
3679 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || mIsBeingDestroyed) { |
3680 | *aDisplayedErrorPage = false; |
3681 | return NS_OK; |
3682 | } |
3683 | |
3684 | if (errorPageURI) { |
3685 | *aDisplayedErrorPage = |
3686 | NS_SUCCEEDED(LoadErrorPage(errorPageURI, aURI, aFailedChannel))((bool)(__builtin_expect(!!(!NS_FAILED_impl(LoadErrorPage(errorPageURI , aURI, aFailedChannel))), 1))); |
3687 | return NS_OK; |
3688 | } |
3689 | } |
3690 | |
3691 | // Test if the error should be displayed |
3692 | if (!error) { |
3693 | return NS_OK; |
3694 | } |
3695 | |
3696 | if (!errorDescriptionID) { |
3697 | errorDescriptionID = error; |
3698 | } |
3699 | |
3700 | Telemetry::AccumulateCategoricalKeyed( |
3701 | IsSubframe() ? "frame"_ns : "top"_ns, |
3702 | mozilla::dom::LoadErrorToTelemetryLabel(aError)); |
3703 | |
3704 | // Test if the error needs to be formatted |
3705 | if (!messageStr.IsEmpty()) { |
3706 | // already obtained message |
3707 | } else { |
3708 | if (addHostPort) { |
3709 | // Build up the host:port string. |
3710 | nsAutoCString hostport; |
3711 | if (aURI) { |
3712 | aURI->GetHostPort(hostport); |
3713 | } else { |
3714 | hostport.Assign('?'); |
3715 | } |
3716 | CopyUTF8toUTF16(hostport, *formatStrs.AppendElement()); |
3717 | } |
3718 | |
3719 | nsAutoCString spec; |
3720 | rv = NS_ERROR_NOT_AVAILABLE; |
3721 | auto& nextFormatStr = *formatStrs.AppendElement(); |
3722 | if (aURI) { |
3723 | // displaying "file://" is aesthetically unpleasing and could even be |
3724 | // confusing to the user |
3725 | if (aURI->SchemeIs("file")) { |
3726 | aURI->GetPathQueryRef(spec); |
3727 | } else { |
3728 | aURI->GetSpec(spec); |
3729 | } |
3730 | |
3731 | nsCOMPtr<nsITextToSubURI> textToSubURI( |
3732 | do_GetService(NS_ITEXTTOSUBURI_CONTRACTID"@mozilla.org/intl/texttosuburi;1", &rv)); |
3733 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) { |
3734 | rv = textToSubURI->UnEscapeURIForUI(spec, nextFormatStr); |
3735 | } |
3736 | } else { |
3737 | spec.Assign('?'); |
3738 | } |
3739 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
3740 | CopyUTF8toUTF16(spec, nextFormatStr); |
3741 | } |
3742 | rv = NS_OK; |
3743 | |
3744 | nsAutoString str; |
3745 | rv = |
3746 | stringBundle->FormatStringFromName(errorDescriptionID, formatStrs, str); |
3747 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 3747); return rv; } } while (false); |
3748 | messageStr.Assign(str); |
3749 | } |
3750 | |
3751 | // Display the error as a page or an alert prompt |
3752 | NS_ENSURE_FALSE(messageStr.IsEmpty(), NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(!(messageStr.IsEmpty()))), 0) )) { NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "!(messageStr.IsEmpty())" ") failed", nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 3752); return NS_ERROR_FAILURE; } } while (false); |
3753 | |
3754 | if ((NS_ERROR_NET_INTERRUPT == aError || NS_ERROR_NET_RESET == aError) && |
3755 | aURI->SchemeIs("https")) { |
3756 | // Maybe TLS intolerant. Treat this as an SSL error. |
3757 | error = "nssFailure2"; |
3758 | } |
3759 | |
3760 | if (mBrowsingContext->GetUseErrorPages()) { |
3761 | // Display an error page |
3762 | nsresult loadedPage = |
3763 | LoadErrorPage(aURI, aURL, errorPage.get(), error, messageStr.get(), |
3764 | cssClass.get(), aFailedChannel); |
3765 | *aDisplayedErrorPage = NS_SUCCEEDED(loadedPage)((bool)(__builtin_expect(!!(!NS_FAILED_impl(loadedPage)), 1)) ); |
3766 | } else { |
3767 | // The prompter reqires that our private window has a document (or it |
3768 | // asserts). Satisfy that assertion now since GetDoc will force |
3769 | // creation of one if it hasn't already been created. |
3770 | if (mScriptGlobal) { |
3771 | Unused << mScriptGlobal->GetDoc(); |
3772 | } |
3773 | |
3774 | // Display a message box |
3775 | prompter->Alert(nullptr, messageStr.get()); |
3776 | } |
3777 | |
3778 | return NS_OK; |
3779 | } |
3780 | |
3781 | #define PREF_SAFEBROWSING_ALLOWOVERRIDE"browser.safebrowsing.allowOverride" "browser.safebrowsing.allowOverride" |
3782 | |
3783 | nsresult nsDocShell::LoadErrorPage(nsIURI* aURI, const char16_t* aURL, |
3784 | const char* aErrorPage, |
3785 | const char* aErrorType, |
3786 | const char16_t* aDescription, |
3787 | const char* aCSSClass, |
3788 | nsIChannel* aFailedChannel) { |
3789 | if (mIsBeingDestroyed) { |
3790 | return NS_ERROR_NOT_AVAILABLE; |
3791 | } |
3792 | |
3793 | #if defined(DEBUG1) |
3794 | if (MOZ_LOG_TEST(gDocShellLog, LogLevel::Debug)(__builtin_expect(!!(mozilla::detail::log_test(gDocShellLog, LogLevel ::Debug)), 0))) { |
3795 | nsAutoCString chanName; |
3796 | if (aFailedChannel) { |
3797 | aFailedChannel->GetName(chanName); |
3798 | } else { |
3799 | chanName.AssignLiteral("<no channel>"); |
3800 | } |
3801 | |
3802 | MOZ_LOG(gDocShellLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gDocShellLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "nsDocShell[%p]::LoadErrorPage(\"%s\", \"%s\", {...}, [%s])\n" , this, aURI ? aURI->GetSpecOrDefault().get() : "", NS_ConvertUTF16toUTF8 (aURL).get(), chanName.get()); } } while (0) |
3803 | ("nsDocShell[%p]::LoadErrorPage(\"%s\", \"%s\", {...}, [%s])\n",do { const ::mozilla::LogModule* moz_real_module = gDocShellLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "nsDocShell[%p]::LoadErrorPage(\"%s\", \"%s\", {...}, [%s])\n" , this, aURI ? aURI->GetSpecOrDefault().get() : "", NS_ConvertUTF16toUTF8 (aURL).get(), chanName.get()); } } while (0) |
3804 | this, aURI ? aURI->GetSpecOrDefault().get() : "",do { const ::mozilla::LogModule* moz_real_module = gDocShellLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "nsDocShell[%p]::LoadErrorPage(\"%s\", \"%s\", {...}, [%s])\n" , this, aURI ? aURI->GetSpecOrDefault().get() : "", NS_ConvertUTF16toUTF8 (aURL).get(), chanName.get()); } } while (0) |
3805 | NS_ConvertUTF16toUTF8(aURL).get(), chanName.get()))do { const ::mozilla::LogModule* moz_real_module = gDocShellLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "nsDocShell[%p]::LoadErrorPage(\"%s\", \"%s\", {...}, [%s])\n" , this, aURI ? aURI->GetSpecOrDefault().get() : "", NS_ConvertUTF16toUTF8 (aURL).get(), chanName.get()); } } while (0); |
3806 | } |
3807 | #endif |
3808 | |
3809 | nsAutoCString url; |
3810 | if (aURI) { |
3811 | nsresult rv = aURI->GetSpec(url); |
3812 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 3812); return rv; } } while (false); |
3813 | } else if (aURL) { |
3814 | CopyUTF16toUTF8(MakeStringSpan(aURL), url); |
3815 | } else { |
3816 | return NS_ERROR_INVALID_POINTER; |
3817 | } |
3818 | |
3819 | // Create a URL to pass all the error information through to the page. |
3820 | |
3821 | #undef SAFE_ESCAPE |
3822 | #define SAFE_ESCAPE(output, input, params)if (NS_warn_if_impl(!NS_Escape(input, output, params), "!NS_Escape(input, output, params)" , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 3822)) { return NS_ERROR_OUT_OF_MEMORY; } \ |
3823 | if (NS_WARN_IF(!NS_Escape(input, output, params))NS_warn_if_impl(!NS_Escape(input, output, params), "!NS_Escape(input, output, params)" , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 3823)) { \ |
3824 | return NS_ERROR_OUT_OF_MEMORY; \ |
3825 | } |
3826 | |
3827 | nsCString escapedUrl, escapedError, escapedDescription, escapedCSSClass; |
3828 | SAFE_ESCAPE(escapedUrl, url, url_Path)if (NS_warn_if_impl(!NS_Escape(url, escapedUrl, url_Path), "!NS_Escape(url, escapedUrl, url_Path)" , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 3828)) { return NS_ERROR_OUT_OF_MEMORY; }; |
3829 | SAFE_ESCAPE(escapedError, nsDependentCString(aErrorType), url_Path)if (NS_warn_if_impl(!NS_Escape(nsDependentCString(aErrorType) , escapedError, url_Path), "!NS_Escape(nsDependentCString(aErrorType), escapedError, url_Path)" , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 3829)) { return NS_ERROR_OUT_OF_MEMORY; }; |
3830 | SAFE_ESCAPE(escapedDescription, NS_ConvertUTF16toUTF8(aDescription),if (NS_warn_if_impl(!NS_Escape(NS_ConvertUTF16toUTF8(aDescription ), escapedDescription, url_Path), "!NS_Escape(NS_ConvertUTF16toUTF8(aDescription), escapedDescription, url_Path)" , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 3831)) { return NS_ERROR_OUT_OF_MEMORY; } |
3831 | url_Path)if (NS_warn_if_impl(!NS_Escape(NS_ConvertUTF16toUTF8(aDescription ), escapedDescription, url_Path), "!NS_Escape(NS_ConvertUTF16toUTF8(aDescription), escapedDescription, url_Path)" , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 3831)) { return NS_ERROR_OUT_OF_MEMORY; }; |
3832 | if (aCSSClass) { |
3833 | nsCString cssClass(aCSSClass); |
3834 | SAFE_ESCAPE(escapedCSSClass, cssClass, url_Path)if (NS_warn_if_impl(!NS_Escape(cssClass, escapedCSSClass, url_Path ), "!NS_Escape(cssClass, escapedCSSClass, url_Path)", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 3834)) { return NS_ERROR_OUT_OF_MEMORY; }; |
3835 | } |
3836 | nsCString errorPageUrl("about:"); |
3837 | errorPageUrl.AppendASCII(aErrorPage); |
3838 | errorPageUrl.AppendLiteral("?e="); |
3839 | |
3840 | errorPageUrl.AppendASCII(escapedError.get()); |
3841 | errorPageUrl.AppendLiteral("&u="); |
3842 | errorPageUrl.AppendASCII(escapedUrl.get()); |
3843 | if ((strcmp(aErrorPage, "blocked") == 0) && |
3844 | Preferences::GetBool(PREF_SAFEBROWSING_ALLOWOVERRIDE"browser.safebrowsing.allowOverride", true)) { |
3845 | errorPageUrl.AppendLiteral("&o=1"); |
3846 | } |
3847 | if (!escapedCSSClass.IsEmpty()) { |
3848 | errorPageUrl.AppendLiteral("&s="); |
3849 | errorPageUrl.AppendASCII(escapedCSSClass.get()); |
3850 | } |
3851 | errorPageUrl.AppendLiteral("&c=UTF-8"); |
3852 | |
3853 | nsCOMPtr<nsICaptivePortalService> cps = do_GetService(NS_CAPTIVEPORTAL_CID{ 0xbdbe0555, 0xfc3d, 0x4f7b, {0x92, 0x05, 0xc3, 0x09, 0xce, 0xb2 , 0xd6, 0x41}}); |
3854 | int32_t cpsState; |
3855 | if (cps && NS_SUCCEEDED(cps->GetState(&cpsState))((bool)(__builtin_expect(!!(!NS_FAILED_impl(cps->GetState( &cpsState))), 1))) && |
3856 | cpsState == nsICaptivePortalService::LOCKED_PORTAL) { |
3857 | errorPageUrl.AppendLiteral("&captive=true"); |
3858 | } |
3859 | |
3860 | errorPageUrl.AppendLiteral("&d="); |
3861 | errorPageUrl.AppendASCII(escapedDescription.get()); |
3862 | |
3863 | nsCOMPtr<nsIURI> errorPageURI; |
3864 | nsresult rv = NS_NewURI(getter_AddRefs(errorPageURI), errorPageUrl); |
3865 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 3865); return rv; } } while (false); |
3866 | |
3867 | return LoadErrorPage(errorPageURI, aURI, aFailedChannel); |
3868 | } |
3869 | |
3870 | nsresult nsDocShell::LoadErrorPage(nsIURI* aErrorURI, nsIURI* aFailedURI, |
3871 | nsIChannel* aFailedChannel) { |
3872 | mFailedChannel = aFailedChannel; |
3873 | mFailedURI = aFailedURI; |
3874 | mFailedLoadType = mLoadType; |
3875 | |
3876 | if (mLSHE) { |
3877 | // Abandon mLSHE's BFCache entry and create a new one. This way, if |
3878 | // we go back or forward to another SHEntry with the same doc |
3879 | // identifier, the error page won't persist. |
3880 | mLSHE->AbandonBFCacheEntry(); |
3881 | } |
3882 | |
3883 | RefPtr<nsDocShellLoadState> loadState = new nsDocShellLoadState(aErrorURI); |
3884 | loadState->SetTriggeringPrincipal(nsContentUtils::GetSystemPrincipal()); |
3885 | if (mBrowsingContext) { |
3886 | loadState->SetTriggeringSandboxFlags(mBrowsingContext->GetSandboxFlags()); |
3887 | loadState->SetTriggeringWindowId( |
3888 | mBrowsingContext->GetCurrentInnerWindowId()); |
3889 | nsPIDOMWindowInner* innerWin = mScriptGlobal->GetCurrentInnerWindow(); |
3890 | if (innerWin) { |
3891 | loadState->SetTriggeringStorageAccess(innerWin->UsingStorageAccess()); |
3892 | } |
3893 | } |
3894 | loadState->SetLoadType(LOAD_ERROR_PAGE); |
3895 | loadState->SetFirstParty(true); |
3896 | loadState->SetSourceBrowsingContext(mBrowsingContext); |
3897 | if (mozilla::SessionHistoryInParent() && mLoadingEntry) { |
3898 | // We keep the loading entry for the load that failed here. If the user |
3899 | // reloads we want to try to reload the original load, not the error page. |
3900 | loadState->SetLoadingSessionHistoryInfo( |
3901 | MakeUnique<LoadingSessionHistoryInfo>(*mLoadingEntry)); |
3902 | } |
3903 | return InternalLoad(loadState); |
3904 | } |
3905 | |
3906 | MOZ_CAN_RUN_SCRIPT_BOUNDARY NS_IMETHODIMPnsresult |
3907 | nsDocShell::Reload(uint32_t aReloadFlags) { |
3908 | return ReloadNavigable(Nothing(), aReloadFlags, nullptr, |
3909 | UserNavigationInvolvement::BrowserUI); |
3910 | } |
3911 | |
3912 | // https://html.spec.whatwg.org/#reload |
3913 | // To reload a navigable navigable given an optional serialized state-or-null |
3914 | // navigationAPIState (default null) and an optional user navigation |
3915 | // involvement userInvolvement (default "none"): |
3916 | nsresult nsDocShell::ReloadNavigable( |
3917 | mozilla::Maybe<NotNull<JSContext*>> aCx, uint32_t aReloadFlags, |
3918 | nsIStructuredCloneContainer* aNavigationAPIState, |
3919 | UserNavigationInvolvement aUserInvolvement) { |
3920 | if (!IsNavigationAllowed()) { |
3921 | return NS_OK; // JS may not handle returning of an error code |
3922 | } |
3923 | |
3924 | NS_ASSERTION(((aReloadFlags & INTERNAL_LOAD_FLAGS_LOADURI_SETUP_FLAGS) == 0),do { if (!(((aReloadFlags & INTERNAL_LOAD_FLAGS_LOADURI_SETUP_FLAGS ) == 0))) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Reload command not updated to use load flags!" , "((aReloadFlags & INTERNAL_LOAD_FLAGS_LOADURI_SETUP_FLAGS) == 0)" , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 3925); MOZ_PretendNoReturn (); } } while (0) |
3925 | "Reload command not updated to use load flags!")do { if (!(((aReloadFlags & INTERNAL_LOAD_FLAGS_LOADURI_SETUP_FLAGS ) == 0))) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Reload command not updated to use load flags!" , "((aReloadFlags & INTERNAL_LOAD_FLAGS_LOADURI_SETUP_FLAGS) == 0)" , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 3925); MOZ_PretendNoReturn (); } } while (0); |
3926 | NS_ASSERTION((aReloadFlags & EXTRA_LOAD_FLAGS) == 0,do { if (!((aReloadFlags & (nsIWebNavigation::LOAD_FLAGS_FROM_EXTERNAL | nsIWebNavigation::LOAD_FLAGS_FIRST_LOAD | nsIWebNavigation ::LOAD_FLAGS_ALLOW_POPUPS | 0xffff0000)) == 0)) { NS_DebugBreak (NS_DEBUG_ASSERTION, "Don't pass these flags to Reload", "(aReloadFlags & EXTRA_LOAD_FLAGS) == 0" , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 3927); MOZ_PretendNoReturn (); } } while (0) |
3927 | "Don't pass these flags to Reload")do { if (!((aReloadFlags & (nsIWebNavigation::LOAD_FLAGS_FROM_EXTERNAL | nsIWebNavigation::LOAD_FLAGS_FIRST_LOAD | nsIWebNavigation ::LOAD_FLAGS_ALLOW_POPUPS | 0xffff0000)) == 0)) { NS_DebugBreak (NS_DEBUG_ASSERTION, "Don't pass these flags to Reload", "(aReloadFlags & EXTRA_LOAD_FLAGS) == 0" , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 3927); MOZ_PretendNoReturn (); } } while (0); |
3928 | |
3929 | uint32_t loadType = MAKE_LOAD_TYPE(LOAD_RELOAD_NORMAL, aReloadFlags)((LOAD_RELOAD_NORMAL) | ((aReloadFlags) << 16)); |
3930 | NS_ENSURE_TRUE(IsValidLoadType(loadType), NS_ERROR_INVALID_ARG)do { if ((__builtin_expect(!!(!(IsValidLoadType(loadType))), 0 ))) { NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "IsValidLoadType(loadType)" ") failed", nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 3930); return NS_ERROR_INVALID_ARG; } } while (false); |
3931 | NS_ENSURE_TRUE(do { if ((__builtin_expect(!!(!(aUserInvolvement == UserNavigationInvolvement ::BrowserUI || aCx)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aUserInvolvement == UserNavigationInvolvement::BrowserUI || aCx" ") failed", nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 3933); return NS_ERROR_INVALID_ARG; } } while (false) |
3932 | aUserInvolvement == UserNavigationInvolvement::BrowserUI || aCx,do { if ((__builtin_expect(!!(!(aUserInvolvement == UserNavigationInvolvement ::BrowserUI || aCx)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aUserInvolvement == UserNavigationInvolvement::BrowserUI || aCx" ") failed", nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 3933); return NS_ERROR_INVALID_ARG; } } while (false) |
3933 | NS_ERROR_INVALID_ARG)do { if ((__builtin_expect(!!(!(aUserInvolvement == UserNavigationInvolvement ::BrowserUI || aCx)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aUserInvolvement == UserNavigationInvolvement::BrowserUI || aCx" ") failed", nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 3933); return NS_ERROR_INVALID_ARG; } } while (false); |
3934 | |
3935 | RefPtr<nsDocShell> docShell(this); |
3936 | |
3937 | // 1. If userInvolvement is not "browser UI", then: |
3938 | if (aUserInvolvement != UserNavigationInvolvement::BrowserUI) { |
3939 | // 1.1 Let navigation be navigable's active window's navigation API. |
3940 | nsPIDOMWindowOuter* windowOuter = GetWindow(); |
3941 | MOZ_DIAGNOSTIC_ASSERT(windowOuter)do { static_assert( mozilla::detail::AssertionConditionType< decltype(windowOuter)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(windowOuter))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("windowOuter", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 3941); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "windowOuter" ")"); do { MOZ_CrashSequence(__null, 3941); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3942 | nsPIDOMWindowInner* windowInner = windowOuter->GetCurrentInnerWindow(); |
3943 | MOZ_DIAGNOSTIC_ASSERT(windowInner)do { static_assert( mozilla::detail::AssertionConditionType< decltype(windowInner)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(windowInner))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("windowInner", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 3943); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "windowInner" ")"); do { MOZ_CrashSequence(__null, 3943); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3944 | RefPtr navigation = windowInner->Navigation(); |
3945 | |
3946 | // 1.2 Let destinationNavigationAPIState be navigable's active session |
3947 | // history entry's navigation API state. |
3948 | // 1.3 If navigationAPIState is not null, then set |
3949 | // destinationNavigationAPIState to navigationAPIState. |
3950 | RefPtr<nsIStructuredCloneContainer> destinationNavigationAPIState = |
3951 | aNavigationAPIState; |
3952 | if (!destinationNavigationAPIState) { |
3953 | destinationNavigationAPIState = |
3954 | mActiveEntry ? mActiveEntry->GetNavigationState() : nullptr; |
3955 | } |
3956 | |
3957 | // 1.4 Let continue be the result of firing a push/replace/reload navigate |
3958 | // event at navigation with navigationType set to "reload", |
3959 | // isSameDocument set to false, userInvolvement set to userInvolvement, |
3960 | // destinationURL set to navigable's active session history entry's URL, |
3961 | // and navigationAPIState set to destinationNavigationAPIState. |
3962 | // 1.5 If continue is false, then return. |
3963 | RefPtr destinationURL = mActiveEntry ? mActiveEntry->GetURI() : nullptr; |
3964 | if (navigation && |
3965 | !navigation->FirePushReplaceReloadNavigateEvent( |
3966 | *aCx, NavigationType::Reload, destinationURL, |
3967 | /* aIsSameDocument */ false, /* aIsSync */ false, |
3968 | Some(aUserInvolvement), |
3969 | /* aSourceElement*/ nullptr, /* aFormDataEntryList */ nullptr, |
3970 | destinationNavigationAPIState, |
3971 | /* aClassiCHistoryAPIState */ nullptr)) { |
3972 | return NS_OK; |
3973 | } |
3974 | } |
3975 | |
3976 | // The following steps are implemented by the remainder of ReloadNavigable. |
3977 | |
3978 | // Send notifications to the HistoryListener if any, about the impending |
3979 | // reload |
3980 | RefPtr<ChildSHistory> rootSH = GetRootSessionHistory(); |
3981 | if (mozilla::SessionHistoryInParent()) { |
3982 | MOZ_LOG(gSHLog, LogLevel::Debug, ("nsDocShell %p Reload", this))do { const ::mozilla::LogModule* moz_real_module = gSHLog; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "nsDocShell %p Reload", this); } } while ( 0); |
3983 | bool forceReload = IsForceReloadType(loadType); |
3984 | if (!XRE_IsParentProcess()) { |
3985 | ++mPendingReloadCount; |
3986 | nsCOMPtr<nsIDocumentViewer> viewer(mDocumentViewer); |
3987 | NS_ENSURE_STATE(viewer)do { if ((__builtin_expect(!!(!(viewer)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "viewer" ") failed", nullptr , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 3987); return NS_ERROR_UNEXPECTED; } } while (false); |
3988 | |
3989 | bool okToUnload = true; |
3990 | MOZ_TRY(viewer->PermitUnload(&okToUnload))__extension__({ auto mozTryVarTempResult = ::mozilla::ToResult (viewer->PermitUnload(&okToUnload)); if ((__builtin_expect (!!(mozTryVarTempResult.isErr()), 0))) { return mozTryVarTempResult .propagateErr(); } mozTryVarTempResult.unwrap(); }); |
3991 | if (!okToUnload) { |
3992 | return NS_OK; |
3993 | } |
3994 | |
3995 | RefPtr<Document> doc(GetDocument()); |
3996 | RefPtr<BrowsingContext> browsingContext(mBrowsingContext); |
3997 | nsCOMPtr<nsIURI> currentURI(mCurrentURI); |
3998 | nsCOMPtr<nsIReferrerInfo> referrerInfo(mReferrerInfo); |
3999 | RefPtr<StopDetector> stopDetector = new StopDetector(); |
4000 | nsCOMPtr<nsILoadGroup> loadGroup; |
4001 | GetLoadGroup(getter_AddRefs(loadGroup)); |
4002 | if (loadGroup) { |
4003 | // loadGroup may be null in theory. In that case stopDetector just |
4004 | // doesn't do anything. |
4005 | loadGroup->AddRequest(stopDetector, nullptr); |
4006 | } |
4007 | |
4008 | ContentChild::GetSingleton()->SendNotifyOnHistoryReload( |
4009 | mBrowsingContext, forceReload, |
4010 | [docShell, doc, loadType, browsingContext, currentURI, referrerInfo, |
4011 | loadGroup, stopDetector]( |
4012 | std::tuple<bool, Maybe<NotNull<RefPtr<nsDocShellLoadState>>>, |
4013 | Maybe<bool>>&& aResult) { |
4014 | auto scopeExit = MakeScopeExit([loadGroup, stopDetector]() { |
4015 | if (loadGroup) { |
4016 | loadGroup->RemoveRequest(stopDetector, nullptr, NS_OK); |
4017 | } |
4018 | }); |
4019 | |
4020 | // Decrease mPendingReloadCount before any other early returns! |
4021 | if (--(docShell->mPendingReloadCount) > 0) { |
4022 | return; |
4023 | } |
4024 | |
4025 | if (stopDetector->Canceled()) { |
4026 | return; |
4027 | } |
4028 | bool canReload; |
4029 | Maybe<NotNull<RefPtr<nsDocShellLoadState>>> loadState; |
4030 | Maybe<bool> reloadingActiveEntry; |
4031 | |
4032 | std::tie(canReload, loadState, reloadingActiveEntry) = aResult; |
4033 | |
4034 | if (!canReload) { |
4035 | return; |
4036 | } |
4037 | |
4038 | if (loadState.isSome()) { |
4039 | MOZ_LOG(do { const ::mozilla::LogModule* moz_real_module = gSHLog; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "nsDocShell %p Reload - LoadHistoryEntry", docShell.get()); } } while (0) |
4040 | gSHLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gSHLog; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "nsDocShell %p Reload - LoadHistoryEntry", docShell.get()); } } while (0) |
4041 | ("nsDocShell %p Reload - LoadHistoryEntry", docShell.get()))do { const ::mozilla::LogModule* moz_real_module = gSHLog; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "nsDocShell %p Reload - LoadHistoryEntry", docShell.get()); } } while (0); |
4042 | loadState.ref()->SetNotifiedBeforeUnloadListeners(true); |
4043 | docShell->LoadHistoryEntry(loadState.ref(), loadType, |
4044 | reloadingActiveEntry.ref()); |
4045 | } else { |
4046 | MOZ_LOG(gSHLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gSHLog; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "nsDocShell %p ReloadDocument", docShell.get ()); } } while (0) |
4047 | ("nsDocShell %p ReloadDocument", docShell.get()))do { const ::mozilla::LogModule* moz_real_module = gSHLog; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "nsDocShell %p ReloadDocument", docShell.get ()); } } while (0); |
4048 | ReloadDocument(docShell, doc, loadType, browsingContext, |
4049 | currentURI, referrerInfo, |
4050 | /* aNotifiedBeforeUnloadListeners */ true); |
4051 | } |
4052 | }, |
4053 | [](mozilla::ipc::ResponseRejectReason) {}); |
4054 | } else { |
4055 | // Parent process |
4056 | bool canReload = false; |
4057 | Maybe<NotNull<RefPtr<nsDocShellLoadState>>> loadState; |
4058 | Maybe<bool> reloadingActiveEntry; |
4059 | if (!mBrowsingContext->IsDiscarded()) { |
4060 | mBrowsingContext->Canonical()->NotifyOnHistoryReload( |
4061 | forceReload, canReload, loadState, reloadingActiveEntry); |
4062 | } |
4063 | if (canReload) { |
4064 | if (loadState.isSome()) { |
4065 | MOZ_LOG(gSHLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gSHLog; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "nsDocShell %p Reload - LoadHistoryEntry", this); } } while (0) |
4066 | ("nsDocShell %p Reload - LoadHistoryEntry", this))do { const ::mozilla::LogModule* moz_real_module = gSHLog; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "nsDocShell %p Reload - LoadHistoryEntry", this); } } while (0); |
4067 | LoadHistoryEntry(loadState.ref(), loadType, |
4068 | reloadingActiveEntry.ref()); |
4069 | } else { |
4070 | MOZ_LOG(gSHLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gSHLog; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "nsDocShell %p ReloadDocument", this); } } while (0) |
4071 | ("nsDocShell %p ReloadDocument", this))do { const ::mozilla::LogModule* moz_real_module = gSHLog; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "nsDocShell %p ReloadDocument", this); } } while (0); |
4072 | RefPtr<Document> doc = GetDocument(); |
4073 | RefPtr<BrowsingContext> bc = mBrowsingContext; |
4074 | nsCOMPtr<nsIURI> currentURI = mCurrentURI; |
4075 | nsCOMPtr<nsIReferrerInfo> referrerInfo = mReferrerInfo; |
4076 | ReloadDocument(this, doc, loadType, bc, currentURI, referrerInfo); |
4077 | } |
4078 | } |
4079 | } |
4080 | return NS_OK; |
4081 | } |
4082 | |
4083 | bool canReload = true; |
4084 | if (rootSH) { |
4085 | rootSH->LegacySHistory()->NotifyOnHistoryReload(&canReload); |
4086 | } |
4087 | |
4088 | if (!canReload) { |
4089 | return NS_OK; |
4090 | } |
4091 | |
4092 | /* If you change this part of code, make sure bug 45297 does not re-occur */ |
4093 | if (mOSHE) { |
4094 | nsCOMPtr<nsISHEntry> oshe = mOSHE; |
4095 | return LoadHistoryEntry( |
4096 | oshe, loadType, |
4097 | aReloadFlags & nsIWebNavigation::LOAD_FLAGS_USER_ACTIVATION); |
4098 | } |
4099 | |
4100 | if (mLSHE) { // In case a reload happened before the current load is done |
4101 | nsCOMPtr<nsISHEntry> lshe = mLSHE; |
4102 | return LoadHistoryEntry( |
4103 | lshe, loadType, |
4104 | aReloadFlags & nsIWebNavigation::LOAD_FLAGS_USER_ACTIVATION); |
4105 | } |
4106 | |
4107 | RefPtr<Document> doc = GetDocument(); |
4108 | RefPtr<BrowsingContext> bc = mBrowsingContext; |
4109 | nsCOMPtr<nsIURI> currentURI = mCurrentURI; |
4110 | nsCOMPtr<nsIReferrerInfo> referrerInfo = mReferrerInfo; |
4111 | return ReloadDocument(this, doc, loadType, bc, currentURI, referrerInfo); |
4112 | } |
4113 | |
4114 | /* static */ |
4115 | nsresult nsDocShell::ReloadDocument(nsDocShell* aDocShell, Document* aDocument, |
4116 | uint32_t aLoadType, |
4117 | BrowsingContext* aBrowsingContext, |
4118 | nsIURI* aCurrentURI, |
4119 | nsIReferrerInfo* aReferrerInfo, |
4120 | bool aNotifiedBeforeUnloadListeners) { |
4121 | if (!aDocument) { |
4122 | return NS_OK; |
4123 | } |
4124 | |
4125 | // Do not inherit owner from document |
4126 | uint32_t flags = INTERNAL_LOAD_FLAGS_NONE; |
4127 | nsAutoString srcdoc; |
4128 | nsIURI* baseURI = nullptr; |
4129 | nsCOMPtr<nsIURI> originalURI; |
4130 | nsCOMPtr<nsIURI> resultPrincipalURI; |
4131 | bool loadReplace = false; |
4132 | |
4133 | nsIPrincipal* triggeringPrincipal = aDocument->NodePrincipal(); |
4134 | nsCOMPtr<nsIContentSecurityPolicy> csp = aDocument->GetCsp(); |
4135 | uint32_t triggeringSandboxFlags = aDocument->GetSandboxFlags(); |
4136 | uint64_t triggeringWindowId = aDocument->InnerWindowID(); |
4137 | bool triggeringStorageAccess = aDocument->UsingStorageAccess(); |
4138 | net::ClassificationFlags triggeringClassificationFlags = |
4139 | aDocument->GetScriptTrackingFlags(); |
4140 | |
4141 | nsAutoString contentTypeHint; |
4142 | aDocument->GetContentType(contentTypeHint); |
4143 | |
4144 | if (aDocument->IsSrcdocDocument()) { |
4145 | aDocument->GetSrcdocData(srcdoc); |
4146 | flags |= INTERNAL_LOAD_FLAGS_IS_SRCDOC; |
4147 | baseURI = aDocument->GetBaseURI(); |
4148 | } else { |
4149 | srcdoc = VoidString(); |
4150 | } |
4151 | nsCOMPtr<nsIChannel> chan = aDocument->GetChannel(); |
4152 | if (chan) { |
4153 | uint32_t loadFlags; |
4154 | chan->GetLoadFlags(&loadFlags); |
4155 | loadReplace = loadFlags & nsIChannel::LOAD_REPLACE; |
4156 | nsCOMPtr<nsIHttpChannel> httpChan(do_QueryInterface(chan)); |
4157 | if (httpChan) { |
4158 | httpChan->GetOriginalURI(getter_AddRefs(originalURI)); |
4159 | } |
4160 | |
4161 | nsCOMPtr<nsILoadInfo> loadInfo = chan->LoadInfo(); |
4162 | loadInfo->GetResultPrincipalURI(getter_AddRefs(resultPrincipalURI)); |
4163 | } |
4164 | |
4165 | if (!triggeringPrincipal) { |
4166 | MOZ_ASSERT(false, "Reload needs a valid triggeringPrincipal")do { static_assert( mozilla::detail::AssertionConditionType< decltype(false)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("false" " (" "Reload needs a valid triggeringPrincipal" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 4166 ); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "Reload needs a valid triggeringPrincipal" ")"); do { MOZ_CrashSequence(__null, 4166); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
4167 | return NS_ERROR_FAILURE; |
4168 | } |
4169 | |
4170 | // Stack variables to ensure changes to the member variables don't affect to |
4171 | // the call. |
4172 | nsCOMPtr<nsIURI> currentURI = aCurrentURI; |
4173 | |
4174 | // Reload always rewrites result principal URI. |
4175 | Maybe<nsCOMPtr<nsIURI>> emplacedResultPrincipalURI; |
4176 | emplacedResultPrincipalURI.emplace(std::move(resultPrincipalURI)); |
4177 | |
4178 | RefPtr<WindowContext> context = aBrowsingContext->GetCurrentWindowContext(); |
4179 | RefPtr<nsDocShellLoadState> loadState = new nsDocShellLoadState(currentURI); |
4180 | loadState->SetReferrerInfo(aReferrerInfo); |
4181 | loadState->SetOriginalURI(originalURI); |
4182 | loadState->SetMaybeResultPrincipalURI(emplacedResultPrincipalURI); |
4183 | loadState->SetLoadReplace(loadReplace); |
4184 | loadState->SetTriggeringPrincipal(triggeringPrincipal); |
4185 | loadState->SetTriggeringSandboxFlags(triggeringSandboxFlags); |
4186 | loadState->SetTriggeringWindowId(triggeringWindowId); |
4187 | loadState->SetTriggeringStorageAccess(triggeringStorageAccess); |
4188 | loadState->SetTriggeringClassificationFlags(triggeringClassificationFlags); |
4189 | loadState->SetPrincipalToInherit(triggeringPrincipal); |
4190 | loadState->SetCsp(csp); |
4191 | loadState->SetInternalLoadFlags(flags); |
4192 | loadState->SetTypeHint(NS_ConvertUTF16toUTF8(contentTypeHint)); |
4193 | loadState->SetLoadType(aLoadType); |
4194 | loadState->SetFirstParty(true); |
4195 | loadState->SetSrcdocData(srcdoc); |
4196 | loadState->SetSourceBrowsingContext(aBrowsingContext); |
4197 | loadState->SetBaseURI(baseURI); |
4198 | loadState->SetHasValidUserGestureActivation( |
4199 | context && context->HasValidTransientUserGestureActivation()); |
4200 | |
4201 | loadState->SetTextDirectiveUserActivation( |
4202 | aDocument->ConsumeTextDirectiveUserActivation() || |
4203 | loadState->HasValidUserGestureActivation()); |
4204 | |
4205 | loadState->SetNotifiedBeforeUnloadListeners(aNotifiedBeforeUnloadListeners); |
4206 | return aDocShell->InternalLoad(loadState); |
4207 | } |
4208 | |
4209 | // TODO: Convert this to MOZ_CAN_RUN_SCRIPT (bug 1415230) |
4210 | MOZ_CAN_RUN_SCRIPT_BOUNDARY NS_IMETHODIMPnsresult |
4211 | nsDocShell::Stop(uint32_t aStopFlags) { |
4212 | RefPtr kungFuDeathGrip = this; |
4213 | if (RefPtr<Document> doc = GetDocument(); doc && !doc->ShouldIgnoreOpens()) { |
4214 | SetOngoingNavigation(Nothing()); |
4215 | } |
4216 | |
4217 | // Revoke any pending event related to content viewer restoration |
4218 | mRestorePresentationEvent.Revoke(); |
4219 | |
4220 | if (mLoadType == LOAD_ERROR_PAGE) { |
4221 | if (mLSHE) { |
4222 | // Since error page loads never unset mLSHE, do so now |
4223 | SetHistoryEntryAndUpdateBC(Some(nullptr), Some<nsISHEntry*>(mLSHE)); |
4224 | } |
4225 | mActiveEntryIsLoadingFromSessionHistory = false; |
4226 | |
4227 | mFailedChannel = nullptr; |
4228 | mFailedURI = nullptr; |
4229 | } |
4230 | |
4231 | if (nsIWebNavigation::STOP_CONTENT & aStopFlags) { |
4232 | // Stop the document loading and animations |
4233 | if (mDocumentViewer) { |
4234 | nsCOMPtr<nsIDocumentViewer> viewer = mDocumentViewer; |
4235 | viewer->Stop(); |
4236 | } |
4237 | } else if (nsIWebNavigation::STOP_NETWORK & aStopFlags) { |
4238 | // Stop the document loading only |
4239 | if (mDocumentViewer) { |
4240 | RefPtr<Document> doc = mDocumentViewer->GetDocument(); |
4241 | if (doc) { |
4242 | doc->StopDocumentLoad(); |
4243 | } |
4244 | } |
4245 | } |
4246 | |
4247 | if (nsIWebNavigation::STOP_NETWORK & aStopFlags) { |
4248 | // Suspend any timers that were set for this loader. We'll clear |
4249 | // them out for good in CreateDocumentViewer. |
4250 | if (mRefreshURIList) { |
4251 | SuspendRefreshURIs(); |
4252 | mSavedRefreshURIList.swap(mRefreshURIList); |
4253 | mRefreshURIList = nullptr; |
4254 | } |
4255 | |
4256 | // XXXbz We could also pass |this| to nsIURILoader::Stop. That will |
4257 | // just call Stop() on us as an nsIDocumentLoader... We need fewer |
4258 | // redundant apis! |
4259 | Stop(); |
4260 | |
4261 | // Clear out mChannelToDisconnectOnPageHide. This page won't go in the |
4262 | // BFCache now, and the Stop above will have removed the DocumentChannel |
4263 | // from the loadgroup. |
4264 | mChannelToDisconnectOnPageHide = 0; |
4265 | } |
4266 | |
4267 | for (auto* child : mChildList.ForwardRange()) { |
4268 | nsCOMPtr<nsIWebNavigation> shellAsNav(do_QueryObject(child)); |
4269 | if (shellAsNav) { |
4270 | shellAsNav->Stop(aStopFlags); |
4271 | } |
4272 | } |
4273 | |
4274 | return NS_OK; |
4275 | } |
4276 | |
4277 | NS_IMETHODIMPnsresult |
4278 | nsDocShell::GetDocument(Document** aDocument) { |
4279 | NS_ENSURE_ARG_POINTER(aDocument)do { if ((__builtin_expect(!!(!(aDocument)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aDocument" ") failed", nullptr , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 4279); return NS_ERROR_INVALID_POINTER; } } while (false); |
4280 | NS_ENSURE_SUCCESS(EnsureDocumentViewer(), NS_ERROR_FAILURE)do { nsresult __rv = EnsureDocumentViewer(); if (((bool)(__builtin_expect (!!(NS_FAILED_impl(__rv)), 0)))) { const char* name = mozilla ::GetStaticErrorName(__rv); mozilla::SmprintfPointer msg = mozilla ::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "EnsureDocumentViewer()", "NS_ERROR_FAILURE", static_cast <uint32_t>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 4280); return NS_ERROR_FAILURE; } } while (false); |
4281 | |
4282 | RefPtr<Document> doc = mDocumentViewer->GetDocument(); |
4283 | if (!doc) { |
4284 | return NS_ERROR_NOT_AVAILABLE; |
4285 | } |
4286 | |
4287 | doc.forget(aDocument); |
4288 | return NS_OK; |
4289 | } |
4290 | |
4291 | NS_IMETHODIMPnsresult |
4292 | nsDocShell::GetCurrentURI(nsIURI** aURI) { |
4293 | NS_ENSURE_ARG_POINTER(aURI)do { if ((__builtin_expect(!!(!(aURI)), 0))) { NS_DebugBreak( NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aURI" ") failed", nullptr , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 4293); return NS_ERROR_INVALID_POINTER; } } while (false); |
4294 | |
4295 | nsCOMPtr<nsIURI> uri = mCurrentURI; |
4296 | uri.forget(aURI); |
4297 | return NS_OK; |
4298 | } |
4299 | |
4300 | NS_IMETHODIMPnsresult |
4301 | nsDocShell::GetSessionHistoryXPCOM(nsISupports** aSessionHistory) { |
4302 | NS_ENSURE_ARG_POINTER(aSessionHistory)do { if ((__builtin_expect(!!(!(aSessionHistory)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aSessionHistory" ") failed" , nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 4302); return NS_ERROR_INVALID_POINTER; } } while (false); |
4303 | RefPtr<ChildSHistory> shistory = GetSessionHistory(); |
4304 | shistory.forget(aSessionHistory); |
4305 | return NS_OK; |
4306 | } |
4307 | |
4308 | //***************************************************************************** |
4309 | // nsDocShell::nsIWebPageDescriptor |
4310 | //***************************************************************************** |
4311 | |
4312 | NS_IMETHODIMPnsresult |
4313 | nsDocShell::LoadPageAsViewSource(nsIDocShell* aOtherDocShell, |
4314 | const nsAString& aURI) { |
4315 | if (!aOtherDocShell) { |
4316 | return NS_ERROR_INVALID_POINTER; |
4317 | } |
4318 | nsCOMPtr<nsIURI> newURI; |
4319 | nsresult rv = NS_NewURI(getter_AddRefs(newURI), aURI); |
4320 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
4321 | return rv; |
4322 | } |
4323 | |
4324 | RefPtr<nsDocShellLoadState> loadState; |
4325 | uint32_t cacheKey; |
4326 | auto* otherDocShell = nsDocShell::Cast(aOtherDocShell); |
4327 | if (mozilla::SessionHistoryInParent()) { |
4328 | loadState = new nsDocShellLoadState(newURI); |
4329 | if (!otherDocShell->FillLoadStateFromCurrentEntry(*loadState)) { |
4330 | return NS_ERROR_INVALID_POINTER; |
4331 | } |
4332 | cacheKey = otherDocShell->GetCacheKeyFromCurrentEntry().valueOr(0); |
4333 | } else { |
4334 | nsCOMPtr<nsISHEntry> entry; |
4335 | bool isOriginalSHE; |
4336 | otherDocShell->GetCurrentSHEntry(getter_AddRefs(entry), &isOriginalSHE); |
4337 | if (!entry) { |
4338 | return NS_ERROR_INVALID_POINTER; |
4339 | } |
4340 | rv = entry->CreateLoadInfo(getter_AddRefs(loadState)); |
4341 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 4341); return rv; } } while (false); |
4342 | entry->GetCacheKey(&cacheKey); |
4343 | loadState->SetURI(newURI); |
4344 | loadState->SetSHEntry(nullptr); |
4345 | } |
4346 | |
4347 | // We're doing a load of the page, via an API that |
4348 | // is only exposed to system code. The triggering principal for this load |
4349 | // should be the system principal. |
4350 | loadState->SetTriggeringPrincipal(nsContentUtils::GetSystemPrincipal()); |
4351 | loadState->SetOriginalURI(nullptr); |
4352 | loadState->SetResultPrincipalURI(nullptr); |
4353 | |
4354 | return InternalLoad(loadState, Some(cacheKey)); |
4355 | } |
4356 | |
4357 | NS_IMETHODIMPnsresult |
4358 | nsDocShell::GetCurrentDescriptor(nsISupports** aPageDescriptor) { |
4359 | MOZ_ASSERT(aPageDescriptor, "Null out param?")do { static_assert( mozilla::detail::AssertionConditionType< decltype(aPageDescriptor)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aPageDescriptor))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aPageDescriptor" " (" "Null out param?" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 4359); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPageDescriptor" ") (" "Null out param?" ")"); do { MOZ_CrashSequence(__null, 4359); __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
4360 | |
4361 | *aPageDescriptor = nullptr; |
4362 | |
4363 | nsISHEntry* src = mOSHE ? mOSHE : mLSHE; |
4364 | if (src) { |
4365 | nsCOMPtr<nsISHEntry> dest; |
4366 | |
4367 | nsresult rv = src->Clone(getter_AddRefs(dest)); |
4368 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
4369 | return rv; |
4370 | } |
4371 | |
4372 | // null out inappropriate cloned attributes... |
4373 | dest->SetParent(nullptr); |
4374 | dest->SetIsSubFrame(false); |
4375 | |
4376 | return CallQueryInterface(dest, aPageDescriptor); |
4377 | } |
4378 | |
4379 | return NS_ERROR_NOT_AVAILABLE; |
4380 | } |
4381 | |
4382 | already_AddRefed<nsIInputStream> nsDocShell::GetPostDataFromCurrentEntry() |
4383 | const { |
4384 | nsCOMPtr<nsIInputStream> postData; |
4385 | if (mozilla::SessionHistoryInParent()) { |
4386 | if (mActiveEntry) { |
4387 | postData = mActiveEntry->GetPostData(); |
4388 | } else if (mLoadingEntry) { |
4389 | postData = mLoadingEntry->mInfo.GetPostData(); |
4390 | } |
4391 | } else { |
4392 | if (mOSHE) { |
4393 | postData = mOSHE->GetPostData(); |
4394 | } else if (mLSHE) { |
4395 | postData = mLSHE->GetPostData(); |
4396 | } |
4397 | } |
4398 | |
4399 | return postData.forget(); |
4400 | } |
4401 | |
4402 | Maybe<uint32_t> nsDocShell::GetCacheKeyFromCurrentEntry() const { |
4403 | if (mozilla::SessionHistoryInParent()) { |
4404 | if (mActiveEntry) { |
4405 | return Some(mActiveEntry->GetCacheKey()); |
4406 | } |
4407 | |
4408 | if (mLoadingEntry) { |
4409 | return Some(mLoadingEntry->mInfo.GetCacheKey()); |
4410 | } |
4411 | } else { |
4412 | if (mOSHE) { |
4413 | return Some(mOSHE->GetCacheKey()); |
4414 | } |
4415 | |
4416 | if (mLSHE) { |
4417 | return Some(mLSHE->GetCacheKey()); |
4418 | } |
4419 | } |
4420 | |
4421 | return Nothing(); |
4422 | } |
4423 | |
4424 | bool nsDocShell::FillLoadStateFromCurrentEntry( |
4425 | nsDocShellLoadState& aLoadState) { |
4426 | if (mLoadingEntry) { |
4427 | mLoadingEntry->mInfo.FillLoadInfo(aLoadState); |
4428 | return true; |
4429 | } |
4430 | if (mActiveEntry) { |
4431 | mActiveEntry->FillLoadInfo(aLoadState); |
4432 | return true; |
4433 | } |
4434 | return false; |
4435 | } |
4436 | |
4437 | //***************************************************************************** |
4438 | // nsDocShell::nsIBaseWindow |
4439 | //***************************************************************************** |
4440 | |
4441 | NS_IMETHODIMPnsresult |
4442 | nsDocShell::InitWindow(nsIWidget* aParentWidget, int32_t aX, int32_t aY, |
4443 | int32_t aWidth, int32_t aHeight) { |
4444 | SetParentWidget(aParentWidget); |
4445 | SetPositionAndSize(aX, aY, aWidth, aHeight, 0); |
4446 | NS_ENSURE_TRUE(Initialize(), NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(Initialize())), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "Initialize()" ") failed" , nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 4446); return NS_ERROR_FAILURE; } } while (false); |
4447 | return NS_OK; |
4448 | } |
4449 | |
4450 | NS_IMETHODIMPnsresult |
4451 | nsDocShell::Destroy() { |
4452 | // XXX: We allow this function to be called just once. If you are going to |
4453 | // reset new variables in this function, please make sure the variables will |
4454 | // never be re-initialized. Adding assertions to check |mIsBeingDestroyed| |
4455 | // in the setter functions for the variables would be enough. |
4456 | if (mIsBeingDestroyed) { |
4457 | return NS_ERROR_DOCSHELL_DYING; |
4458 | } |
4459 | |
4460 | NS_ASSERTION(mItemType == typeContent || mItemType == typeChrome,do { if (!(mItemType == typeContent || mItemType == typeChrome )) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Unexpected item type in docshell" , "mItemType == typeContent || mItemType == typeChrome", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 4461); MOZ_PretendNoReturn(); } } while (0) |
4461 | "Unexpected item type in docshell")do { if (!(mItemType == typeContent || mItemType == typeChrome )) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Unexpected item type in docshell" , "mItemType == typeContent || mItemType == typeChrome", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 4461); MOZ_PretendNoReturn(); } } while (0); |
4462 | |
4463 | nsCOMPtr<nsIObserverService> serv = services::GetObserverService(); |
4464 | if (serv) { |
4465 | const char* msg = mItemType == typeContent |
4466 | ? NS_WEBNAVIGATION_DESTROY"webnavigation-destroy" |
4467 | : NS_CHROME_WEBNAVIGATION_DESTROY"chrome-webnavigation-destroy"; |
4468 | serv->NotifyObservers(GetAsSupports(this), msg, nullptr); |
4469 | } |
4470 | |
4471 | mIsBeingDestroyed = true; |
4472 | |
4473 | // Brak the cycle with the initial client, if present. |
4474 | mInitialClientSource.reset(); |
4475 | |
4476 | // Make sure to blow away our mLoadingURI just in case. No loads |
4477 | // from inside this pagehide. |
4478 | mLoadingURI = nullptr; |
4479 | |
4480 | // Fire unload event before we blow anything away. |
4481 | (void)FirePageHideNotification(true); |
4482 | |
4483 | // Clear pointers to any detached nsEditorData that's lying |
4484 | // around in shistory entries. Breaks cycle. See bug 430921. |
4485 | if (mOSHE) { |
4486 | mOSHE->SetEditorData(nullptr); |
4487 | } |
4488 | if (mLSHE) { |
4489 | mLSHE->SetEditorData(nullptr); |
4490 | } |
4491 | |
4492 | // Note: mContentListener can be null if Init() failed and we're being |
4493 | // called from the destructor. |
4494 | if (mContentListener) { |
4495 | mContentListener->DropDocShellReference(); |
4496 | mContentListener->SetParentContentListener(nullptr); |
4497 | // Note that we do NOT set mContentListener to null here; that |
4498 | // way if someone tries to do a load in us after this point |
4499 | // the nsDSURIContentListener will block it. All of which |
4500 | // means that we should do this before calling Stop(), of |
4501 | // course. |
4502 | } |
4503 | |
4504 | // Stop any URLs that are currently being loaded... |
4505 | Stop(nsIWebNavigation::STOP_ALL); |
4506 | |
4507 | mEditorData = nullptr; |
4508 | |
4509 | // Save the state of the current document, before destroying the window. |
4510 | // This is needed to capture the state of a frameset when the new document |
4511 | // causes the frameset to be destroyed... |
4512 | PersistLayoutHistoryState(); |
4513 | |
4514 | // Remove this docshell from its parent's child list |
4515 | nsCOMPtr<nsIDocShellTreeItem> docShellParentAsItem = |
4516 | do_QueryInterface(GetAsSupports(mParent)); |
4517 | if (docShellParentAsItem) { |
4518 | docShellParentAsItem->RemoveChild(this); |
4519 | } |
4520 | |
4521 | if (mDocumentViewer) { |
4522 | mDocumentViewer->Close(nullptr); |
4523 | mDocumentViewer->Destroy(); |
4524 | mDocumentViewer = nullptr; |
4525 | } |
4526 | |
4527 | nsDocLoader::Destroy(); |
4528 | |
4529 | mParentWidget = nullptr; |
4530 | SetCurrentURIInternal(nullptr); |
4531 | |
4532 | if (mScriptGlobal) { |
4533 | mScriptGlobal->DetachFromDocShell(!mWillChangeProcess); |
4534 | mScriptGlobal = nullptr; |
4535 | } |
4536 | |
4537 | if (GetSessionHistory()) { |
4538 | // We want to destroy these content viewers now rather than |
4539 | // letting their destruction wait for the session history |
4540 | // entries to get garbage collected. (Bug 488394) |
4541 | GetSessionHistory()->EvictLocalDocumentViewers(); |
4542 | } |
4543 | |
4544 | if (mWillChangeProcess && !mBrowsingContext->IsDiscarded()) { |
4545 | mBrowsingContext->PrepareForProcessChange(); |
4546 | } |
4547 | |
4548 | SetTreeOwner(nullptr); |
4549 | |
4550 | mBrowserChild = nullptr; |
4551 | |
4552 | mChromeEventHandler = nullptr; |
4553 | |
4554 | mBCWebProgressStatusFilter = nullptr; |
4555 | |
4556 | // Cancel any timers that were set for this docshell; this is needed |
4557 | // to break the cycle between us and the timers. |
4558 | CancelRefreshURITimers(); |
4559 | |
4560 | return NS_OK; |
4561 | } |
4562 | |
4563 | double nsDocShell::GetWidgetCSSToDeviceScale() { |
4564 | if (mParentWidget) { |
4565 | return mParentWidget->GetDefaultScale().scale; |
4566 | } |
4567 | if (nsCOMPtr<nsIBaseWindow> ownerWindow = do_QueryInterface(mTreeOwner)) { |
4568 | return ownerWindow->GetWidgetCSSToDeviceScale(); |
4569 | } |
4570 | return 1.0; |
4571 | } |
4572 | |
4573 | NS_IMETHODIMPnsresult |
4574 | nsDocShell::GetDevicePixelsPerDesktopPixel(double* aScale) { |
4575 | if (mParentWidget) { |
4576 | *aScale = mParentWidget->GetDesktopToDeviceScale().scale; |
4577 | return NS_OK; |
4578 | } |
4579 | |
4580 | nsCOMPtr<nsIBaseWindow> ownerWindow(do_QueryInterface(mTreeOwner)); |
4581 | if (ownerWindow) { |
4582 | return ownerWindow->GetDevicePixelsPerDesktopPixel(aScale); |
4583 | } |
4584 | |
4585 | *aScale = 1.0; |
4586 | return NS_OK; |
4587 | } |
4588 | |
4589 | NS_IMETHODIMPnsresult |
4590 | nsDocShell::SetPosition(int32_t aX, int32_t aY) { |
4591 | mBounds.MoveTo(aX, aY); |
4592 | |
4593 | if (mDocumentViewer) { |
4594 | NS_ENSURE_SUCCESS(mDocumentViewer->Move(aX, aY), NS_ERROR_FAILURE)do { nsresult __rv = mDocumentViewer->Move(aX, aY); if ((( bool)(__builtin_expect(!!(NS_FAILED_impl(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "mDocumentViewer->Move(aX, aY)" , "NS_ERROR_FAILURE", static_cast<uint32_t>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""); NS_DebugBreak (NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 4594); return NS_ERROR_FAILURE; } } while (false); |
4595 | } |
4596 | |
4597 | return NS_OK; |
4598 | } |
4599 | |
4600 | NS_IMETHODIMPnsresult |
4601 | nsDocShell::SetPositionDesktopPix(int32_t aX, int32_t aY) { |
4602 | nsCOMPtr<nsIBaseWindow> ownerWindow(do_QueryInterface(mTreeOwner)); |
4603 | if (ownerWindow) { |
4604 | return ownerWindow->SetPositionDesktopPix(aX, aY); |
4605 | } |
4606 | |
4607 | double scale = 1.0; |
4608 | GetDevicePixelsPerDesktopPixel(&scale); |
4609 | return SetPosition(NSToIntRound(aX * scale), NSToIntRound(aY * scale)); |
4610 | } |
4611 | |
4612 | NS_IMETHODIMPnsresult |
4613 | nsDocShell::GetPosition(int32_t* aX, int32_t* aY) { |
4614 | return GetPositionAndSize(aX, aY, nullptr, nullptr); |
4615 | } |
4616 | |
4617 | NS_IMETHODIMPnsresult |
4618 | nsDocShell::SetSize(int32_t aWidth, int32_t aHeight, bool aRepaint) { |
4619 | int32_t x = 0, y = 0; |
4620 | GetPosition(&x, &y); |
4621 | return SetPositionAndSize(x, y, aWidth, aHeight, |
4622 | aRepaint ? nsIBaseWindow::eRepaint : 0); |
4623 | } |
4624 | |
4625 | NS_IMETHODIMPnsresult |
4626 | nsDocShell::GetSize(int32_t* aWidth, int32_t* aHeight) { |
4627 | return GetPositionAndSize(nullptr, nullptr, aWidth, aHeight); |
4628 | } |
4629 | |
4630 | NS_IMETHODIMPnsresult |
4631 | nsDocShell::SetPositionAndSize(int32_t aX, int32_t aY, int32_t aWidth, |
4632 | int32_t aHeight, uint32_t aFlags) { |
4633 | mBounds.SetRect(aX, aY, aWidth, aHeight); |
4634 | |
4635 | // Hold strong ref, since SetBounds can make us null out mDocumentViewer |
4636 | nsCOMPtr<nsIDocumentViewer> viewer = mDocumentViewer; |
4637 | if (viewer) { |
4638 | uint32_t cvflags = (aFlags & nsIBaseWindow::eDelayResize) |
4639 | ? nsIDocumentViewer::eDelayResize |
4640 | : 0; |
4641 | // XXX Border figured in here or is that handled elsewhere? |
4642 | nsresult rv = viewer->SetBoundsWithFlags(mBounds, cvflags); |
4643 | NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "NS_ERROR_FAILURE", static_cast <uint32_t>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 4643); return NS_ERROR_FAILURE; } } while (false); |
4644 | } |
4645 | |
4646 | return NS_OK; |
4647 | } |
4648 | |
4649 | NS_IMETHODIMPnsresult |
4650 | nsDocShell::GetPositionAndSize(int32_t* aX, int32_t* aY, int32_t* aWidth, |
4651 | int32_t* aHeight) { |
4652 | if (mParentWidget) { |
4653 | // ensure size is up-to-date if window has changed resolution |
4654 | LayoutDeviceIntRect r = mParentWidget->GetClientBounds(); |
4655 | SetPositionAndSize(mBounds.X(), mBounds.Y(), r.Width(), r.Height(), 0); |
4656 | } |
4657 | |
4658 | // We should really consider just getting this information from |
4659 | // our window instead of duplicating the storage and code... |
4660 | if (aWidth || aHeight) { |
4661 | // Caller wants to know our size; make sure to give them up to |
4662 | // date information. |
4663 | RefPtr<Document> doc(do_GetInterface(GetAsSupports(mParent))); |
4664 | if (doc) { |
4665 | doc->FlushPendingNotifications(FlushType::Layout); |
4666 | } |
4667 | } |
4668 | |
4669 | DoGetPositionAndSize(aX, aY, aWidth, aHeight); |
4670 | return NS_OK; |
4671 | } |
4672 | |
4673 | void nsDocShell::DoGetPositionAndSize(int32_t* aX, int32_t* aY, int32_t* aWidth, |
4674 | int32_t* aHeight) { |
4675 | if (aX) { |
4676 | *aX = mBounds.X(); |
4677 | } |
4678 | if (aY) { |
4679 | *aY = mBounds.Y(); |
4680 | } |
4681 | if (aWidth) { |
4682 | *aWidth = mBounds.Width(); |
4683 | } |
4684 | if (aHeight) { |
4685 | *aHeight = mBounds.Height(); |
4686 | } |
4687 | } |
4688 | |
4689 | NS_IMETHODIMPnsresult |
4690 | nsDocShell::SetDimensions(DimensionRequest&& aRequest) { |
4691 | return NS_ERROR_NOT_IMPLEMENTED; |
4692 | } |
4693 | |
4694 | NS_IMETHODIMPnsresult |
4695 | nsDocShell::GetDimensions(DimensionKind aDimensionKind, int32_t* aX, |
4696 | int32_t* aY, int32_t* aCX, int32_t* aCY) { |
4697 | return NS_ERROR_NOT_IMPLEMENTED; |
4698 | } |
4699 | |
4700 | NS_IMETHODIMPnsresult |
4701 | nsDocShell::Repaint(bool aForce) { |
4702 | PresShell* presShell = GetPresShell(); |
4703 | NS_ENSURE_TRUE(presShell, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(presShell)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "presShell" ") failed", nullptr , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 4703); return NS_ERROR_FAILURE; } } while (false); |
4704 | |
4705 | RefPtr<nsViewManager> viewManager = presShell->GetViewManager(); |
4706 | NS_ENSURE_TRUE(viewManager, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(viewManager)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "viewManager" ") failed" , nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 4706); return NS_ERROR_FAILURE; } } while (false); |
4707 | |
4708 | viewManager->InvalidateAllViews(); |
4709 | return NS_OK; |
4710 | } |
4711 | |
4712 | NS_IMETHODIMPnsresult |
4713 | nsDocShell::GetParentWidget(nsIWidget** aParentWidget) { |
4714 | NS_ENSURE_ARG_POINTER(aParentWidget)do { if ((__builtin_expect(!!(!(aParentWidget)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aParentWidget" ") failed" , nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 4714); return NS_ERROR_INVALID_POINTER; } } while (false); |
4715 | |
4716 | *aParentWidget = mParentWidget; |
4717 | NS_IF_ADDREF(*aParentWidget)ns_if_addref(*aParentWidget); |
4718 | |
4719 | return NS_OK; |
4720 | } |
4721 | |
4722 | NS_IMETHODIMPnsresult |
4723 | nsDocShell::SetParentWidget(nsIWidget* aParentWidget) { |
4724 | MOZ_ASSERT(!mIsBeingDestroyed)do { static_assert( mozilla::detail::AssertionConditionType< decltype(!mIsBeingDestroyed)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!mIsBeingDestroyed))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!mIsBeingDestroyed" , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 4724); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "!mIsBeingDestroyed" ")"); do { MOZ_CrashSequence (__null, 4724); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); |
4725 | mParentWidget = aParentWidget; |
4726 | |
4727 | return NS_OK; |
4728 | } |
4729 | |
4730 | NS_IMETHODIMPnsresult |
4731 | nsDocShell::GetNativeHandle(nsAString& aNativeHandle) { |
4732 | // the nativeHandle should be accessed from nsIAppWindow |
4733 | return NS_ERROR_NOT_IMPLEMENTED; |
4734 | } |
4735 | |
4736 | NS_IMETHODIMPnsresult |
4737 | nsDocShell::GetVisibility(bool* aVisibility) { |
4738 | NS_ENSURE_ARG_POINTER(aVisibility)do { if ((__builtin_expect(!!(!(aVisibility)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aVisibility" ") failed" , nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 4738); return NS_ERROR_INVALID_POINTER; } } while (false); |
4739 | |
4740 | *aVisibility = false; |
4741 | |
4742 | if (!mDocumentViewer) { |
4743 | return NS_OK; |
4744 | } |
4745 | |
4746 | PresShell* presShell = GetPresShell(); |
4747 | if (!presShell) { |
4748 | return NS_OK; |
4749 | } |
4750 | |
4751 | // get the view manager |
4752 | nsViewManager* vm = presShell->GetViewManager(); |
4753 | NS_ENSURE_TRUE(vm, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(vm)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING , "NS_ENSURE_TRUE(" "vm" ") failed", nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 4753); return NS_ERROR_FAILURE; } } while (false); |
4754 | |
4755 | // get the root view |
4756 | nsView* view = vm->GetRootView(); // views are not ref counted |
4757 | NS_ENSURE_TRUE(view, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(view)), 0))) { NS_DebugBreak( NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "view" ") failed", nullptr , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 4757); return NS_ERROR_FAILURE; } } while (false); |
4758 | |
4759 | // if our root view is hidden, we are not visible |
4760 | if (view->GetVisibility() == ViewVisibility::Hide) { |
4761 | return NS_OK; |
4762 | } |
4763 | |
4764 | // otherwise, we must walk up the document and view trees checking |
4765 | // for a hidden view, unless we're an off screen browser, which |
4766 | // would make this test meaningless. |
4767 | |
4768 | RefPtr<nsDocShell> docShell = this; |
4769 | RefPtr<nsDocShell> parentItem = docShell->GetInProcessParentDocshell(); |
4770 | while (parentItem) { |
4771 | // Null-check for crash in bug 267804 |
4772 | if (!parentItem->GetPresShell()) { |
4773 | MOZ_ASSERT_UNREACHABLE("parent docshell has null pres shell")do { static_assert( mozilla::detail::AssertionConditionType< decltype(false)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: " "parent docshell has null pres shell" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 4773); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: " "parent docshell has null pres shell" ")"); do { MOZ_CrashSequence(__null, 4773); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
4774 | return NS_OK; |
4775 | } |
4776 | |
4777 | vm = docShell->GetPresShell()->GetViewManager(); |
4778 | if (vm) { |
4779 | view = vm->GetRootView(); |
4780 | } |
4781 | |
4782 | if (view) { |
4783 | view = view->GetParent(); // anonymous inner view |
4784 | if (view) { |
4785 | view = view->GetParent(); // subdocumentframe's view |
4786 | } |
4787 | } |
4788 | |
4789 | nsIFrame* frame = view ? view->GetFrame() : nullptr; |
4790 | if (frame && !frame->IsVisibleConsideringAncestors( |
4791 | nsIFrame::VISIBILITY_CROSS_CHROME_CONTENT_BOUNDARY)) { |
4792 | return NS_OK; |
4793 | } |
4794 | |
4795 | docShell = parentItem; |
4796 | parentItem = docShell->GetInProcessParentDocshell(); |
4797 | } |
4798 | |
4799 | nsCOMPtr<nsIBaseWindow> treeOwnerAsWin(do_QueryInterface(mTreeOwner)); |
4800 | if (!treeOwnerAsWin) { |
4801 | *aVisibility = true; |
4802 | return NS_OK; |
4803 | } |
4804 | |
4805 | // Check with the tree owner as well to give embedders a chance to |
4806 | // expose visibility as well. |
4807 | nsresult rv = treeOwnerAsWin->GetVisibility(aVisibility); |
4808 | if (rv == NS_ERROR_NOT_IMPLEMENTED) { |
4809 | // The tree owner had no opinion on our visibility. |
4810 | *aVisibility = true; |
4811 | return NS_OK; |
4812 | } |
4813 | return rv; |
4814 | } |
4815 | |
4816 | void nsDocShell::ActivenessMaybeChanged() { |
4817 | const bool isActive = mBrowsingContext->IsActive(); |
4818 | if (RefPtr<PresShell> presShell = GetPresShell()) { |
4819 | presShell->ActivenessMaybeChanged(); |
4820 | } |
4821 | |
4822 | // Tell the window about it |
4823 | if (mScriptGlobal) { |
4824 | mScriptGlobal->SetIsBackground(!isActive); |
4825 | if (RefPtr<Document> doc = mScriptGlobal->GetExtantDoc()) { |
4826 | // Update orientation when the top-level browsing context becomes active. |
4827 | if (isActive && mBrowsingContext->IsTop() && |
4828 | !mBrowsingContext->Windowless()) { |
4829 | // We only care about the top-level browsing context. |
4830 | auto orientation = mBrowsingContext->GetOrientationLock(); |
4831 | ScreenOrientation::UpdateActiveOrientationLock(orientation); |
4832 | } |
4833 | |
4834 | doc->PostVisibilityUpdateEvent(); |
4835 | } |
4836 | } |
4837 | |
4838 | // Tell the nsDOMNavigationTiming about it |
4839 | RefPtr<nsDOMNavigationTiming> timing = mTiming; |
4840 | if (!timing && mDocumentViewer) { |
4841 | if (Document* doc = mDocumentViewer->GetDocument()) { |
4842 | timing = doc->GetNavigationTiming(); |
4843 | } |
4844 | } |
4845 | if (timing) { |
4846 | timing->NotifyDocShellStateChanged( |
4847 | isActive ? nsDOMNavigationTiming::DocShellState::eActive |
4848 | : nsDOMNavigationTiming::DocShellState::eInactive); |
4849 | } |
4850 | |
4851 | // Restart or stop meta refresh timers if necessary |
4852 | if (mDisableMetaRefreshWhenInactive) { |
4853 | if (isActive) { |
4854 | ResumeRefreshURIs(); |
4855 | } else { |
4856 | SuspendRefreshURIs(); |
4857 | } |
4858 | } |
4859 | |
4860 | if (InputTaskManager::CanSuspendInputEvent()) { |
4861 | mBrowsingContext->Group()->UpdateInputTaskManagerIfNeeded(isActive); |
4862 | } |
4863 | } |
4864 | |
4865 | NS_IMETHODIMPnsresult |
4866 | nsDocShell::SetDefaultLoadFlags(uint32_t aDefaultLoadFlags) { |
4867 | if (!mWillChangeProcess) { |
4868 | // Intentionally ignoring handling discarded browsing contexts. |
4869 | Unused << mBrowsingContext->SetDefaultLoadFlags(aDefaultLoadFlags); |
4870 | } else { |
4871 | // Bug 1623565: DevTools tries to clean up defaultLoadFlags on |
4872 | // shutdown. Sorry DevTools, your DocShell is in another process. |
4873 | NS_WARNING("nsDocShell::SetDefaultLoadFlags called on Zombie DocShell")NS_DebugBreak(NS_DEBUG_WARNING, "nsDocShell::SetDefaultLoadFlags called on Zombie DocShell" , nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 4873); |
4874 | } |
4875 | return NS_OK; |
4876 | } |
4877 | |
4878 | NS_IMETHODIMPnsresult |
4879 | nsDocShell::GetDefaultLoadFlags(uint32_t* aDefaultLoadFlags) { |
4880 | *aDefaultLoadFlags = mBrowsingContext->GetDefaultLoadFlags(); |
4881 | return NS_OK; |
4882 | } |
4883 | |
4884 | NS_IMETHODIMPnsresult |
4885 | nsDocShell::GetFailedChannel(nsIChannel** aFailedChannel) { |
4886 | NS_ENSURE_ARG_POINTER(aFailedChannel)do { if ((__builtin_expect(!!(!(aFailedChannel)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aFailedChannel" ") failed" , nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 4886); return NS_ERROR_INVALID_POINTER; } } while (false); |
4887 | Document* doc = GetDocument(); |
4888 | if (!doc) { |
4889 | *aFailedChannel = nullptr; |
4890 | return NS_OK; |
4891 | } |
4892 | NS_IF_ADDREF(*aFailedChannel = doc->GetFailedChannel())ns_if_addref(*aFailedChannel = doc->GetFailedChannel()); |
4893 | return NS_OK; |
4894 | } |
4895 | |
4896 | NS_IMETHODIMPnsresult |
4897 | nsDocShell::SetVisibility(bool aVisibility) { |
4898 | // Show()/Hide() may change mDocumentViewer. |
4899 | nsCOMPtr<nsIDocumentViewer> viewer = mDocumentViewer; |
4900 | if (!viewer) { |
4901 | return NS_OK; |
4902 | } |
4903 | if (aVisibility) { |
4904 | viewer->Show(); |
4905 | } else { |
4906 | viewer->Hide(); |
4907 | } |
4908 | |
4909 | return NS_OK; |
4910 | } |
4911 | |
4912 | NS_IMETHODIMPnsresult |
4913 | nsDocShell::GetEnabled(bool* aEnabled) { |
4914 | NS_ENSURE_ARG_POINTER(aEnabled)do { if ((__builtin_expect(!!(!(aEnabled)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aEnabled" ") failed", nullptr , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 4914); return NS_ERROR_INVALID_POINTER; } } while (false); |
4915 | *aEnabled = true; |
4916 | return NS_ERROR_NOT_IMPLEMENTED; |
4917 | } |
4918 | |
4919 | NS_IMETHODIMPnsresult |
4920 | nsDocShell::SetEnabled(bool aEnabled) { return NS_ERROR_NOT_IMPLEMENTED; } |
4921 | |
4922 | NS_IMETHODIMPnsresult |
4923 | nsDocShell::GetMainWidget(nsIWidget** aMainWidget) { |
4924 | // We don't create our own widget, so simply return the parent one. |
4925 | return GetParentWidget(aMainWidget); |
4926 | } |
4927 | |
4928 | NS_IMETHODIMPnsresult |
4929 | nsDocShell::GetTitle(nsAString& aTitle) { |
4930 | aTitle = mTitle; |
4931 | return NS_OK; |
4932 | } |
4933 | |
4934 | NS_IMETHODIMPnsresult |
4935 | nsDocShell::SetTitle(const nsAString& aTitle) { |
4936 | // Avoid unnecessary updates of the title if the URI and the title haven't |
4937 | // changed. |
4938 | if (mTitleValidForCurrentURI && mTitle == aTitle) { |
4939 | return NS_OK; |
4940 | } |
4941 | |
4942 | // Store local title |
4943 | mTitle = aTitle; |
4944 | mTitleValidForCurrentURI = true; |
4945 | |
4946 | // When title is set on the top object it should then be passed to the |
4947 | // tree owner. |
4948 | if (mBrowsingContext->IsTop()) { |
4949 | nsCOMPtr<nsIBaseWindow> treeOwnerAsWin(do_QueryInterface(mTreeOwner)); |
4950 | if (treeOwnerAsWin) { |
4951 | treeOwnerAsWin->SetTitle(aTitle); |
4952 | } |
4953 | } |
4954 | |
4955 | if (mCurrentURI && mLoadType != LOAD_ERROR_PAGE) { |
4956 | UpdateGlobalHistoryTitle(mCurrentURI); |
4957 | } |
4958 | |
4959 | // Update SessionHistory with the document's title. |
4960 | if (mLoadType != LOAD_BYPASS_HISTORY && mLoadType != LOAD_ERROR_PAGE) { |
4961 | SetTitleOnHistoryEntry(true); |
4962 | } |
4963 | |
4964 | return NS_OK; |
4965 | } |
4966 | |
4967 | void nsDocShell::SetTitleOnHistoryEntry(bool aUpdateEntryInSessionHistory) { |
4968 | if (mOSHE) { |
4969 | mOSHE->SetTitle(mTitle); |
4970 | } |
4971 | |
4972 | if (mActiveEntry && mBrowsingContext) { |
4973 | mActiveEntry->SetTitle(mTitle); |
4974 | if (aUpdateEntryInSessionHistory) { |
4975 | if (XRE_IsParentProcess()) { |
4976 | SessionHistoryEntry* entry = |
4977 | mBrowsingContext->Canonical()->GetActiveSessionHistoryEntry(); |
4978 | if (entry) { |
4979 | entry->SetTitle(mTitle); |
4980 | } |
4981 | } else { |
4982 | mozilla::Unused |
4983 | << ContentChild::GetSingleton()->SendSessionHistoryEntryTitle( |
4984 | mBrowsingContext, mTitle); |
4985 | } |
4986 | } |
4987 | } |
4988 | } |
4989 | |
4990 | nsPoint nsDocShell::GetCurScrollPos() { |
4991 | nsPoint scrollPos; |
4992 | if (ScrollContainerFrame* sf = GetRootScrollContainerFrame()) { |
4993 | scrollPos = sf->GetVisualViewportOffset(); |
4994 | } |
4995 | return scrollPos; |
4996 | } |
4997 | |
4998 | nsresult nsDocShell::SetCurScrollPosEx(int32_t aCurHorizontalPos, |
4999 | int32_t aCurVerticalPos) { |
5000 | ScrollContainerFrame* sf = GetRootScrollContainerFrame(); |
5001 | NS_ENSURE_TRUE(sf, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(sf)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING , "NS_ENSURE_TRUE(" "sf" ") failed", nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 5001); return NS_ERROR_FAILURE; } } while (false); |
5002 | |
5003 | ScrollMode scrollMode = |
5004 | sf->IsSmoothScroll() ? ScrollMode::SmoothMsd : ScrollMode::Instant; |
5005 | |
5006 | nsPoint targetPos(aCurHorizontalPos, aCurVerticalPos); |
5007 | sf->ScrollTo(targetPos, scrollMode); |
5008 | |
5009 | // Set the visual viewport offset as well. |
5010 | |
5011 | RefPtr<PresShell> presShell = GetPresShell(); |
5012 | NS_ENSURE_TRUE(presShell, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(presShell)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "presShell" ") failed", nullptr , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 5012); return NS_ERROR_FAILURE; } } while (false); |
5013 | |
5014 | nsPresContext* presContext = presShell->GetPresContext(); |
5015 | NS_ENSURE_TRUE(presContext, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(presContext)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "presContext" ") failed" , nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 5015); return NS_ERROR_FAILURE; } } while (false); |
5016 | |
5017 | // Only the root content document can have a distinct visual viewport offset. |
5018 | if (!presContext->IsRootContentDocumentCrossProcess()) { |
5019 | return NS_OK; |
5020 | } |
5021 | |
5022 | // Not on a platform with a distinct visual viewport - don't bother setting |
5023 | // the visual viewport offset. |
5024 | if (!presShell->IsVisualViewportSizeSet()) { |
5025 | return NS_OK; |
5026 | } |
5027 | |
5028 | presShell->ScrollToVisual(targetPos, layers::FrameMetrics::eMainThread, |
5029 | scrollMode); |
5030 | |
5031 | return NS_OK; |
5032 | } |
5033 | |
5034 | void nsDocShell::SetScrollbarPreference(mozilla::ScrollbarPreference aPref) { |
5035 | if (mScrollbarPref == aPref) { |
5036 | return; |
5037 | } |
5038 | mScrollbarPref = aPref; |
5039 | auto* ps = GetPresShell(); |
5040 | if (!ps) { |
5041 | return; |
5042 | } |
5043 | nsIFrame* rootScrollContainerFrame = ps->GetRootScrollContainerFrame(); |
5044 | if (!rootScrollContainerFrame) { |
5045 | return; |
5046 | } |
5047 | ps->FrameNeedsReflow(rootScrollContainerFrame, |
5048 | IntrinsicDirty::FrameAncestorsAndDescendants, |
5049 | NS_FRAME_IS_DIRTY); |
5050 | } |
5051 | |
5052 | //***************************************************************************** |
5053 | // nsDocShell::nsIRefreshURI |
5054 | //***************************************************************************** |
5055 | |
5056 | NS_IMETHODIMPnsresult |
5057 | nsDocShell::RefreshURI(nsIURI* aURI, nsIPrincipal* aPrincipal, |
5058 | uint32_t aDelay) { |
5059 | MOZ_ASSERT(!mIsBeingDestroyed)do { static_assert( mozilla::detail::AssertionConditionType< decltype(!mIsBeingDestroyed)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!mIsBeingDestroyed))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!mIsBeingDestroyed" , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 5059); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "!mIsBeingDestroyed" ")"); do { MOZ_CrashSequence (__null, 5059); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); |
5060 | |
5061 | NS_ENSURE_ARG(aURI)do { if ((__builtin_expect(!!(!(aURI)), 0))) { NS_DebugBreak( NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aURI" ") failed", nullptr , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 5061); return NS_ERROR_INVALID_ARG; } } while (false); |
5062 | |
5063 | /* Check if Meta refresh/redirects are permitted. Some |
5064 | * embedded applications may not want to do this. |
5065 | * Must do this before sending out NOTIFY_REFRESH events |
5066 | * because listeners may have side effects (e.g. displaying a |
5067 | * button to manually trigger the refresh later). |
5068 | */ |
5069 | bool allowRedirects = true; |
5070 | GetAllowMetaRedirects(&allowRedirects); |
5071 | if (!allowRedirects) { |
5072 | return NS_OK; |
5073 | } |
5074 | |
5075 | // If any web progress listeners are listening for NOTIFY_REFRESH events, |
5076 | // give them a chance to block this refresh. |
5077 | bool sameURI; |
5078 | nsresult rv = aURI->Equals(mCurrentURI, &sameURI); |
5079 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
5080 | sameURI = false; |
5081 | } |
5082 | if (!RefreshAttempted(this, aURI, aDelay, sameURI)) { |
5083 | return NS_OK; |
5084 | } |
5085 | |
5086 | nsCOMPtr<nsITimerCallback> refreshTimer = |
5087 | new nsRefreshTimer(this, aURI, aPrincipal, aDelay); |
5088 | |
5089 | BusyFlags busyFlags = GetBusyFlags(); |
5090 | |
5091 | if (!mRefreshURIList) { |
5092 | mRefreshURIList = nsArray::Create(); |
5093 | } |
5094 | |
5095 | if (busyFlags & BUSY_FLAGS_BUSY || |
5096 | (!mBrowsingContext->IsActive() && mDisableMetaRefreshWhenInactive)) { |
5097 | // We don't want to create the timer right now. Instead queue up the |
5098 | // request and trigger the timer in EndPageLoad() or whenever we become |
5099 | // active. |
5100 | mRefreshURIList->AppendElement(refreshTimer); |
5101 | } else { |
5102 | // There is no page loading going on right now. Create the |
5103 | // timer and fire it right away. |
5104 | nsCOMPtr<nsPIDOMWindowOuter> win = GetWindow(); |
5105 | NS_ENSURE_TRUE(win, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(win)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING , "NS_ENSURE_TRUE(" "win" ") failed", nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 5105); return NS_ERROR_FAILURE; } } while (false); |
5106 | |
5107 | nsCOMPtr<nsITimer> timer; |
5108 | MOZ_TRY_VAR(timer, NS_NewTimerWithCallback(refreshTimer, aDelay,(timer) = __extension__({ auto mozTryVarTempResult = ::mozilla ::ToResult(NS_NewTimerWithCallback(refreshTimer, aDelay, nsITimer ::TYPE_ONE_SHOT)); if ((__builtin_expect(!!(mozTryVarTempResult .isErr()), 0))) { return mozTryVarTempResult.propagateErr(); } mozTryVarTempResult.unwrap(); }); |
5109 | nsITimer::TYPE_ONE_SHOT))(timer) = __extension__({ auto mozTryVarTempResult = ::mozilla ::ToResult(NS_NewTimerWithCallback(refreshTimer, aDelay, nsITimer ::TYPE_ONE_SHOT)); if ((__builtin_expect(!!(mozTryVarTempResult .isErr()), 0))) { return mozTryVarTempResult.propagateErr(); } mozTryVarTempResult.unwrap(); });; |
5110 | |
5111 | mRefreshURIList->AppendElement(timer); // owning timer ref |
5112 | } |
5113 | return NS_OK; |
5114 | } |
5115 | |
5116 | nsresult nsDocShell::ForceRefreshURIFromTimer(nsIURI* aURI, |
5117 | nsIPrincipal* aPrincipal, |
5118 | uint32_t aDelay, |
5119 | nsITimer* aTimer) { |
5120 | MOZ_ASSERT(aTimer, "Must have a timer here")do { static_assert( mozilla::detail::AssertionConditionType< decltype(aTimer)>::isValid, "invalid assertion condition") ; if ((__builtin_expect(!!(!(!!(aTimer))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aTimer" " (" "Must have a timer here" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 5120 ); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aTimer" ") (" "Must have a timer here" ")"); do { MOZ_CrashSequence(__null, 5120); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
5121 | |
5122 | // Remove aTimer from mRefreshURIList if needed |
5123 | if (mRefreshURIList) { |
5124 | uint32_t n = 0; |
5125 | mRefreshURIList->GetLength(&n); |
5126 | |
5127 | for (uint32_t i = 0; i < n; ++i) { |
5128 | nsCOMPtr<nsITimer> timer = do_QueryElementAt(mRefreshURIList, i); |
5129 | if (timer == aTimer) { |
5130 | mRefreshURIList->RemoveElementAt(i); |
5131 | break; |
5132 | } |
5133 | } |
5134 | } |
5135 | |
5136 | return ForceRefreshURI(aURI, aPrincipal, aDelay); |
5137 | } |
5138 | |
5139 | NS_IMETHODIMPnsresult |
5140 | nsDocShell::ForceRefreshURI(nsIURI* aURI, nsIPrincipal* aPrincipal, |
5141 | uint32_t aDelay) { |
5142 | NS_ENSURE_ARG(aURI)do { if ((__builtin_expect(!!(!(aURI)), 0))) { NS_DebugBreak( NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aURI" ") failed", nullptr , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 5142); return NS_ERROR_INVALID_ARG; } } while (false); |
5143 | |
5144 | RefPtr<nsDocShellLoadState> loadState = new nsDocShellLoadState(aURI); |
5145 | loadState->SetOriginalURI(mCurrentURI); |
5146 | loadState->SetResultPrincipalURI(aURI); |
5147 | loadState->SetResultPrincipalURIIsSome(true); |
5148 | loadState->SetKeepResultPrincipalURIIfSet(true); |
5149 | loadState->SetIsMetaRefresh(true); |
5150 | |
5151 | RefPtr<Document> doc = GetDocument(); |
5152 | NS_ENSURE_STATE(doc)do { if ((__builtin_expect(!!(!(doc)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING , "NS_ENSURE_TRUE(" "doc" ") failed", nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 5152); return NS_ERROR_UNEXPECTED; } } while (false); |
5153 | |
5154 | // Set the triggering pricipal to aPrincipal if available, or current |
5155 | // document's principal otherwise. |
5156 | nsCOMPtr<nsIPrincipal> principal = aPrincipal; |
5157 | if (!principal) { |
5158 | principal = doc->NodePrincipal(); |
5159 | } |
5160 | loadState->SetTriggeringPrincipal(principal); |
5161 | loadState->SetCsp(doc->GetCsp()); |
5162 | loadState->SetHasValidUserGestureActivation( |
5163 | doc->HasValidTransientUserGestureActivation()); |
5164 | |
5165 | loadState->SetTextDirectiveUserActivation( |
5166 | doc->ConsumeTextDirectiveUserActivation() || |
5167 | loadState->HasValidUserGestureActivation()); |
5168 | loadState->SetTriggeringSandboxFlags(doc->GetSandboxFlags()); |
5169 | loadState->SetTriggeringWindowId(doc->InnerWindowID()); |
5170 | loadState->SetTriggeringStorageAccess(doc->UsingStorageAccess()); |
5171 | loadState->SetTriggeringClassificationFlags(doc->GetScriptTrackingFlags()); |
5172 | |
5173 | loadState->SetPrincipalIsExplicit(true); |
5174 | |
5175 | /* Check if this META refresh causes a redirection |
5176 | * to another site. |
5177 | */ |
5178 | bool equalUri = false; |
5179 | nsresult rv = aURI->Equals(mCurrentURI, &equalUri); |
5180 | |
5181 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && !equalUri && aDelay <= REFRESH_REDIRECT_TIMER15000) { |
5182 | /* It is a META refresh based redirection within the threshold time |
5183 | * we have in mind (15000 ms as defined by REFRESH_REDIRECT_TIMER). |
5184 | * Pass a REPLACE flag to LoadURI(). |
5185 | */ |
5186 | loadState->SetLoadType(LOAD_REFRESH_REPLACE); |
5187 | } else { |
5188 | loadState->SetLoadType(LOAD_REFRESH); |
5189 | } |
5190 | |
5191 | const bool sendReferrer = StaticPrefs::network_http_referer_sendFromRefresh(); |
5192 | /* The document's referrer policy is needed instead of mReferrerInfo's |
5193 | * referrer policy. |
5194 | */ |
5195 | const nsCOMPtr<nsIReferrerInfo> referrerInfo = |
5196 | new ReferrerInfo(*doc, sendReferrer); |
5197 | /* We mimic HTTP, which passes the original referrer. See step 3 of |
5198 | * <https://html.spec.whatwg.org/multipage/browsing-the-web.html#create-navigation-params-by-fetching>. |
5199 | */ |
5200 | loadState->SetReferrerInfo(referrerInfo); |
5201 | |
5202 | loadState->SetLoadFlags( |
5203 | nsIWebNavigation::LOAD_FLAGS_DISALLOW_INHERIT_PRINCIPAL); |
5204 | loadState->SetFirstParty(true); |
5205 | |
5206 | /* |
5207 | * LoadURI(...) will cancel all refresh timers... This causes the |
5208 | * Timer and its refreshData instance to be released... |
5209 | */ |
5210 | LoadURI(loadState, false); |
5211 | |
5212 | return NS_OK; |
5213 | } |
5214 | |
5215 | static const char16_t* SkipASCIIWhitespace(const char16_t* aStart, |
5216 | const char16_t* aEnd) { |
5217 | const char16_t* iter = aStart; |
5218 | while (iter != aEnd && mozilla::IsAsciiWhitespace(*iter)) { |
5219 | ++iter; |
5220 | } |
5221 | return iter; |
5222 | } |
5223 | |
5224 | static std::tuple<const char16_t*, const char16_t*> ExtractURLString( |
5225 | const char16_t* aPosition, const char16_t* aEnd) { |
5226 | MOZ_ASSERT(aPosition != aEnd)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aPosition != aEnd)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aPosition != aEnd))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aPosition != aEnd" , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 5226); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "aPosition != aEnd" ")"); do { MOZ_CrashSequence (__null, 5226); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); |
5227 | |
5228 | // 1. Let urlString be the substring of input from the code point at |
5229 | // position to the end of the string. |
5230 | const char16_t* urlStart = aPosition; |
5231 | const char16_t* urlEnd = aEnd; |
5232 | |
5233 | // 2. If the code point in input pointed to by position is U+0055 (U) or |
5234 | // U+0075 (u), then advance position to the next code point. |
5235 | // Otherwise, jump to the step labeled skip quotes. |
5236 | if (*aPosition == 'U' || *aPosition == 'u') { |
5237 | ++aPosition; |
5238 | |
5239 | // 3. If the code point in input pointed to by position is U+0052 (R) or |
5240 | // U+0072 (r), then advance position to the next code point. |
5241 | // Otherwise, jump to the step labeled parse. |
5242 | if (aPosition == aEnd || (*aPosition != 'R' && *aPosition != 'r')) { |
5243 | return std::make_tuple(urlStart, urlEnd); |
5244 | } |
5245 | |
5246 | ++aPosition; |
5247 | |
5248 | // 4. If the code point in input pointed to by position is U+004C (L) or |
5249 | // U+006C (l), then advance position to the next code point. |
5250 | // Otherwise, jump to the step labeled parse. |
5251 | if (aPosition == aEnd || (*aPosition != 'L' && *aPosition != 'l')) { |
5252 | return std::make_tuple(urlStart, urlEnd); |
5253 | } |
5254 | |
5255 | ++aPosition; |
5256 | |
5257 | // 5. Skip ASCII whitespace within input given position. |
5258 | aPosition = SkipASCIIWhitespace(aPosition, aEnd); |
5259 | |
5260 | // 6. If the code point in input pointed to by position is U+003D (=), |
5261 | // then advance position to the next code point. Otherwise, jump to |
5262 | // the step labeled parse. |
5263 | if (aPosition == aEnd || *aPosition != '=') { |
5264 | return std::make_tuple(urlStart, urlEnd); |
5265 | } |
5266 | |
5267 | ++aPosition; |
5268 | |
5269 | // 7. Skip ASCII whitespace within input given position. |
5270 | aPosition = SkipASCIIWhitespace(aPosition, aEnd); |
5271 | } |
5272 | |
5273 | // 8. Skip quotes: If the code point in input pointed to by position is |
5274 | // U+0027 (') or U+0022 ("), then let quote be that code point, and |
5275 | // advance position to the next code point. Otherwise, let quote be |
5276 | // the empty string. |
5277 | Maybe<char> quote; |
5278 | if (aPosition != aEnd && (*aPosition == '\'' || *aPosition == '"')) { |
5279 | quote.emplace(*aPosition); |
5280 | ++aPosition; |
5281 | } |
5282 | |
5283 | // 9. Set urlString to the substring of input from the code point at |
5284 | // position to the end of the string. |
5285 | urlStart = aPosition; |
5286 | urlEnd = aEnd; |
5287 | |
5288 | // 10. If quote is not the empty string, and there is a code point in |
5289 | // urlString equal to quote, then truncate urlString at that code |
5290 | // point, so that it and all subsequent code points are removed. |
5291 | const char16_t* quotePos; |
5292 | if (quote.isSome() && |
5293 | (quotePos = nsCharTraits<char16_t>::find( |
5294 | urlStart, std::distance(urlStart, aEnd), quote.value()))) { |
5295 | urlEnd = quotePos; |
5296 | } |
5297 | |
5298 | return std::make_tuple(urlStart, urlEnd); |
5299 | } |
5300 | |
5301 | void nsDocShell::SetupRefreshURIFromHeader(Document* aDocument, |
5302 | const nsAString& aHeader) { |
5303 | if (mIsBeingDestroyed) { |
5304 | return; |
5305 | } |
5306 | |
5307 | const char16_t* position = aHeader.BeginReading(); |
5308 | const char16_t* end = aHeader.EndReading(); |
5309 | |
5310 | // See https://html.spec.whatwg.org/#shared-declarative-refresh-steps. |
5311 | |
5312 | // 3. Skip ASCII whitespace |
5313 | position = SkipASCIIWhitespace(position, end); |
5314 | |
5315 | // 4. Let time be 0. |
5316 | CheckedInt<uint32_t> milliSeconds; |
5317 | |
5318 | // 5. Collect a sequence of code points that are ASCII digits |
5319 | const char16_t* digitsStart = position; |
5320 | while (position != end && mozilla::IsAsciiDigit(*position)) { |
5321 | ++position; |
5322 | } |
5323 | |
5324 | if (position == digitsStart) { |
5325 | // 6. If timeString is the empty string, then: |
5326 | // 1. If the code point in input pointed to by position is not U+002E |
5327 | // (.), then return. |
5328 | if (position == end || *position != '.') { |
5329 | return; |
5330 | } |
5331 | } else { |
5332 | // 7. Otherwise, set time to the result of parsing timeString using the |
5333 | // rules for parsing non-negative integers. |
5334 | nsContentUtils::ParseHTMLIntegerResultFlags result; |
5335 | uint32_t seconds = |
5336 | nsContentUtils::ParseHTMLInteger(digitsStart, position, &result); |
5337 | MOZ_ASSERT(!(result & nsContentUtils::eParseHTMLInteger_Negative))do { static_assert( mozilla::detail::AssertionConditionType< decltype(!(result & nsContentUtils::eParseHTMLInteger_Negative ))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(!(result & nsContentUtils::eParseHTMLInteger_Negative )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("!(result & nsContentUtils::eParseHTMLInteger_Negative)" , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 5337); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "!(result & nsContentUtils::eParseHTMLInteger_Negative)" ")"); do { MOZ_CrashSequence(__null, 5337); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
5338 | if (result & nsContentUtils::eParseHTMLInteger_Error) { |
5339 | // The spec assumes no errors here (since we only pass ASCII digits in), |
5340 | // but we can still overflow, so this block should deal with that (and |
5341 | // only that). |
5342 | MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType< decltype(!(result & ~(nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput | nsContentUtils::eParseHTMLInteger_Error | nsContentUtils:: eParseHTMLInteger_ErrorOverflow)))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!(result & ~(nsContentUtils ::eParseHTMLInteger_DidNotConsumeAllInput | nsContentUtils::eParseHTMLInteger_Error | nsContentUtils::eParseHTMLInteger_ErrorOverflow))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!(result & ~(nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput | nsContentUtils::eParseHTMLInteger_Error | nsContentUtils::eParseHTMLInteger_ErrorOverflow))" , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 5345); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "!(result & ~(nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput | nsContentUtils::eParseHTMLInteger_Error | nsContentUtils::eParseHTMLInteger_ErrorOverflow))" ")"); do { MOZ_CrashSequence(__null, 5345); __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
5343 | !(result & ~(nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput |do { static_assert( mozilla::detail::AssertionConditionType< decltype(!(result & ~(nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput | nsContentUtils::eParseHTMLInteger_Error | nsContentUtils:: eParseHTMLInteger_ErrorOverflow)))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!(result & ~(nsContentUtils ::eParseHTMLInteger_DidNotConsumeAllInput | nsContentUtils::eParseHTMLInteger_Error | nsContentUtils::eParseHTMLInteger_ErrorOverflow))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!(result & ~(nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput | nsContentUtils::eParseHTMLInteger_Error | nsContentUtils::eParseHTMLInteger_ErrorOverflow))" , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 5345); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "!(result & ~(nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput | nsContentUtils::eParseHTMLInteger_Error | nsContentUtils::eParseHTMLInteger_ErrorOverflow))" ")"); do { MOZ_CrashSequence(__null, 5345); __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
5344 | nsContentUtils::eParseHTMLInteger_Error |do { static_assert( mozilla::detail::AssertionConditionType< decltype(!(result & ~(nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput | nsContentUtils::eParseHTMLInteger_Error | nsContentUtils:: eParseHTMLInteger_ErrorOverflow)))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!(result & ~(nsContentUtils ::eParseHTMLInteger_DidNotConsumeAllInput | nsContentUtils::eParseHTMLInteger_Error | nsContentUtils::eParseHTMLInteger_ErrorOverflow))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!(result & ~(nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput | nsContentUtils::eParseHTMLInteger_Error | nsContentUtils::eParseHTMLInteger_ErrorOverflow))" , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 5345); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "!(result & ~(nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput | nsContentUtils::eParseHTMLInteger_Error | nsContentUtils::eParseHTMLInteger_ErrorOverflow))" ")"); do { MOZ_CrashSequence(__null, 5345); __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
5345 | nsContentUtils::eParseHTMLInteger_ErrorOverflow)))do { static_assert( mozilla::detail::AssertionConditionType< decltype(!(result & ~(nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput | nsContentUtils::eParseHTMLInteger_Error | nsContentUtils:: eParseHTMLInteger_ErrorOverflow)))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!(result & ~(nsContentUtils ::eParseHTMLInteger_DidNotConsumeAllInput | nsContentUtils::eParseHTMLInteger_Error | nsContentUtils::eParseHTMLInteger_ErrorOverflow))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!(result & ~(nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput | nsContentUtils::eParseHTMLInteger_Error | nsContentUtils::eParseHTMLInteger_ErrorOverflow))" , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 5345); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "!(result & ~(nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput | nsContentUtils::eParseHTMLInteger_Error | nsContentUtils::eParseHTMLInteger_ErrorOverflow))" ")"); do { MOZ_CrashSequence(__null, 5345); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
5346 | return; |
5347 | } |
5348 | MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType< decltype(!(result & nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput ))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(!(result & nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("!(result & nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput)" , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 5349); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "!(result & nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput)" ")"); do { MOZ_CrashSequence(__null, 5349); __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
5349 | !(result & nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput))do { static_assert( mozilla::detail::AssertionConditionType< decltype(!(result & nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput ))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(!(result & nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("!(result & nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput)" , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 5349); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "!(result & nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput)" ")"); do { MOZ_CrashSequence(__null, 5349); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
5350 | |
5351 | milliSeconds = seconds; |
5352 | milliSeconds *= 1000; |
5353 | if (!milliSeconds.isValid()) { |
5354 | return; |
5355 | } |
5356 | } |
5357 | |
5358 | // 8. Collect a sequence of code points that are ASCII digits and U+002E FULL |
5359 | // STOP characters (.) from input given position. Ignore any collected |
5360 | // characters. |
5361 | while (position != end && |
5362 | (mozilla::IsAsciiDigit(*position) || *position == '.')) { |
5363 | ++position; |
5364 | } |
5365 | |
5366 | // 9. Let urlRecord be document's URL. |
5367 | nsCOMPtr<nsIURI> urlRecord(aDocument->GetDocumentURI()); |
5368 | |
5369 | // 10. If position is not past the end of input |
5370 | if (position != end) { |
5371 | // 1. If the code point in input pointed to by position is not U+003B (;), |
5372 | // U+002C (,), or ASCII whitespace, then return. |
5373 | if (*position != ';' && *position != ',' && |
5374 | !mozilla::IsAsciiWhitespace(*position)) { |
5375 | return; |
5376 | } |
5377 | |
5378 | // 2. Skip ASCII whitespace within input given position. |
5379 | position = SkipASCIIWhitespace(position, end); |
5380 | |
5381 | // 3. If the code point in input pointed to by position is U+003B (;) or |
5382 | // U+002C (,), then advance position to the next code point. |
5383 | if (position != end && (*position == ';' || *position == ',')) { |
5384 | ++position; |
5385 | |
5386 | // 4. Skip ASCII whitespace within input given position. |
5387 | position = SkipASCIIWhitespace(position, end); |
5388 | } |
5389 | |
5390 | // 11. If position is not past the end of input, then: |
5391 | if (position != end) { |
5392 | const char16_t* urlStart; |
5393 | const char16_t* urlEnd; |
5394 | |
5395 | // 1-10. See ExtractURLString. |
5396 | std::tie(urlStart, urlEnd) = ExtractURLString(position, end); |
5397 | |
5398 | // 11. Parse: Parse urlString relative to document. If that fails, return. |
5399 | // Otherwise, set urlRecord to the resulting URL record. |
5400 | nsresult rv = |
5401 | NS_NewURI(getter_AddRefs(urlRecord), |
5402 | Substring(urlStart, std::distance(urlStart, urlEnd)), |
5403 | /* charset = */ nullptr, aDocument->GetDocBaseURI()); |
5404 | NS_ENSURE_SUCCESS_VOID(rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS_VOID(%s) failed with " "result 0x%" "X" "%s%s%s", "rv", static_cast<uint32_t> (__rv), name ? " (" : "", name ? name : "", name ? ")" : ""); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 5404); return; } } while (false); |
5405 | } |
5406 | } |
5407 | |
5408 | nsIPrincipal* principal = aDocument->NodePrincipal(); |
5409 | nsCOMPtr<nsIScriptSecurityManager> securityManager = |
5410 | nsContentUtils::GetSecurityManager(); |
5411 | nsresult rv = securityManager->CheckLoadURIWithPrincipal( |
5412 | principal, urlRecord, |
5413 | nsIScriptSecurityManager::LOAD_IS_AUTOMATIC_DOCUMENT_REPLACEMENT, |
5414 | aDocument->InnerWindowID()); |
5415 | NS_ENSURE_SUCCESS_VOID(rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS_VOID(%s) failed with " "result 0x%" "X" "%s%s%s", "rv", static_cast<uint32_t> (__rv), name ? " (" : "", name ? name : "", name ? ")" : ""); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 5415); return; } } while (false); |
5416 | |
5417 | bool isjs = true; |
5418 | rv = NS_URIChainHasFlags( |
5419 | urlRecord, nsIProtocolHandler::URI_OPENING_EXECUTES_SCRIPT, &isjs); |
5420 | NS_ENSURE_SUCCESS_VOID(rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS_VOID(%s) failed with " "result 0x%" "X" "%s%s%s", "rv", static_cast<uint32_t> (__rv), name ? " (" : "", name ? name : "", name ? ")" : ""); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 5420); return; } } while (false); |
5421 | |
5422 | if (isjs) { |
5423 | return; |
5424 | } |
5425 | |
5426 | RefreshURI(urlRecord, principal, milliSeconds.value()); |
5427 | } |
5428 | |
5429 | static void DoCancelRefreshURITimers(nsIMutableArray* aTimerList) { |
5430 | if (!aTimerList) { |
5431 | return; |
5432 | } |
5433 | |
5434 | uint32_t n = 0; |
5435 | aTimerList->GetLength(&n); |
5436 | |
5437 | while (n) { |
5438 | nsCOMPtr<nsITimer> timer(do_QueryElementAt(aTimerList, --n)); |
5439 | |
5440 | aTimerList->RemoveElementAt(n); // bye bye owning timer ref |
5441 | |
5442 | if (timer) { |
5443 | timer->Cancel(); |
5444 | } |
5445 | } |
5446 | } |
5447 | |
5448 | NS_IMETHODIMPnsresult |
5449 | nsDocShell::CancelRefreshURITimers() { |
5450 | DoCancelRefreshURITimers(mRefreshURIList); |
5451 | DoCancelRefreshURITimers(mSavedRefreshURIList); |
5452 | DoCancelRefreshURITimers(mBFCachedRefreshURIList); |
5453 | mRefreshURIList = nullptr; |
5454 | mSavedRefreshURIList = nullptr; |
5455 | mBFCachedRefreshURIList = nullptr; |
5456 | |
5457 | return NS_OK; |
5458 | } |
5459 | |
5460 | NS_IMETHODIMPnsresult |
5461 | nsDocShell::GetRefreshPending(bool* aResult) { |
5462 | if (!mRefreshURIList) { |
5463 | *aResult = false; |
5464 | return NS_OK; |
5465 | } |
5466 | |
5467 | uint32_t count; |
5468 | nsresult rv = mRefreshURIList->GetLength(&count); |
5469 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) { |
5470 | *aResult = (count != 0); |
5471 | } |
5472 | return rv; |
5473 | } |
5474 | |
5475 | void nsDocShell::RefreshURIToQueue() { |
5476 | if (mRefreshURIList) { |
5477 | uint32_t n = 0; |
5478 | mRefreshURIList->GetLength(&n); |
5479 | |
5480 | for (uint32_t i = 0; i < n; ++i) { |
5481 | nsCOMPtr<nsITimer> timer = do_QueryElementAt(mRefreshURIList, i); |
5482 | if (!timer) { |
5483 | continue; // this must be a nsRefreshURI already |
5484 | } |
5485 | |
5486 | // Replace this timer object with a nsRefreshTimer object. |
5487 | nsCOMPtr<nsITimerCallback> callback; |
5488 | timer->GetCallback(getter_AddRefs(callback)); |
5489 | |
5490 | timer->Cancel(); |
5491 | |
5492 | mRefreshURIList->ReplaceElementAt(callback, i); |
5493 | } |
5494 | } |
5495 | } |
5496 | |
5497 | NS_IMETHODIMPnsresult |
5498 | nsDocShell::SuspendRefreshURIs() { |
5499 | RefreshURIToQueue(); |
5500 | |
5501 | // Suspend refresh URIs for our child shells as well. |
5502 | for (auto* child : mChildList.ForwardRange()) { |
5503 | nsCOMPtr<nsIDocShell> shell = do_QueryObject(child); |
5504 | if (shell) { |
5505 | shell->SuspendRefreshURIs(); |
5506 | } |
5507 | } |
5508 | |
5509 | return NS_OK; |
5510 | } |
5511 | |
5512 | NS_IMETHODIMPnsresult |
5513 | nsDocShell::ResumeRefreshURIs() { |
5514 | RefreshURIFromQueue(); |
5515 | |
5516 | // Resume refresh URIs for our child shells as well. |
5517 | for (auto* child : mChildList.ForwardRange()) { |
5518 | nsCOMPtr<nsIDocShell> shell = do_QueryObject(child); |
5519 | if (shell) { |
5520 | shell->ResumeRefreshURIs(); |
5521 | } |
5522 | } |
5523 | |
5524 | return NS_OK; |
5525 | } |
5526 | |
5527 | nsresult nsDocShell::RefreshURIFromQueue() { |
5528 | if (!mRefreshURIList) { |
5529 | return NS_OK; |
5530 | } |
5531 | uint32_t n = 0; |
5532 | mRefreshURIList->GetLength(&n); |
5533 | |
5534 | while (n) { |
5535 | nsCOMPtr<nsITimerCallback> refreshInfo = |
5536 | do_QueryElementAt(mRefreshURIList, --n); |
5537 | |
5538 | if (refreshInfo) { |
5539 | // This is the nsRefreshTimer object, waiting to be |
5540 | // setup in a timer object and fired. |
5541 | // Create the timer and trigger it. |
5542 | uint32_t delay = static_cast<nsRefreshTimer*>( |
5543 | static_cast<nsITimerCallback*>(refreshInfo)) |
5544 | ->GetDelay(); |
5545 | nsCOMPtr<nsPIDOMWindowOuter> win = GetWindow(); |
5546 | if (win) { |
5547 | nsCOMPtr<nsITimer> timer; |
5548 | NS_NewTimerWithCallback(getter_AddRefs(timer), refreshInfo, delay, |
5549 | nsITimer::TYPE_ONE_SHOT); |
5550 | |
5551 | if (timer) { |
5552 | // Replace the nsRefreshTimer element in the queue with |
5553 | // its corresponding timer object, so that in case another |
5554 | // load comes through before the timer can go off, the timer will |
5555 | // get cancelled in CancelRefreshURITimer() |
5556 | mRefreshURIList->ReplaceElementAt(timer, n); |
5557 | } |
5558 | } |
5559 | } |
5560 | } |
5561 | |
5562 | return NS_OK; |
5563 | } |
5564 | |
5565 | static bool IsFollowupPartOfMultipart(nsIRequest* aRequest) { |
5566 | nsCOMPtr<nsIMultiPartChannel> multiPartChannel = do_QueryInterface(aRequest); |
5567 | bool firstPart = false; |
5568 | return multiPartChannel && |
5569 | NS_SUCCEEDED(multiPartChannel->GetIsFirstPart(&firstPart))((bool)(__builtin_expect(!!(!NS_FAILED_impl(multiPartChannel-> GetIsFirstPart(&firstPart))), 1))) && |
5570 | !firstPart; |
5571 | } |
5572 | |
5573 | nsresult nsDocShell::Embed(nsIDocumentViewer* aDocumentViewer, |
5574 | WindowGlobalChild* aWindowActor, |
5575 | bool aIsTransientAboutBlank, nsIRequest* aRequest, |
5576 | nsIURI* aPreviousURI) { |
5577 | // Save the LayoutHistoryState of the previous document, before |
5578 | // setting up new document |
5579 | PersistLayoutHistoryState(); |
5580 | |
5581 | nsresult rv = SetupNewViewer(aDocumentViewer, aWindowActor); |
5582 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 5582); return rv; } } while (false); |
5583 | |
5584 | // XXX What if SetupNewViewer fails? |
5585 | if (mozilla::SessionHistoryInParent() ? !!mLoadingEntry : !!mLSHE) { |
5586 | // Set history.state |
5587 | SetDocCurrentStateObj(mLSHE, |
5588 | mLoadingEntry ? &mLoadingEntry->mInfo : nullptr); |
5589 | } |
5590 | |
5591 | if (mLSHE) { |
5592 | // Restore the editing state, if it's stored in session history. |
5593 | if (mLSHE->HasDetachedEditor()) { |
5594 | ReattachEditorToWindow(mLSHE); |
5595 | } |
5596 | |
5597 | SetHistoryEntryAndUpdateBC(Nothing(), Some<nsISHEntry*>(mLSHE)); |
5598 | } |
5599 | |
5600 | if (!aIsTransientAboutBlank && mozilla::SessionHistoryInParent() && |
5601 | !IsFollowupPartOfMultipart(aRequest)) { |
5602 | bool expired = false; |
5603 | uint32_t cacheKey = 0; |
5604 | nsCOMPtr<nsICacheInfoChannel> cacheChannel = do_QueryInterface(aRequest); |
5605 | if (cacheChannel) { |
5606 | // Check if the page has expired from cache |
5607 | uint32_t expTime = 0; |
5608 | cacheChannel->GetCacheTokenExpirationTime(&expTime); |
5609 | uint32_t now = PRTimeToSeconds(PR_Now()); |
5610 | if (expTime <= now) { |
5611 | expired = true; |
5612 | } |
5613 | |
5614 | // The checks for updating cache key are similar to the old session |
5615 | // history in OnNewURI. Try to update the cache key if |
5616 | // - we should update session history and aren't doing a session |
5617 | // history load. |
5618 | // - we're doing a forced reload. |
5619 | if (((!mLoadingEntry || !mLoadingEntry->mLoadIsFromSessionHistory) && |
5620 | mBrowsingContext->ShouldUpdateSessionHistory(mLoadType)) || |
5621 | IsForceReloadType(mLoadType)) { |
5622 | cacheChannel->GetCacheKey(&cacheKey); |
5623 | } |
5624 | } |
5625 | |
5626 | nsCOMPtr<nsIPrincipal> partitionedPrincipal; |
5627 | RefPtr<Document> doc = GetDocument(); |
5628 | if (doc) { |
5629 | partitionedPrincipal = doc->PartitionedPrincipal(); |
5630 | } |
5631 | |
5632 | MOZ_LOG(gSHLog, LogLevel::Debug, ("document %p Embed", this))do { const ::mozilla::LogModule* moz_real_module = gSHLog; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "document %p Embed", this); } } while (0); |
5633 | |
5634 | MoveLoadingToActiveEntry(expired, cacheKey, aPreviousURI, |
5635 | partitionedPrincipal); |
5636 | } |
5637 | |
5638 | bool updateHistory = true; |
5639 | |
5640 | // Determine if this type of load should update history |
5641 | switch (mLoadType) { |
5642 | case LOAD_NORMAL_REPLACE: |
5643 | case LOAD_REFRESH_REPLACE: |
5644 | case LOAD_STOP_CONTENT_AND_REPLACE: |
5645 | case LOAD_RELOAD_BYPASS_CACHE: |
5646 | case LOAD_RELOAD_BYPASS_PROXY: |
5647 | case LOAD_RELOAD_BYPASS_PROXY_AND_CACHE: |
5648 | case LOAD_REPLACE_BYPASS_CACHE: |
5649 | updateHistory = false; |
5650 | break; |
5651 | default: |
5652 | break; |
5653 | } |
5654 | |
5655 | if (!updateHistory) { |
5656 | SetLayoutHistoryState(nullptr); |
5657 | } |
5658 | |
5659 | return NS_OK; |
5660 | } |
5661 | |
5662 | //***************************************************************************** |
5663 | // nsDocShell::nsIWebProgressListener |
5664 | //***************************************************************************** |
5665 | |
5666 | NS_IMETHODIMPnsresult |
5667 | nsDocShell::OnProgressChange(nsIWebProgress* aProgress, nsIRequest* aRequest, |
5668 | int32_t aCurSelfProgress, int32_t aMaxSelfProgress, |
5669 | int32_t aCurTotalProgress, |
5670 | int32_t aMaxTotalProgress) { |
5671 | // Listeners in the parent process only care about aCurTotalProgress and |
5672 | // aMaxTotalProgress, which is internally managed by nsDocLoader. Because of |
5673 | // this, we don't send progress notifications except when they are recorded by |
5674 | // the toplevel context, and only report them on the toplevel context in the |
5675 | // parent process. |
5676 | // |
5677 | // FIXME: We should track progress for out-of-process iframes and manage total |
5678 | // progress in the parent process for more accurate notifications. |
5679 | MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType< decltype(mBrowsingContext->IsTop())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mBrowsingContext->IsTop() ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "mBrowsingContext->IsTop()" " (" "notification excluded in AddProgressListener(...) for non-toplevel BCs" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 5681 ); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mBrowsingContext->IsTop()" ") (" "notification excluded in AddProgressListener(...) for non-toplevel BCs" ")"); do { MOZ_CrashSequence(__null, 5681); __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
5680 | mBrowsingContext->IsTop(),do { static_assert( mozilla::detail::AssertionConditionType< decltype(mBrowsingContext->IsTop())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mBrowsingContext->IsTop() ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "mBrowsingContext->IsTop()" " (" "notification excluded in AddProgressListener(...) for non-toplevel BCs" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 5681 ); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mBrowsingContext->IsTop()" ") (" "notification excluded in AddProgressListener(...) for non-toplevel BCs" ")"); do { MOZ_CrashSequence(__null, 5681); __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
5681 | "notification excluded in AddProgressListener(...) for non-toplevel BCs")do { static_assert( mozilla::detail::AssertionConditionType< decltype(mBrowsingContext->IsTop())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mBrowsingContext->IsTop() ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "mBrowsingContext->IsTop()" " (" "notification excluded in AddProgressListener(...) for non-toplevel BCs" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 5681 ); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mBrowsingContext->IsTop()" ") (" "notification excluded in AddProgressListener(...) for non-toplevel BCs" ")"); do { MOZ_CrashSequence(__null, 5681); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
5682 | |
5683 | if (nsCOMPtr<nsIWebProgressListener> listener = BCWebProgressListener()) { |
5684 | listener->OnProgressChange(aProgress, aRequest, aCurSelfProgress, |
5685 | aMaxSelfProgress, aCurTotalProgress, |
5686 | aMaxTotalProgress); |
5687 | } |
5688 | |
5689 | return NS_OK; |
5690 | } |
5691 | |
5692 | NS_IMETHODIMPnsresult |
5693 | nsDocShell::OnStateChange(nsIWebProgress* aProgress, nsIRequest* aRequest, |
5694 | uint32_t aStateFlags, nsresult aStatus) { |
5695 | // If we're receiving a notification on ourselves which has at least one of |
5696 | // the state change flags in kStateChangeFlagFilter, also notify WebProgress |
5697 | // on BrowsingContextWebProgress, potentially over IPC. |
5698 | // |
5699 | // NOTE: We don't notify for bubbled notifications (aProgress != this), as |
5700 | // BrowsingContextWebProgress independently handles event bubbling in the |
5701 | // parent process. |
5702 | // |
5703 | // NOTE: We don't filter notifications when registering our listener, as |
5704 | // `STATE_IS_REDIRECTED_DOCUMENT` cannot be filtered for at registration time. |
5705 | static constexpr uint32_t kStateChangeFlagFilter = |
5706 | STATE_IS_NETWORK | STATE_IS_DOCUMENT | STATE_IS_WINDOW | |
5707 | STATE_IS_REDIRECTED_DOCUMENT; |
5708 | if (aProgress == this && (aStateFlags & kStateChangeFlagFilter) != 0) { |
5709 | if (nsCOMPtr<nsIWebProgressListener> listener = BCWebProgressListener()) { |
5710 | listener->OnStateChange(aProgress, aRequest, aStateFlags, aStatus); |
5711 | } |
5712 | } |
5713 | |
5714 | if ((~aStateFlags & (STATE_START | STATE_IS_NETWORK)) == 0) { |
5715 | // Save timing statistics. |
5716 | nsCOMPtr<nsIChannel> channel(do_QueryInterface(aRequest)); |
5717 | nsCOMPtr<nsIURI> uri; |
5718 | channel->GetURI(getter_AddRefs(uri)); |
5719 | nsAutoCString aURI; |
5720 | uri->GetAsciiSpec(aURI); |
5721 | |
5722 | if (this == aProgress) { |
5723 | mozilla::Unused << MaybeInitTiming(); |
5724 | mTiming->NotifyFetchStart(uri, |
5725 | ConvertLoadTypeToNavigationType(mLoadType)); |
5726 | // If we are starting a DocumentChannel, we need to pass the timing |
5727 | // statistics so that should a process switch occur, the starting type can |
5728 | // be passed to the new DocShell running in the other content process. |
5729 | if (RefPtr<DocumentChannel> docChannel = do_QueryObject(aRequest)) { |
5730 | docChannel->SetNavigationTiming(mTiming); |
5731 | } |
5732 | } |
5733 | |
5734 | // Page has begun to load |
5735 | mBusyFlags = (BusyFlags)(BUSY_FLAGS_BUSY | BUSY_FLAGS_BEFORE_PAGE_LOAD); |
5736 | |
5737 | if ((aStateFlags & STATE_RESTORING) == 0) { |
5738 | if (SessionStorePlatformCollection()) { |
5739 | if (IsForceReloadType(mLoadType)) { |
5740 | if (WindowContext* windowContext = |
5741 | mBrowsingContext->GetCurrentWindowContext()) { |
5742 | SessionStoreChild::From(windowContext->GetWindowGlobalChild()) |
5743 | ->ResetSessionStore(mBrowsingContext, |
5744 | mBrowsingContext->GetSessionStoreEpoch()); |
5745 | } |
5746 | } |
5747 | } |
5748 | } |
5749 | } else if ((~aStateFlags & (STATE_TRANSFERRING | STATE_IS_DOCUMENT)) == 0) { |
5750 | // Page is loading |
5751 | mBusyFlags = (BusyFlags)(BUSY_FLAGS_BUSY | BUSY_FLAGS_PAGE_LOADING); |
5752 | } else if ((aStateFlags & STATE_STOP) && (aStateFlags & STATE_IS_NETWORK)) { |
5753 | // Page has finished loading |
5754 | mBusyFlags = BUSY_FLAGS_NONE; |
5755 | } |
5756 | |
5757 | if ((~aStateFlags & (STATE_IS_DOCUMENT | STATE_STOP)) == 0) { |
5758 | nsCOMPtr<nsIWebProgress> webProgress = |
5759 | do_QueryInterface(GetAsSupports(this)); |
5760 | // Is the document stop notification for this document? |
5761 | if (aProgress == webProgress.get()) { |
5762 | nsCOMPtr<nsIChannel> channel(do_QueryInterface(aRequest)); |
5763 | EndPageLoad(aProgress, channel, aStatus); |
5764 | } |
5765 | } |
5766 | // note that redirect state changes will go through here as well, but it |
5767 | // is better to handle those in OnRedirectStateChange where more |
5768 | // information is available. |
5769 | return NS_OK; |
5770 | } |
5771 | |
5772 | NS_IMETHODIMPnsresult |
5773 | nsDocShell::OnLocationChange(nsIWebProgress* aProgress, nsIRequest* aRequest, |
5774 | nsIURI* aURI, uint32_t aFlags) { |
5775 | // If we're receiving a notification on ourselves, also notify WebProgress on |
5776 | // BrowsingContextWebProgress, potentially over IPC. |
5777 | // |
5778 | // NOTE: We don't notify for bubbled notifications (aProgress != this), as |
5779 | // BrowsingContextWebProgress independently handles event bubbling in the |
5780 | // parent process. |
5781 | // |
5782 | // NOTE: Tests depend on this happening before UpdateSecurityState. |
5783 | if (aProgress == this) { |
5784 | if (nsCOMPtr<nsIWebProgressListener> listener = BCWebProgressListener()) { |
5785 | listener->OnLocationChange(aProgress, aRequest, aURI, aFlags); |
5786 | } |
5787 | } |
5788 | |
5789 | // Since we've now changed Documents, notify the BrowsingContext that we've |
5790 | // changed. Ideally we'd just let the BrowsingContext do this when it |
5791 | // changes the current window global, but that happens before this and we |
5792 | // have a lot of tests that depend on the specific ordering of messages. |
5793 | bool isTopLevel = false; |
5794 | if (XRE_IsParentProcess() && |
5795 | !(aFlags & nsIWebProgressListener::LOCATION_CHANGE_SAME_DOCUMENT) && |
5796 | NS_SUCCEEDED(aProgress->GetIsTopLevel(&isTopLevel))((bool)(__builtin_expect(!!(!NS_FAILED_impl(aProgress->GetIsTopLevel (&isTopLevel))), 1))) && isTopLevel) { |
5797 | GetBrowsingContext()->Canonical()->UpdateSecurityState(); |
5798 | } |
5799 | return NS_OK; |
5800 | } |
5801 | |
5802 | void nsDocShell::OnRedirectStateChange(nsIChannel* aOldChannel, |
5803 | nsIChannel* aNewChannel, |
5804 | uint32_t aRedirectFlags, |
5805 | uint32_t aStateFlags) { |
5806 | NS_ASSERTION(aStateFlags & STATE_REDIRECTING,do { if (!(aStateFlags & STATE_REDIRECTING)) { NS_DebugBreak (NS_DEBUG_ASSERTION, "Calling OnRedirectStateChange when there is no redirect" , "aStateFlags & STATE_REDIRECTING", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 5807); MOZ_PretendNoReturn(); } } while (0) |
5807 | "Calling OnRedirectStateChange when there is no redirect")do { if (!(aStateFlags & STATE_REDIRECTING)) { NS_DebugBreak (NS_DEBUG_ASSERTION, "Calling OnRedirectStateChange when there is no redirect" , "aStateFlags & STATE_REDIRECTING", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 5807); MOZ_PretendNoReturn(); } } while (0); |
5808 | |
5809 | if (!(aStateFlags & STATE_IS_DOCUMENT)) { |
5810 | return; // not a toplevel document |
5811 | } |
5812 | |
5813 | nsCOMPtr<nsIURI> oldURI, newURI; |
5814 | aOldChannel->GetURI(getter_AddRefs(oldURI)); |
5815 | aNewChannel->GetURI(getter_AddRefs(newURI)); |
5816 | if (!oldURI || !newURI) { |
5817 | return; |
5818 | } |
5819 | |
5820 | // DocumentChannel adds redirect chain to global history in the parent |
5821 | // process. The redirect chain can't be queried from the content process, so |
5822 | // there's no need to update global history here. |
5823 | RefPtr<DocumentChannel> docChannel = do_QueryObject(aOldChannel); |
5824 | if (!docChannel) { |
5825 | // Below a URI visit is saved (see AddURIVisit method doc). |
5826 | // The visit chain looks something like: |
5827 | // ... |
5828 | // Site N - 1 |
5829 | // => Site N |
5830 | // (redirect to =>) Site N + 1 (we are here!) |
5831 | |
5832 | // Get N - 1 and transition type |
5833 | nsCOMPtr<nsIURI> previousURI; |
5834 | uint32_t previousFlags = 0; |
5835 | ExtractLastVisit(aOldChannel, getter_AddRefs(previousURI), &previousFlags); |
5836 | |
5837 | if (aRedirectFlags & nsIChannelEventSink::REDIRECT_INTERNAL || |
5838 | net::ChannelIsPost(aOldChannel)) { |
5839 | // 1. Internal redirects are ignored because they are specific to the |
5840 | // channel implementation. |
5841 | // 2. POSTs are not saved by global history. |
5842 | // |
5843 | // Regardless, we need to propagate the previous visit to the new |
5844 | // channel. |
5845 | SaveLastVisit(aNewChannel, previousURI, previousFlags); |
5846 | } else { |
5847 | // Get the HTTP response code, if available. |
5848 | uint32_t responseStatus = 0; |
5849 | nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aOldChannel); |
5850 | if (httpChannel) { |
5851 | Unused << httpChannel->GetResponseStatus(&responseStatus); |
5852 | } |
5853 | |
5854 | // Add visit N -1 => N |
5855 | AddURIVisit(oldURI, previousURI, previousFlags, responseStatus); |
5856 | |
5857 | // Since N + 1 could be the final destination, we will not save N => N + 1 |
5858 | // here. OnNewURI will do that, so we will cache it. |
5859 | SaveLastVisit(aNewChannel, oldURI, aRedirectFlags); |
5860 | } |
5861 | } |
5862 | |
5863 | if (!(aRedirectFlags & nsIChannelEventSink::REDIRECT_INTERNAL) && |
5864 | mLoadType & (LOAD_CMD_RELOAD | LOAD_CMD_HISTORY)) { |
5865 | mLoadType = LOAD_NORMAL_REPLACE; |
5866 | SetHistoryEntryAndUpdateBC(Some(nullptr), Nothing()); |
5867 | } |
5868 | } |
5869 | |
5870 | NS_IMETHODIMPnsresult |
5871 | nsDocShell::OnStatusChange(nsIWebProgress* aWebProgress, nsIRequest* aRequest, |
5872 | nsresult aStatus, const char16_t* aMessage) { |
5873 | // If we're receiving a notification on ourselves, also notify WebProgress on |
5874 | // BrowsingContextWebProgress, potentially over IPC. |
5875 | // |
5876 | // NOTE: We don't notify for bubbled notifications (aWebProgress != this), as |
5877 | // BrowsingContextWebProgress independently handles event bubbling in the |
5878 | // parent process. |
5879 | if (aWebProgress == this) { |
5880 | if (nsCOMPtr<nsIWebProgressListener> listener = BCWebProgressListener()) { |
5881 | listener->OnStatusChange(aWebProgress, aRequest, aStatus, aMessage); |
5882 | } |
5883 | } |
5884 | |
5885 | return NS_OK; |
5886 | } |
5887 | |
5888 | NS_IMETHODIMPnsresult |
5889 | nsDocShell::OnSecurityChange(nsIWebProgress* aWebProgress, nsIRequest* aRequest, |
5890 | uint32_t aState) { |
5891 | // If we're receiving a notification on ourselves, also notify WebProgress on |
5892 | // BrowsingContextWebProgress, potentially over IPC. |
5893 | // |
5894 | // NOTE: We don't notify for bubbled notifications (aWebProgress != this), as |
5895 | // BrowsingContextWebProgress independently handles event bubbling in the |
5896 | // parent process. |
5897 | if (aWebProgress == this) { |
5898 | if (nsCOMPtr<nsIWebProgressListener> listener = BCWebProgressListener()) { |
5899 | listener->OnSecurityChange(aWebProgress, aRequest, aState); |
5900 | } |
5901 | } |
5902 | |
5903 | return NS_OK; |
5904 | } |
5905 | |
5906 | NS_IMETHODIMPnsresult |
5907 | nsDocShell::OnContentBlockingEvent(nsIWebProgress* aWebProgress, |
5908 | nsIRequest* aRequest, uint32_t aEvent) { |
5909 | MOZ_ASSERT_UNREACHABLE("notification excluded in AddProgressListener(...)")do { static_assert( mozilla::detail::AssertionConditionType< decltype(false)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: " "notification excluded in AddProgressListener(...)" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 5909); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: " "notification excluded in AddProgressListener(...)" ")"); do { MOZ_CrashSequence(__null, 5909); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
5910 | return NS_OK; |
5911 | } |
5912 | |
5913 | already_AddRefed<nsIWebProgressListener> nsDocShell::BCWebProgressListener() { |
5914 | // If this BrowsingContext has been replaced, we should discard any |
5915 | // notifications which would otherwise be delivered in-process. |
5916 | if (XRE_IsParentProcess() && mBrowsingContext->Canonical()->IsReplaced()) { |
5917 | return nullptr; |
5918 | } |
5919 | |
5920 | // Create a nsBrowserStatusFilter to perform some throttling of |
5921 | // OnProgressChange and OnStatusChange notifications which are delivered to |
5922 | // our BCWebProgress listener. This reduces the amount of IPC traffic. |
5923 | if (!mBCWebProgressStatusFilter && !mIsBeingDestroyed) { |
5924 | nsCOMPtr<nsIWebProgressListener> innerListener; |
5925 | if (XRE_IsParentProcess()) { |
5926 | innerListener = mBrowsingContext->Canonical()->GetWebProgress(); |
5927 | } else { |
5928 | innerListener = do_QueryReferent(mBrowserChild); |
5929 | } |
5930 | if (innerListener) { |
5931 | // NOTE: We need to disable filtering of StateChange events here, as |
5932 | // listeners on BrowsingContextWebProgress may depend on state change |
5933 | // notifications are otherwise filtered. |
5934 | // NOTE: Unlike other nsIWebProgress types, nsBrowserStatusFilter holds a |
5935 | // strong cycle-collected reference to the inner listener. |
5936 | mBCWebProgressStatusFilter = |
5937 | new nsBrowserStatusFilter(/* aDisableStateChangeFilters */ true); |
5938 | mBCWebProgressStatusFilter->AddProgressListener( |
5939 | innerListener, nsIWebProgress::NOTIFY_ALL); |
5940 | } |
5941 | } |
5942 | |
5943 | return do_AddRef(mBCWebProgressStatusFilter); |
5944 | } |
5945 | |
5946 | already_AddRefed<nsIURIFixupInfo> nsDocShell::KeywordToURI( |
5947 | const nsACString& aKeyword, bool aIsPrivateContext) { |
5948 | nsCOMPtr<nsIURIFixupInfo> info; |
5949 | if (!XRE_IsContentProcess()) { |
5950 | nsCOMPtr<nsIURIFixup> uriFixup = components::URIFixup::Service(); |
5951 | if (uriFixup) { |
5952 | uriFixup->KeywordToURI(aKeyword, aIsPrivateContext, getter_AddRefs(info)); |
5953 | } |
5954 | } |
5955 | return info.forget(); |
5956 | } |
5957 | |
5958 | /* static */ |
5959 | already_AddRefed<nsIURI> nsDocShell::MaybeFixBadCertDomainErrorURI( |
5960 | nsIChannel* aChannel, nsIURI* aUrl) { |
5961 | if (!aChannel) { |
5962 | return nullptr; |
5963 | } |
5964 | |
5965 | nsresult rv = NS_OK; |
5966 | nsAutoCString host; |
5967 | rv = aUrl->GetAsciiHost(host); |
5968 | if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv )), 0))), "NS_FAILED(rv)", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 5968)) { |
5969 | return nullptr; |
5970 | } |
5971 | |
5972 | // Return if fixup enable pref is turned off. |
5973 | if (!mozilla::StaticPrefs::security_bad_cert_domain_error_url_fix_enabled()) { |
5974 | return nullptr; |
5975 | } |
5976 | |
5977 | // Return if scheme is not HTTPS. |
5978 | if (!aUrl->SchemeIs("https")) { |
5979 | return nullptr; |
5980 | } |
5981 | |
5982 | nsCOMPtr<nsILoadInfo> info = aChannel->LoadInfo(); |
5983 | if (!info) { |
5984 | return nullptr; |
5985 | } |
5986 | |
5987 | // Skip doing the fixup if our channel was redirected, because we |
5988 | // shouldn't be guessing things about the post-redirect URI. |
5989 | if (!info->RedirectChain().IsEmpty()) { |
5990 | return nullptr; |
5991 | } |
5992 | |
5993 | int32_t port = 0; |
5994 | rv = aUrl->GetPort(&port); |
5995 | if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv )), 0))), "NS_FAILED(rv)", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 5995)) { |
5996 | return nullptr; |
5997 | } |
5998 | |
5999 | // Don't fix up hosts with ports. |
6000 | if (port != -1) { |
6001 | return nullptr; |
6002 | } |
6003 | |
6004 | // Don't fix up localhost url. |
6005 | if (host == "localhost") { |
6006 | return nullptr; |
6007 | } |
6008 | |
6009 | // Don't fix up hostnames with IP address. |
6010 | if (net_IsValidIPv4Addr(host) || net_IsValidIPv6Addr(host)) { |
6011 | return nullptr; |
6012 | } |
6013 | |
6014 | nsAutoCString userPass; |
6015 | rv = aUrl->GetUserPass(userPass); |
6016 | if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv )), 0))), "NS_FAILED(rv)", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 6016)) { |
6017 | return nullptr; |
6018 | } |
6019 | |
6020 | // Security - URLs with user / password info should NOT be modified. |
6021 | if (!userPass.IsEmpty()) { |
6022 | return nullptr; |
6023 | } |
6024 | |
6025 | nsCOMPtr<nsITransportSecurityInfo> tsi; |
6026 | rv = aChannel->GetSecurityInfo(getter_AddRefs(tsi)); |
6027 | if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv )), 0))), "NS_FAILED(rv)", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 6027)) { |
6028 | return nullptr; |
6029 | } |
6030 | |
6031 | if (NS_WARN_IF(!tsi)NS_warn_if_impl(!tsi, "!tsi", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 6031)) { |
6032 | return nullptr; |
6033 | } |
6034 | |
6035 | nsCOMPtr<nsIX509Cert> cert; |
6036 | rv = tsi->GetServerCert(getter_AddRefs(cert)); |
6037 | if (NS_WARN_IF(NS_FAILED(rv) || !cert)NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv )), 0))) || !cert, "NS_FAILED(rv) || !cert", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 6037)) { |
6038 | return nullptr; |
6039 | } |
6040 | |
6041 | nsTArray<uint8_t> certBytes; |
6042 | rv = cert->GetRawDER(certBytes); |
6043 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
6044 | return nullptr; |
6045 | } |
6046 | |
6047 | mozilla::pkix::Input serverCertInput; |
6048 | mozilla::pkix::Result result = |
6049 | serverCertInput.Init(certBytes.Elements(), certBytes.Length()); |
6050 | if (result != mozilla::pkix::Success) { |
6051 | return nullptr; |
6052 | } |
6053 | |
6054 | constexpr auto wwwPrefix = "www."_ns; |
6055 | nsAutoCString newHost; |
6056 | if (StringBeginsWith(host, wwwPrefix)) { |
6057 | // Try www.example.com -> example.com |
6058 | newHost.Assign(Substring(host, wwwPrefix.Length())); |
6059 | } else { |
6060 | // Try example.com -> www.example.com |
6061 | newHost.Assign(wwwPrefix); |
6062 | newHost.Append(host); |
6063 | } |
6064 | |
6065 | mozilla::pkix::Input newHostInput; |
6066 | result = newHostInput.Init( |
6067 | BitwiseCast<const uint8_t*, const char*>(newHost.BeginReading()), |
6068 | newHost.Length()); |
6069 | if (result != mozilla::pkix::Success) { |
6070 | return nullptr; |
6071 | } |
6072 | |
6073 | // Because certificate verification returned Result::ERROR_BAD_CERT_DOMAIN / |
6074 | // SSL_ERROR_BAD_CERT_DOMAIN, a chain was built and we know whether or not |
6075 | // the root was a built-in. |
6076 | bool rootIsBuiltIn; |
6077 | if (NS_FAILED(tsi->GetIsBuiltCertChainRootBuiltInRoot(&rootIsBuiltIn))((bool)(__builtin_expect(!!(NS_FAILED_impl(tsi->GetIsBuiltCertChainRootBuiltInRoot (&rootIsBuiltIn))), 0)))) { |
6078 | return nullptr; |
6079 | } |
6080 | mozilla::psm::SkipInvalidSANsForNonBuiltInRootsPolicy nameMatchingPolicy( |
6081 | rootIsBuiltIn); |
6082 | |
6083 | // Check if the certificate is valid for the new hostname. |
6084 | result = mozilla::pkix::CheckCertHostname(serverCertInput, newHostInput, |
6085 | nameMatchingPolicy); |
6086 | if (result != mozilla::pkix::Success) { |
6087 | return nullptr; |
6088 | } |
6089 | |
6090 | nsCOMPtr<nsIURI> newURI; |
6091 | Unused << NS_MutateURI(aUrl).SetHost(newHost).Finalize( |
6092 | getter_AddRefs(newURI)); |
6093 | |
6094 | return newURI.forget(); |
6095 | } |
6096 | |
6097 | /* static */ |
6098 | already_AddRefed<nsIURI> nsDocShell::AttemptURIFixup( |
6099 | nsIChannel* aChannel, nsresult aStatus, |
6100 | const mozilla::Maybe<nsCString>& aOriginalURIString, uint32_t aLoadType, |
6101 | bool aIsTopFrame, bool aAllowKeywordFixup, bool aUsePrivateBrowsing, |
6102 | bool aNotifyKeywordSearchLoading, nsIInputStream** aNewPostData, |
6103 | nsILoadInfo::SchemelessInputType* outSchemelessInput) { |
6104 | if (aStatus != NS_ERROR_UNKNOWN_HOST && aStatus != NS_ERROR_NET_RESET && |
6105 | aStatus != NS_ERROR_CONNECTION_REFUSED && |
6106 | aStatus != |
6107 | mozilla::psm::GetXPCOMFromNSSError(SSL_ERROR_BAD_CERT_DOMAIN)) { |
6108 | return nullptr; |
6109 | } |
6110 | |
6111 | if (!(aLoadType == LOAD_NORMAL && aIsTopFrame) && !aAllowKeywordFixup) { |
6112 | return nullptr; |
6113 | } |
6114 | |
6115 | nsCOMPtr<nsIURI> url; |
6116 | nsresult rv = aChannel->GetURI(getter_AddRefs(url)); |
6117 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
6118 | return nullptr; |
6119 | } |
6120 | |
6121 | // |
6122 | // Try and make an alternative URI from the old one |
6123 | // |
6124 | nsCOMPtr<nsIURI> newURI; |
6125 | nsCOMPtr<nsIInputStream> newPostData; |
6126 | |
6127 | nsAutoCString oldSpec; |
6128 | url->GetSpec(oldSpec); |
6129 | |
6130 | // |
6131 | // First try keyword fixup |
6132 | // |
6133 | nsAutoString keywordProviderName, keywordAsSent; |
6134 | if (aStatus == NS_ERROR_UNKNOWN_HOST && aAllowKeywordFixup) { |
6135 | // we should only perform a keyword search under the following |
6136 | // conditions: |
6137 | // (0) Pref keyword.enabled is true |
6138 | // (1) the url scheme is http (or https) |
6139 | // (2) the url does not have a protocol scheme |
6140 | // If we don't enforce such a policy, then we end up doing |
6141 | // keyword searchs on urls we don't intend like imap, file, |
6142 | // mailbox, etc. This could lead to a security problem where we |
6143 | // send data to the keyword server that we shouldn't be. |
6144 | // Someone needs to clean up keywords in general so we can |
6145 | // determine on a per url basis if we want keywords |
6146 | // enabled...this is just a bandaid... |
6147 | if (Preferences::GetBool("keyword.enabled", false) && |
6148 | net::SchemeIsHttpOrHttps(url)) { |
6149 | bool attemptFixup = false; |
6150 | nsAutoCString host; |
6151 | Unused << url->GetHost(host); |
6152 | if (host.FindChar('.') == kNotFound) { |
6153 | attemptFixup = true; |
6154 | } else { |
6155 | // For domains with dots, we check the public suffix validity. |
6156 | nsCOMPtr<nsIEffectiveTLDService> tldService = |
6157 | do_GetService(NS_EFFECTIVETLDSERVICE_CONTRACTID"@mozilla.org/network/effective-tld-service;1"); |
6158 | if (tldService) { |
6159 | nsAutoCString suffix; |
6160 | attemptFixup = |
6161 | NS_SUCCEEDED(tldService->GetKnownPublicSuffix(url, suffix))((bool)(__builtin_expect(!!(!NS_FAILED_impl(tldService->GetKnownPublicSuffix (url, suffix))), 1))) && |
6162 | suffix.IsEmpty(); |
6163 | } |
6164 | } |
6165 | if (attemptFixup) { |
6166 | nsCOMPtr<nsIURIFixupInfo> info; |
6167 | // only send non-qualified hosts to the keyword server |
6168 | if (aOriginalURIString && !aOriginalURIString->IsEmpty()) { |
6169 | info = KeywordToURI(*aOriginalURIString, aUsePrivateBrowsing); |
6170 | } else { |
6171 | // |
6172 | // If this string was passed through nsStandardURL by |
6173 | // chance, then it may have been converted from UTF-8 to |
6174 | // Punycode, which would result in a completely bogus keyword |
6175 | // query. Here we try to recover the original Unicode |
6176 | // value, but this is not 100% correct since the value may |
6177 | // have been normalized per the IDN normalization rules. |
6178 | // |
6179 | // Since we don't have access to the exact original string |
6180 | // that was entered by the user, this will just have to do. |
6181 | nsAutoCString utf8Host; |
6182 | mozilla_net_recover_keyword_from_punycode(&host, &utf8Host); |
6183 | info = KeywordToURI(utf8Host, aUsePrivateBrowsing); |
6184 | } |
6185 | if (info) { |
6186 | info->GetPreferredURI(getter_AddRefs(newURI)); |
6187 | info->GetSchemelessInput(outSchemelessInput); |
6188 | if (newURI) { |
6189 | info->GetKeywordAsSent(keywordAsSent); |
6190 | info->GetKeywordProviderName(keywordProviderName); |
6191 | info->GetPostData(getter_AddRefs(newPostData)); |
6192 | } |
6193 | } |
6194 | } |
6195 | } |
6196 | } |
6197 | |
6198 | // |
6199 | // Now try change the address, e.g. turn http://foo into |
6200 | // http://www.foo.com, and if that doesn't work try https with |
6201 | // https://foo and https://www.foo.com. |
6202 | // |
6203 | if (aStatus == NS_ERROR_UNKNOWN_HOST || aStatus == NS_ERROR_NET_RESET) { |
6204 | // Skip fixup for anything except a normal document load |
6205 | // operation on the topframe. |
6206 | bool doCreateAlternate = aLoadType == LOAD_NORMAL && aIsTopFrame; |
6207 | |
6208 | if (doCreateAlternate) { |
6209 | nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo(); |
6210 | nsIPrincipal* principal = loadInfo->TriggeringPrincipal(); |
6211 | // Only do this if our channel was loaded directly by the user from the |
6212 | // URL bar or similar (system principal) and not redirected, because we |
6213 | // shouldn't be guessing things about links from other sites, or a |
6214 | // post-redirect URI. |
6215 | doCreateAlternate = principal && principal->IsSystemPrincipal() && |
6216 | loadInfo->RedirectChain().IsEmpty(); |
6217 | } |
6218 | // Test if keyword lookup produced a new URI or not |
6219 | if (doCreateAlternate && newURI) { |
6220 | bool sameURI = false; |
6221 | url->Equals(newURI, &sameURI); |
6222 | if (!sameURI) { |
6223 | // Keyword lookup made a new URI so no need to try |
6224 | // an alternate one. |
6225 | doCreateAlternate = false; |
6226 | } |
6227 | } |
6228 | if (doCreateAlternate) { |
6229 | newURI = nullptr; |
6230 | newPostData = nullptr; |
6231 | keywordProviderName.Truncate(); |
6232 | keywordAsSent.Truncate(); |
6233 | nsCOMPtr<nsIURIFixup> uriFixup = components::URIFixup::Service(); |
6234 | if (uriFixup) { |
6235 | nsCOMPtr<nsIURIFixupInfo> fixupInfo; |
6236 | uriFixup->GetFixupURIInfo(oldSpec, nsIURIFixup::FIXUP_FLAG_NONE, |
6237 | getter_AddRefs(fixupInfo)); |
6238 | if (fixupInfo) { |
6239 | fixupInfo->GetPreferredURI(getter_AddRefs(newURI)); |
6240 | } |
6241 | } |
6242 | } |
6243 | } else if (aStatus == NS_ERROR_CONNECTION_REFUSED && |
6244 | Preferences::GetBool("browser.fixup.fallback-to-https", false)) { |
6245 | // Try HTTPS, since http didn't work |
6246 | if (url->SchemeIs("http")) { |
6247 | int32_t port = 0; |
6248 | url->GetPort(&port); |
6249 | |
6250 | // Fall back to HTTPS only if port is default |
6251 | if (port == -1) { |
6252 | newURI = nullptr; |
6253 | newPostData = nullptr; |
6254 | Unused << NS_MutateURI(url) |
6255 | .SetScheme("https"_ns) |
6256 | .Finalize(getter_AddRefs(newURI)); |
6257 | } |
6258 | } |
6259 | } |
6260 | |
6261 | // If we have a SSL_ERROR_BAD_CERT_DOMAIN error, try adding or removing |
6262 | // "www." to/from the beginning of the domain name to see if we can avoid |
6263 | // showing the cert error page. For example, https://example.com -> |
6264 | // https://www.example.com or https://www.example.com -> https://example.com. |
6265 | if (aStatus == |
6266 | mozilla::psm::GetXPCOMFromNSSError(SSL_ERROR_BAD_CERT_DOMAIN)) { |
6267 | newPostData = nullptr; |
6268 | newURI = MaybeFixBadCertDomainErrorURI(aChannel, url); |
6269 | } |
6270 | |
6271 | // Did we make a new URI that is different to the old one? If so |
6272 | // load it. |
6273 | // |
6274 | if (newURI) { |
6275 | // Make sure the new URI is different from the old one, |
6276 | // otherwise there's little point trying to load it again. |
6277 | bool sameURI = false; |
6278 | url->Equals(newURI, &sameURI); |
6279 | if (!sameURI) { |
6280 | if (aNewPostData) { |
6281 | newPostData.forget(aNewPostData); |
6282 | } |
6283 | if (aNotifyKeywordSearchLoading) { |
6284 | // This notification is meant for Firefox Health Report so it |
6285 | // can increment counts from the search engine |
6286 | MaybeNotifyKeywordSearchLoading(keywordProviderName, keywordAsSent); |
6287 | } |
6288 | return newURI.forget(); |
6289 | } |
6290 | } |
6291 | |
6292 | return nullptr; |
6293 | } |
6294 | |
6295 | nsresult nsDocShell::FilterStatusForErrorPage( |
6296 | nsresult aStatus, nsIChannel* aChannel, uint32_t aLoadType, |
6297 | bool aIsTopFrame, bool aUseErrorPages, |
6298 | bool* aSkippedUnknownProtocolNavigation) { |
6299 | // Errors to be shown only on top-level frames |
6300 | if ((aStatus == NS_ERROR_UNKNOWN_HOST || |
6301 | aStatus == NS_ERROR_CONNECTION_REFUSED || |
6302 | aStatus == NS_ERROR_UNKNOWN_PROXY_HOST || |
6303 | aStatus == NS_ERROR_PROXY_CONNECTION_REFUSED || |
6304 | aStatus == NS_ERROR_PROXY_FORBIDDEN || |
6305 | aStatus == NS_ERROR_PROXY_NOT_IMPLEMENTED || |
6306 | aStatus == NS_ERROR_PROXY_AUTHENTICATION_FAILED || |
6307 | aStatus == NS_ERROR_PROXY_TOO_MANY_REQUESTS || |
6308 | aStatus == NS_ERROR_MALFORMED_URI || |
6309 | aStatus == NS_ERROR_BLOCKED_BY_POLICY || |
6310 | aStatus == NS_ERROR_DOM_COOP_FAILED || |
6311 | aStatus == NS_ERROR_DOM_COEP_FAILED || |
6312 | aStatus == NS_ERROR_DOM_INVALID_HEADER_VALUE) && |
6313 | (aIsTopFrame || aUseErrorPages)) { |
6314 | return aStatus; |
6315 | } |
6316 | |
6317 | if (aStatus == NS_ERROR_NET_TIMEOUT || |
6318 | aStatus == NS_ERROR_NET_TIMEOUT_EXTERNAL || |
6319 | aStatus == NS_ERROR_NET_EMPTY_RESPONSE || |
6320 | aStatus == NS_ERROR_NET_ERROR_RESPONSE || |
6321 | aStatus == NS_ERROR_PROXY_GATEWAY_TIMEOUT || |
6322 | aStatus == NS_ERROR_REDIRECT_LOOP || |
6323 | aStatus == NS_ERROR_UNKNOWN_SOCKET_TYPE || |
6324 | aStatus == NS_ERROR_NET_INTERRUPT || aStatus == NS_ERROR_NET_RESET || |
6325 | aStatus == NS_ERROR_PROXY_BAD_GATEWAY || aStatus == NS_ERROR_OFFLINE || |
6326 | aStatus == NS_ERROR_MALWARE_URI || aStatus == NS_ERROR_PHISHING_URI || |
6327 | aStatus == NS_ERROR_UNWANTED_URI || aStatus == NS_ERROR_HARMFUL_URI || |
6328 | aStatus == NS_ERROR_UNSAFE_CONTENT_TYPE || |
6329 | aStatus == NS_ERROR_INTERCEPTION_FAILED || |
6330 | aStatus == NS_ERROR_NET_INADEQUATE_SECURITY || |
6331 | aStatus == NS_ERROR_NET_HTTP2_SENT_GOAWAY || |
6332 | aStatus == NS_ERROR_NET_HTTP3_PROTOCOL_ERROR || |
6333 | aStatus == NS_ERROR_BASIC_HTTP_AUTH_DISABLED || |
6334 | aStatus == NS_ERROR_DOM_BAD_URI || aStatus == NS_ERROR_FILE_NOT_FOUND || |
6335 | aStatus == NS_ERROR_FILE_ACCESS_DENIED || |
6336 | aStatus == NS_ERROR_CORRUPTED_CONTENT || |
6337 | aStatus == NS_ERROR_INVALID_CONTENT_ENCODING || |
6338 | NS_ERROR_GET_MODULE(aStatus) == NS_ERROR_MODULE_SECURITY21) { |
6339 | // Errors to be shown for any frame |
6340 | return aStatus; |
6341 | } |
6342 | |
6343 | if (aStatus == NS_ERROR_UNKNOWN_PROTOCOL) { |
6344 | // For unknown protocols we only display an error if the load is triggered |
6345 | // by the browser itself. Showing the error for page-triggered navigations |
6346 | // causes annoying behavior for users when a page tries to open an external |
6347 | // app which has not been installed, see bug 1528305. A missing WebExtension |
6348 | // protocol handlers will however always load the error page, as it is not |
6349 | // expected to be opened externally, see bug 1921426. |
6350 | nsCOMPtr<nsILoadInfo> info = aChannel->LoadInfo(); |
6351 | if (!info->TriggeringPrincipal()->IsSystemPrincipal() && |
6352 | !BasePrincipal::Cast(info->TriggeringPrincipal())->AddonPolicy()) { |
6353 | if (aSkippedUnknownProtocolNavigation) { |
6354 | *aSkippedUnknownProtocolNavigation = true; |
6355 | } |
6356 | return NS_OK; |
6357 | } |
6358 | return aStatus; |
6359 | } |
6360 | |
6361 | if (aStatus == NS_ERROR_DOCUMENT_NOT_CACHED) { |
6362 | // Non-caching channels will simply return NS_ERROR_OFFLINE. |
6363 | // Caching channels would have to look at their flags to work |
6364 | // out which error to return. Or we can fix up the error here. |
6365 | if (!(aLoadType & LOAD_CMD_HISTORY)) { |
6366 | return NS_ERROR_OFFLINE; |
6367 | } |
6368 | return aStatus; |
6369 | } |
6370 | |
6371 | return NS_OK; |
6372 | } |
6373 | |
6374 | nsresult nsDocShell::EndPageLoad(nsIWebProgress* aProgress, |
6375 | nsIChannel* aChannel, nsresult aStatus) { |
6376 | MOZ_LOG(gDocShellLeakLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gDocShellLeakLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "DOCSHELL %p EndPageLoad status: %" "x" "\n" , this, static_cast<uint32_t>(aStatus)); } } while (0) |
6377 | ("DOCSHELL %p EndPageLoad status: %" PRIx32 "\n", this,do { const ::mozilla::LogModule* moz_real_module = gDocShellLeakLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "DOCSHELL %p EndPageLoad status: %" "x" "\n" , this, static_cast<uint32_t>(aStatus)); } } while (0) |
6378 | static_cast<uint32_t>(aStatus)))do { const ::mozilla::LogModule* moz_real_module = gDocShellLeakLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "DOCSHELL %p EndPageLoad status: %" "x" "\n" , this, static_cast<uint32_t>(aStatus)); } } while (0); |
6379 | if (!aChannel) { |
6380 | return NS_ERROR_NULL_POINTER; |
6381 | } |
6382 | |
6383 | // Make sure to discard the initial client if we never created the initial |
6384 | // about:blank document. Do this before possibly returning from the method |
6385 | // due to an error. |
6386 | mInitialClientSource.reset(); |
6387 | |
6388 | nsCOMPtr<nsIConsoleReportCollector> reporter = do_QueryInterface(aChannel); |
6389 | if (reporter) { |
6390 | nsCOMPtr<nsILoadGroup> loadGroup; |
6391 | aChannel->GetLoadGroup(getter_AddRefs(loadGroup)); |
6392 | if (loadGroup) { |
6393 | reporter->FlushConsoleReports(loadGroup); |
6394 | } else { |
6395 | reporter->FlushConsoleReports(GetDocument()); |
6396 | } |
6397 | } |
6398 | |
6399 | nsCOMPtr<nsIURI> url; |
6400 | nsresult rv = aChannel->GetURI(getter_AddRefs(url)); |
6401 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
6402 | return rv; |
6403 | } |
6404 | |
6405 | nsCOMPtr<nsITimedChannel> timingChannel = do_QueryInterface(aChannel); |
6406 | if (timingChannel) { |
6407 | TimeStamp channelCreationTime; |
6408 | rv = timingChannel->GetChannelCreation(&channelCreationTime); |
6409 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && !channelCreationTime.IsNull()) { |
6410 | glean::performance_page::total_content_page_load.AccumulateRawDuration( |
6411 | TimeStamp::Now() - channelCreationTime); |
6412 | } |
6413 | } |
6414 | |
6415 | // Timing is picked up by the window, we don't need it anymore |
6416 | mTiming = nullptr; |
6417 | |
6418 | // clean up reload state for meta charset |
6419 | if (eCharsetReloadRequested == mCharsetReloadState) { |
6420 | mCharsetReloadState = eCharsetReloadStopOrigional; |
6421 | } else { |
6422 | mCharsetReloadState = eCharsetReloadInit; |
6423 | } |
6424 | |
6425 | // Save a pointer to the currently-loading history entry. |
6426 | // nsDocShell::EndPageLoad will clear mLSHE, but we may need this history |
6427 | // entry further down in this method. |
6428 | nsCOMPtr<nsISHEntry> loadingSHE = mLSHE; |
6429 | mozilla::Unused << loadingSHE; // XXX: Not sure if we need this anymore |
6430 | |
6431 | // |
6432 | // one of many safeguards that prevent death and destruction if |
6433 | // someone is so very very rude as to bring this window down |
6434 | // during this load handler. |
6435 | // |
6436 | nsCOMPtr<nsIDocShell> kungFuDeathGrip(this); |
6437 | |
6438 | // Notify the DocumentViewer that the Document has finished loading. This |
6439 | // will cause any OnLoad(...) and PopState(...) handlers to fire. |
6440 | if (!mEODForCurrentDocument && mDocumentViewer) { |
6441 | mIsExecutingOnLoadHandler = true; |
6442 | nsCOMPtr<nsIDocumentViewer> viewer = mDocumentViewer; |
6443 | viewer->LoadComplete(aStatus); |
6444 | mIsExecutingOnLoadHandler = false; |
6445 | |
6446 | mEODForCurrentDocument = true; |
6447 | } |
6448 | /* Check if the httpChannel has any cache-control related response headers, |
6449 | * like no-store, no-cache. If so, update SHEntry so that |
6450 | * when a user goes back/forward to this page, we appropriately do |
6451 | * form value restoration or load from server. |
6452 | */ |
6453 | nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(aChannel)); |
6454 | if (!httpChannel) { |
6455 | // HttpChannel could be hiding underneath a Multipart channel. |
6456 | GetHttpChannel(aChannel, getter_AddRefs(httpChannel)); |
6457 | } |
6458 | |
6459 | if (httpChannel) { |
6460 | // figure out if SH should be saving layout state. |
6461 | bool discardLayoutState = ShouldDiscardLayoutState(httpChannel); |
6462 | if (mLSHE && discardLayoutState && (mLoadType & LOAD_CMD_NORMAL) && |
6463 | (mLoadType != LOAD_BYPASS_HISTORY) && (mLoadType != LOAD_ERROR_PAGE)) { |
6464 | mLSHE->SetSaveLayoutStateFlag(false); |
6465 | } |
6466 | } |
6467 | |
6468 | // Clear mLSHE after calling the onLoadHandlers. This way, if the |
6469 | // onLoadHandler tries to load something different in |
6470 | // itself or one of its children, we can deal with it appropriately. |
6471 | if (mLSHE) { |
6472 | mLSHE->SetLoadType(LOAD_HISTORY); |
6473 | |
6474 | // Clear the mLSHE reference to indicate document loading is done one |
6475 | // way or another. |
6476 | SetHistoryEntryAndUpdateBC(Some(nullptr), Nothing()); |
6477 | } |
6478 | mActiveEntryIsLoadingFromSessionHistory = false; |
6479 | |
6480 | // if there's a refresh header in the channel, this method |
6481 | // will set it up for us. |
6482 | if (mBrowsingContext->IsActive() || !mDisableMetaRefreshWhenInactive) |
6483 | RefreshURIFromQueue(); |
6484 | |
6485 | // Test whether this is the top frame or a subframe |
6486 | bool isTopFrame = mBrowsingContext->IsTop(); |
6487 | |
6488 | bool hadErrorStatus = false; |
6489 | // If status code indicates an error it means that DocumentChannel already |
6490 | // tried to fixup the uri and failed. Throw an error dialog box here. |
6491 | if (NS_FAILED(aStatus)((bool)(__builtin_expect(!!(NS_FAILED_impl(aStatus)), 0)))) { |
6492 | // If we got CONTENT_BLOCKED from EndPageLoad, then we need to fire |
6493 | // the error event to our embedder, since tests are relying on this. |
6494 | // The error event is usually fired by the caller of InternalLoad, but |
6495 | // this particular error can happen asynchronously. |
6496 | // Bug 1629201 is filed for having much clearer decision making around |
6497 | // which cases need error events. |
6498 | bool fireFrameErrorEvent = (aStatus == NS_ERROR_CONTENT_BLOCKED_SHOW_ALT || |
6499 | aStatus == NS_ERROR_CONTENT_BLOCKED); |
6500 | UnblockEmbedderLoadEventForFailure(fireFrameErrorEvent); |
6501 | |
6502 | bool skippedUnknownProtocolNavigation = false; |
6503 | aStatus = FilterStatusForErrorPage(aStatus, aChannel, mLoadType, isTopFrame, |
6504 | mBrowsingContext->GetUseErrorPages(), |
6505 | &skippedUnknownProtocolNavigation); |
6506 | hadErrorStatus = true; |
6507 | if (NS_FAILED(aStatus)((bool)(__builtin_expect(!!(NS_FAILED_impl(aStatus)), 0)))) { |
6508 | if (!mIsBeingDestroyed) { |
6509 | DisplayLoadError(aStatus, url, nullptr, aChannel); |
6510 | } |
6511 | } else if (skippedUnknownProtocolNavigation) { |
6512 | nsAutoCString sanitized; |
6513 | nsTArray<nsString> params; |
6514 | if (NS_SUCCEEDED(NS_GetSanitizedURIStringFromURI(url, sanitized))((bool)(__builtin_expect(!!(!NS_FAILED_impl(NS_GetSanitizedURIStringFromURI (url, sanitized))), 1)))) { |
6515 | params.AppendElement(NS_ConvertUTF8toUTF16(sanitized)); |
6516 | } else { |
6517 | params.AppendElement(u"(unknown uri)"_ns); |
6518 | } |
6519 | nsContentUtils::ReportToConsole( |
6520 | nsIScriptError::warningFlag, "DOM"_ns, GetExtantDocument(), |
6521 | nsContentUtils::eDOM_PROPERTIES, "UnknownProtocolNavigationPrevented", |
6522 | params); |
6523 | } |
6524 | } else { |
6525 | // If we have a host |
6526 | nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo(); |
6527 | PredictorLearnRedirect(url, aChannel, loadInfo->GetOriginAttributes()); |
6528 | } |
6529 | |
6530 | if (hadErrorStatus) { |
6531 | // Don't send session store updates if the reason EndPageLoad was called is |
6532 | // because we are process switching. Sometimes the update takes too long and |
6533 | // incorrectly overrides session store data from the following load. |
6534 | return NS_OK; |
6535 | } |
6536 | if (SessionStorePlatformCollection()) { |
6537 | if (WindowContext* windowContext = |
6538 | mBrowsingContext->GetCurrentWindowContext()) { |
6539 | using Change = SessionStoreChangeListener::Change; |
6540 | |
6541 | // We've finished loading the page and now we want to collect all the |
6542 | // session store state that the page is initialized with. |
6543 | SessionStoreChangeListener::CollectSessionStoreData( |
6544 | windowContext, |
6545 | EnumSet<Change>(Change::Input, Change::Scroll, Change::SessionHistory, |
6546 | Change::WireFrame)); |
6547 | } |
6548 | } |
6549 | |
6550 | return NS_OK; |
6551 | } |
6552 | |
6553 | //***************************************************************************** |
6554 | // nsDocShell: Content Viewer Management |
6555 | //***************************************************************************** |
6556 | |
6557 | nsresult nsDocShell::EnsureDocumentViewer() { |
6558 | if (mDocumentViewer) { |
6559 | return NS_OK; |
6560 | } |
6561 | if (mIsBeingDestroyed) { |
6562 | return NS_ERROR_FAILURE; |
6563 | } |
6564 | |
6565 | nsCOMPtr<nsIContentSecurityPolicy> cspToInheritForAboutBlank; |
6566 | nsCOMPtr<nsIURI> baseURI; |
6567 | nsIPrincipal* principal = GetInheritedPrincipal(false); |
6568 | nsIPrincipal* partitionedPrincipal = GetInheritedPrincipal(false, true); |
6569 | |
6570 | nsCOMPtr<nsIDocShellTreeItem> parentItem; |
6571 | GetInProcessSameTypeParent(getter_AddRefs(parentItem)); |
6572 | if (parentItem) { |
6573 | if (nsCOMPtr<nsPIDOMWindowOuter> domWin = GetWindow()) { |
6574 | nsCOMPtr<Element> parentElement = domWin->GetFrameElementInternal(); |
6575 | if (parentElement) { |
6576 | baseURI = parentElement->GetBaseURI(); |
6577 | cspToInheritForAboutBlank = parentElement->GetCsp(); |
6578 | } |
6579 | } |
6580 | } |
6581 | |
6582 | nsresult rv = CreateAboutBlankDocumentViewer( |
6583 | principal, partitionedPrincipal, cspToInheritForAboutBlank, baseURI, |
6584 | /* aIsInitialDocument */ true); |
6585 | |
6586 | NS_ENSURE_STATE(mDocumentViewer)do { if ((__builtin_expect(!!(!(mDocumentViewer)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "mDocumentViewer" ") failed" , nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 6586); return NS_ERROR_UNEXPECTED; } } while (false); |
6587 | |
6588 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) { |
6589 | RefPtr<Document> doc(GetDocument()); |
6590 | MOZ_ASSERT(doc,do { static_assert( mozilla::detail::AssertionConditionType< decltype(doc)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(doc))), 0))) { do { } while (false ); MOZ_ReportAssertionFailure("doc" " (" "Should have doc if CreateAboutBlankDocumentViewer " "succeeded!" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 6592); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc" ") (" "Should have doc if CreateAboutBlankDocumentViewer " "succeeded!" ")"); do { MOZ_CrashSequence(__null, 6592); __attribute__ ((nomerge)) ::abort(); } while (false); } } while (false) |
6591 | "Should have doc if CreateAboutBlankDocumentViewer "do { static_assert( mozilla::detail::AssertionConditionType< decltype(doc)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(doc))), 0))) { do { } while (false ); MOZ_ReportAssertionFailure("doc" " (" "Should have doc if CreateAboutBlankDocumentViewer " "succeeded!" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 6592); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc" ") (" "Should have doc if CreateAboutBlankDocumentViewer " "succeeded!" ")"); do { MOZ_CrashSequence(__null, 6592); __attribute__ ((nomerge)) ::abort(); } while (false); } } while (false) |
6592 | "succeeded!")do { static_assert( mozilla::detail::AssertionConditionType< decltype(doc)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(doc))), 0))) { do { } while (false ); MOZ_ReportAssertionFailure("doc" " (" "Should have doc if CreateAboutBlankDocumentViewer " "succeeded!" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 6592); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc" ") (" "Should have doc if CreateAboutBlankDocumentViewer " "succeeded!" ")"); do { MOZ_CrashSequence(__null, 6592); __attribute__ ((nomerge)) ::abort(); } while (false); } } while (false); |
6593 | MOZ_ASSERT(doc->IsInitialDocument(), "Document should be initial document")do { static_assert( mozilla::detail::AssertionConditionType< decltype(doc->IsInitialDocument())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(doc->IsInitialDocument()) )), 0))) { do { } while (false); MOZ_ReportAssertionFailure("doc->IsInitialDocument()" " (" "Document should be initial document" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 6593); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc->IsInitialDocument()" ") (" "Document should be initial document" ")"); do { MOZ_CrashSequence (__null, 6593); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); |
6594 | |
6595 | // Documents created using EnsureDocumentViewer may be transient |
6596 | // placeholders created by framescripts before content has a |
6597 | // chance to load. In some cases, window.open(..., "noopener") |
6598 | // will create such a document and then synchronously tear it |
6599 | // down, firing a "pagehide" event. Doing so violates our |
6600 | // assertions about DocGroups. It's easier to silence the |
6601 | // assertion here than to avoid creating the extra document. |
6602 | doc->IgnoreDocGroupMismatches(); |
6603 | } |
6604 | |
6605 | return rv; |
6606 | } |
6607 | |
6608 | nsresult nsDocShell::CreateAboutBlankDocumentViewer( |
6609 | nsIPrincipal* aPrincipal, nsIPrincipal* aPartitionedPrincipal, |
6610 | nsIContentSecurityPolicy* aCSP, nsIURI* aBaseURI, bool aIsInitialDocument, |
6611 | const Maybe<nsILoadInfo::CrossOriginEmbedderPolicy>& aCOEP, |
6612 | bool aTryToSaveOldPresentation, bool aCheckPermitUnload, |
6613 | WindowGlobalChild* aActor) { |
6614 | RefPtr<Document> blankDoc; |
6615 | nsCOMPtr<nsIDocumentViewer> viewer; |
6616 | nsresult rv = NS_ERROR_FAILURE; |
6617 | |
6618 | PROFILER_MARKER_UNTYPED("CreateAboutBlankDocumentViewer", DOM,do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl ("CreateAboutBlankDocumentViewer", ::geckoprofiler::category:: DOM, MarkerStack::Capture()); } } while (false); } while (false ) |
6619 | MarkerStack::Capture())do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl ("CreateAboutBlankDocumentViewer", ::geckoprofiler::category:: DOM, MarkerStack::Capture()); } } while (false); } while (false ); |
6620 | |
6621 | MOZ_ASSERT_IF(aActor, aActor->DocumentPrincipal() == aPrincipal)do { if (aActor) { do { static_assert( mozilla::detail::AssertionConditionType <decltype(aActor->DocumentPrincipal() == aPrincipal)> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(aActor->DocumentPrincipal() == aPrincipal))), 0)) ) { do { } while (false); MOZ_ReportAssertionFailure("aActor->DocumentPrincipal() == aPrincipal" , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 6621); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "aActor->DocumentPrincipal() == aPrincipal" ")"); do { MOZ_CrashSequence(__null, 6621); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); |
6622 | |
6623 | /* mCreatingDocument should never be true at this point. However, it's |
6624 | a theoretical possibility. We want to know about it and make it stop, |
6625 | and this sounds like a job for an assertion. */ |
6626 | NS_ASSERTION(!mCreatingDocument,do { if (!(!mCreatingDocument)) { NS_DebugBreak(NS_DEBUG_ASSERTION , "infinite(?) loop creating document averted", "!mCreatingDocument" , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 6627); MOZ_PretendNoReturn (); } } while (0) |
6627 | "infinite(?) loop creating document averted")do { if (!(!mCreatingDocument)) { NS_DebugBreak(NS_DEBUG_ASSERTION , "infinite(?) loop creating document averted", "!mCreatingDocument" , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 6627); MOZ_PretendNoReturn (); } } while (0); |
6628 | if (mCreatingDocument) { |
6629 | return NS_ERROR_FAILURE; |
6630 | } |
6631 | |
6632 | if (!mBrowsingContext->AncestorsAreCurrent() || |
6633 | (mozilla::SessionHistoryInParent() && mBrowsingContext->IsInBFCache())) { |
6634 | mBrowsingContext->RemoveRootFromBFCacheSync(); |
6635 | return NS_ERROR_NOT_AVAILABLE; |
6636 | } |
6637 | |
6638 | // mDocumentViewer->PermitUnload may release |this| docshell. |
6639 | nsCOMPtr<nsIDocShell> kungFuDeathGrip(this); |
6640 | |
6641 | // Ensure that UsesOriginAgentCluster has been initialized for this |
6642 | // BrowsingContextGroup/principal pair before creating the document. |
6643 | if (aPrincipal) { |
6644 | mBrowsingContext->Group()->EnsureUsesOriginAgentClusterInitialized( |
6645 | aPrincipal); |
6646 | } |
6647 | |
6648 | AutoRestore<bool> creatingDocument(mCreatingDocument); |
6649 | mCreatingDocument = true; |
6650 | |
6651 | if (aPrincipal && !aPrincipal->IsSystemPrincipal() && |
6652 | mItemType != typeChrome) { |
6653 | MOZ_ASSERT(aPrincipal->OriginAttributesRef() ==do { static_assert( mozilla::detail::AssertionConditionType< decltype(aPrincipal->OriginAttributesRef() == mBrowsingContext ->OriginAttributesRef())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aPrincipal->OriginAttributesRef () == mBrowsingContext->OriginAttributesRef()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aPrincipal->OriginAttributesRef() == mBrowsingContext->OriginAttributesRef()" , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 6654); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "aPrincipal->OriginAttributesRef() == mBrowsingContext->OriginAttributesRef()" ")"); do { MOZ_CrashSequence(__null, 6654); __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
6654 | mBrowsingContext->OriginAttributesRef())do { static_assert( mozilla::detail::AssertionConditionType< decltype(aPrincipal->OriginAttributesRef() == mBrowsingContext ->OriginAttributesRef())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aPrincipal->OriginAttributesRef () == mBrowsingContext->OriginAttributesRef()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aPrincipal->OriginAttributesRef() == mBrowsingContext->OriginAttributesRef()" , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 6654); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "aPrincipal->OriginAttributesRef() == mBrowsingContext->OriginAttributesRef()" ")"); do { MOZ_CrashSequence(__null, 6654); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
6655 | } |
6656 | |
6657 | // Make sure timing is created. But first record whether we had it |
6658 | // already, so we don't clobber the timing for an in-progress load. |
6659 | bool hadTiming = mTiming; |
6660 | bool toBeReset = MaybeInitTiming(); |
6661 | if (mDocumentViewer) { |
6662 | if (aCheckPermitUnload) { |
6663 | // We've got a content viewer already. Make sure the user |
6664 | // permits us to discard the current document and replace it |
6665 | // with about:blank. And also ensure we fire the unload events |
6666 | // in the current document. |
6667 | |
6668 | // Unload gets fired first for |
6669 | // document loaded from the session history. |
6670 | mTiming->NotifyBeforeUnload(); |
6671 | |
6672 | bool okToUnload; |
6673 | rv = mDocumentViewer->PermitUnload(&okToUnload); |
6674 | |
6675 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && !okToUnload) { |
6676 | // The user chose not to unload the page, interrupt the load. |
6677 | MaybeResetInitTiming(toBeReset); |
6678 | return NS_ERROR_FAILURE; |
6679 | } |
6680 | if (mTiming) { |
6681 | mTiming->NotifyUnloadAccepted(mCurrentURI); |
6682 | } |
6683 | } |
6684 | |
6685 | mSavingOldViewer = |
6686 | aTryToSaveOldPresentation && |
6687 | CanSavePresentation(LOAD_NORMAL, nullptr, nullptr, |
6688 | /* aReportBFCacheComboTelemetry */ true); |
6689 | |
6690 | // Make sure to blow away our mLoadingURI just in case. No loads |
6691 | // from inside this pagehide. |
6692 | mLoadingURI = nullptr; |
6693 | |
6694 | // Stop any in-progress loading, so that we don't accidentally trigger any |
6695 | // PageShow notifications from Embed() interrupting our loading below. |
6696 | Stop(); |
6697 | |
6698 | // Notify the current document that it is about to be unloaded!! |
6699 | // |
6700 | // It is important to fire the unload() notification *before* any state |
6701 | // is changed within the DocShell - otherwise, javascript will get the |
6702 | // wrong information :-( |
6703 | // |
6704 | (void)FirePageHideNotification(!mSavingOldViewer); |
6705 | // pagehide notification might destroy this docshell. |
6706 | if (mIsBeingDestroyed) { |
6707 | return NS_ERROR_DOCSHELL_DYING; |
6708 | } |
6709 | } |
6710 | |
6711 | // Now make sure we don't think we're in the middle of firing unload after |
6712 | // this point. This will make us fire unload when the about:blank document |
6713 | // unloads... but that's ok, more or less. Would be nice if it fired load |
6714 | // too, of course. |
6715 | mFiredUnloadEvent = false; |
6716 | |
6717 | nsCOMPtr<nsIDocumentLoaderFactory> docFactory = |
6718 | nsContentUtils::FindInternalDocumentViewer("text/html"_ns); |
6719 | |
6720 | if (docFactory) { |
6721 | nsCOMPtr<nsIPrincipal> principal, partitionedPrincipal; |
6722 | const uint32_t sandboxFlags = |
6723 | mBrowsingContext->GetHasLoadedNonInitialDocument() |
6724 | ? mBrowsingContext->GetSandboxFlags() |
6725 | : mBrowsingContext->GetInitialSandboxFlags(); |
6726 | // If we're sandboxed, then create a new null principal. We skip |
6727 | // this if we're being created from WindowGlobalChild, since in |
6728 | // that case we already have a null principal if required. |
6729 | // We can't compare againt the BrowsingContext sandbox flag, since |
6730 | // the value was taken when the load initiated and may have since |
6731 | // changed. |
6732 | if ((sandboxFlags & SANDBOXED_ORIGIN) && !aActor) { |
6733 | if (aPrincipal) { |
6734 | principal = NullPrincipal::CreateWithInheritedAttributes(aPrincipal); |
6735 | } else { |
6736 | principal = NullPrincipal::Create(GetOriginAttributes()); |
6737 | } |
6738 | partitionedPrincipal = principal; |
6739 | } else { |
6740 | principal = aPrincipal; |
6741 | partitionedPrincipal = aPartitionedPrincipal; |
6742 | } |
6743 | |
6744 | // We cannot get the foreign partitioned prinicpal for the initial |
6745 | // about:blank page. So, we change to check if we need to use the |
6746 | // partitioned principal for the service worker here. |
6747 | MaybeCreateInitialClientSource( |
6748 | StoragePrincipalHelper::ShouldUsePartitionPrincipalForServiceWorker( |
6749 | this) |
6750 | ? partitionedPrincipal |
6751 | : principal); |
6752 | |
6753 | // generate (about:blank) document to load |
6754 | blankDoc = nsContentDLF::CreateBlankDocument(mLoadGroup, principal, |
6755 | partitionedPrincipal, this); |
6756 | if (blankDoc) { |
6757 | // Hack: manually set the CSP for the new document |
6758 | // Please create an actual copy of the CSP (do not share the same |
6759 | // reference) otherwise appending a new policy within the new |
6760 | // document will be incorrectly propagated to the opening doc. |
6761 | if (aCSP) { |
6762 | RefPtr<nsCSPContext> cspToInherit = new nsCSPContext(); |
6763 | cspToInherit->InitFromOther(static_cast<nsCSPContext*>(aCSP)); |
6764 | blankDoc->SetCsp(cspToInherit); |
6765 | } |
6766 | |
6767 | blankDoc->SetIsInitialDocument(aIsInitialDocument); |
6768 | |
6769 | blankDoc->SetEmbedderPolicy(aCOEP); |
6770 | |
6771 | // Hack: set the base URI manually, since this document never |
6772 | // got Reset() with a channel. |
6773 | blankDoc->SetBaseURI(aBaseURI); |
6774 | |
6775 | // Copy our sandbox flags to the document. These are immutable |
6776 | // after being set here. |
6777 | blankDoc->SetSandboxFlags(sandboxFlags); |
6778 | |
6779 | // We inherit the classification flags from the parent document if the |
6780 | // principal matches. |
6781 | nsCOMPtr<nsIDocShellTreeItem> parentItem; |
6782 | GetInProcessSameTypeParent(getter_AddRefs(parentItem)); |
6783 | if (parentItem) { |
6784 | RefPtr<Document> parentDocument = parentItem->GetDocument(); |
6785 | if (parentDocument && principal && |
6786 | principal->Equals(parentDocument->NodePrincipal())) { |
6787 | blankDoc->SetClassificationFlags( |
6788 | parentDocument->GetClassificationFlags()); |
6789 | } |
6790 | } |
6791 | |
6792 | // create a content viewer for us and the new document |
6793 | docFactory->CreateInstanceForDocument( |
6794 | NS_ISUPPORTS_CAST(nsIDocShell*, this)static_cast<nsISupports*>(static_cast<nsIDocShell*> (this)), blankDoc, "view", |
6795 | getter_AddRefs(viewer)); |
6796 | |
6797 | // hook 'em up |
6798 | if (viewer) { |
6799 | viewer->SetContainer(this); |
6800 | if (mLoadingEntry && mBrowsingContext->IsTop()) { |
6801 | mLoadingEntry->mInfo.SetTransient(); |
6802 | } |
6803 | rv = Embed(viewer, aActor, true, nullptr, mCurrentURI); |
6804 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 6804); return rv; } } while (false); |
6805 | |
6806 | SetCurrentURI(blankDoc->GetDocumentURI(), nullptr, |
6807 | /* aFireLocationChange */ true, |
6808 | /* aIsInitialAboutBlank */ true, |
6809 | /* aLocationFlags */ 0); |
6810 | rv = mIsBeingDestroyed ? NS_ERROR_NOT_AVAILABLE : NS_OK; |
6811 | } |
6812 | |
6813 | if (Element* embedderElement = blankDoc->GetEmbedderElement()) { |
6814 | blankDoc->InitFeaturePolicy(AsVariant(embedderElement)); |
6815 | } else { |
6816 | blankDoc->InitFeaturePolicy(AsVariant(Nothing{})); |
6817 | } |
6818 | } |
6819 | } |
6820 | |
6821 | // The transient about:blank viewer doesn't have a session history entry. |
6822 | SetHistoryEntryAndUpdateBC(Nothing(), Some(nullptr)); |
6823 | |
6824 | // Clear out our mTiming like we would in EndPageLoad, if we didn't |
6825 | // have one before entering this function. |
6826 | if (!hadTiming) { |
6827 | mTiming = nullptr; |
6828 | mBlankTiming = true; |
6829 | } |
6830 | |
6831 | return rv; |
6832 | } |
6833 | |
6834 | NS_IMETHODIMPnsresult |
6835 | nsDocShell::CreateAboutBlankDocumentViewer(nsIPrincipal* aPrincipal, |
6836 | nsIPrincipal* aPartitionedPrincipal, |
6837 | nsIContentSecurityPolicy* aCSP) { |
6838 | return CreateAboutBlankDocumentViewer(aPrincipal, aPartitionedPrincipal, aCSP, |
6839 | nullptr, |
6840 | /* aIsInitialDocument */ false); |
6841 | } |
6842 | |
6843 | nsresult nsDocShell::CreateDocumentViewerForActor( |
6844 | WindowGlobalChild* aWindowActor) { |
6845 | MOZ_ASSERT(aWindowActor)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aWindowActor)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aWindowActor))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aWindowActor", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 6845); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aWindowActor" ")"); do { MOZ_CrashSequence(__null, 6845); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
6846 | |
6847 | // FIXME: WindowGlobalChild should provide the PartitionedPrincipal. |
6848 | // FIXME: We may want to support non-initial documents here. |
6849 | nsresult rv = CreateAboutBlankDocumentViewer( |
6850 | aWindowActor->DocumentPrincipal(), aWindowActor->DocumentPrincipal(), |
6851 | /* aCsp */ nullptr, |
6852 | /* aBaseURI */ nullptr, |
6853 | /* aIsInitialDocument */ true, |
6854 | /* aCOEP */ Nothing(), |
6855 | /* aTryToSaveOldPresentation */ true, |
6856 | /* aCheckPermitUnload */ true, aWindowActor); |
6857 | #ifdef DEBUG1 |
6858 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) { |
6859 | RefPtr<Document> doc(GetDocument()); |
6860 | MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType< decltype(doc)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(doc))), 0))) { do { } while (false ); MOZ_ReportAssertionFailure("doc" " (" "Should have a document if CreateAboutBlankDocumentViewer succeeded" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 6862 ); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc" ") (" "Should have a document if CreateAboutBlankDocumentViewer succeeded" ")"); do { MOZ_CrashSequence(__null, 6862); __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
6861 | doc,do { static_assert( mozilla::detail::AssertionConditionType< decltype(doc)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(doc))), 0))) { do { } while (false ); MOZ_ReportAssertionFailure("doc" " (" "Should have a document if CreateAboutBlankDocumentViewer succeeded" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 6862 ); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc" ") (" "Should have a document if CreateAboutBlankDocumentViewer succeeded" ")"); do { MOZ_CrashSequence(__null, 6862); __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
6862 | "Should have a document if CreateAboutBlankDocumentViewer succeeded")do { static_assert( mozilla::detail::AssertionConditionType< decltype(doc)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(doc))), 0))) { do { } while (false ); MOZ_ReportAssertionFailure("doc" " (" "Should have a document if CreateAboutBlankDocumentViewer succeeded" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 6862 ); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc" ") (" "Should have a document if CreateAboutBlankDocumentViewer succeeded" ")"); do { MOZ_CrashSequence(__null, 6862); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
6863 | MOZ_ASSERT(doc->GetOwnerGlobal() == aWindowActor->GetWindowGlobal(),do { static_assert( mozilla::detail::AssertionConditionType< decltype(doc->GetOwnerGlobal() == aWindowActor->GetWindowGlobal ())>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(doc->GetOwnerGlobal() == aWindowActor->GetWindowGlobal ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("doc->GetOwnerGlobal() == aWindowActor->GetWindowGlobal()" " (" "New document should be in the same global as our actor" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 6864 ); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc->GetOwnerGlobal() == aWindowActor->GetWindowGlobal()" ") (" "New document should be in the same global as our actor" ")"); do { MOZ_CrashSequence(__null, 6864); __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
6864 | "New document should be in the same global as our actor")do { static_assert( mozilla::detail::AssertionConditionType< decltype(doc->GetOwnerGlobal() == aWindowActor->GetWindowGlobal ())>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(doc->GetOwnerGlobal() == aWindowActor->GetWindowGlobal ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("doc->GetOwnerGlobal() == aWindowActor->GetWindowGlobal()" " (" "New document should be in the same global as our actor" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 6864 ); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc->GetOwnerGlobal() == aWindowActor->GetWindowGlobal()" ") (" "New document should be in the same global as our actor" ")"); do { MOZ_CrashSequence(__null, 6864); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
6865 | MOZ_ASSERT(doc->IsInitialDocument(),do { static_assert( mozilla::detail::AssertionConditionType< decltype(doc->IsInitialDocument())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(doc->IsInitialDocument()) )), 0))) { do { } while (false); MOZ_ReportAssertionFailure("doc->IsInitialDocument()" " (" "New document should be an initial document" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 6866); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc->IsInitialDocument()" ") (" "New document should be an initial document" ")"); do { MOZ_CrashSequence(__null, 6866); __attribute__((nomerge)) :: abort(); } while (false); } } while (false) |
6866 | "New document should be an initial document")do { static_assert( mozilla::detail::AssertionConditionType< decltype(doc->IsInitialDocument())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(doc->IsInitialDocument()) )), 0))) { do { } while (false); MOZ_ReportAssertionFailure("doc->IsInitialDocument()" " (" "New document should be an initial document" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 6866); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc->IsInitialDocument()" ") (" "New document should be an initial document" ")"); do { MOZ_CrashSequence(__null, 6866); __attribute__((nomerge)) :: abort(); } while (false); } } while (false); |
6867 | } |
6868 | #endif |
6869 | |
6870 | return rv; |
6871 | } |
6872 | |
6873 | bool nsDocShell::CanSavePresentation(uint32_t aLoadType, |
6874 | nsIRequest* aNewRequest, |
6875 | Document* aNewDocument, |
6876 | bool aReportBFCacheComboTelemetry) { |
6877 | if (!mOSHE) { |
6878 | return false; // no entry to save into |
6879 | } |
6880 | |
6881 | MOZ_ASSERT(!mozilla::SessionHistoryInParent(),do { static_assert( mozilla::detail::AssertionConditionType< decltype(!mozilla::SessionHistoryInParent())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!mozilla::SessionHistoryInParent ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("!mozilla::SessionHistoryInParent()" " (" "mOSHE cannot be non-null with SHIP" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 6882 ); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()" ") (" "mOSHE cannot be non-null with SHIP" ")"); do { MOZ_CrashSequence (__null, 6882); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false) |
6882 | "mOSHE cannot be non-null with SHIP")do { static_assert( mozilla::detail::AssertionConditionType< decltype(!mozilla::SessionHistoryInParent())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!mozilla::SessionHistoryInParent ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("!mozilla::SessionHistoryInParent()" " (" "mOSHE cannot be non-null with SHIP" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 6882 ); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()" ") (" "mOSHE cannot be non-null with SHIP" ")"); do { MOZ_CrashSequence (__null, 6882); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); |
6883 | nsCOMPtr<nsIDocumentViewer> viewer = mOSHE->GetDocumentViewer(); |
6884 | if (viewer) { |
6885 | NS_WARNING("mOSHE already has a content viewer!")NS_DebugBreak(NS_DEBUG_WARNING, "mOSHE already has a content viewer!" , nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 6885); |
6886 | return false; |
6887 | } |
6888 | |
6889 | // Only save presentation for "normal" loads and link loads. Anything else |
6890 | // probably wants to refetch the page, so caching the old presentation |
6891 | // would be incorrect. |
6892 | if (aLoadType != LOAD_NORMAL && aLoadType != LOAD_HISTORY && |
6893 | aLoadType != LOAD_LINK && aLoadType != LOAD_STOP_CONTENT && |
6894 | aLoadType != LOAD_STOP_CONTENT_AND_REPLACE && |
6895 | aLoadType != LOAD_ERROR_PAGE) { |
6896 | return false; |
6897 | } |
6898 | |
6899 | // If the session history entry has the saveLayoutState flag set to false, |
6900 | // then we should not cache the presentation. |
6901 | if (!mOSHE->GetSaveLayoutStateFlag()) { |
6902 | return false; |
6903 | } |
6904 | |
6905 | // If the document is not done loading, don't cache it. |
6906 | if (!mScriptGlobal || mScriptGlobal->IsLoading()) { |
6907 | MOZ_LOG(gPageCacheLog, mozilla::LogLevel::Verbose,do { const ::mozilla::LogModule* moz_real_module = gPageCacheLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , mozilla::LogLevel::Verbose)), 0))) { mozilla::detail::log_print (moz_real_module, mozilla::LogLevel::Verbose, "Blocked due to document still loading" ); } } while (0) |
6908 | ("Blocked due to document still loading"))do { const ::mozilla::LogModule* moz_real_module = gPageCacheLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , mozilla::LogLevel::Verbose)), 0))) { mozilla::detail::log_print (moz_real_module, mozilla::LogLevel::Verbose, "Blocked due to document still loading" ); } } while (0); |
6909 | return false; |
6910 | } |
6911 | |
6912 | if (mScriptGlobal->WouldReuseInnerWindow(aNewDocument)) { |
6913 | return false; |
6914 | } |
6915 | |
6916 | // Avoid doing the work of saving the presentation state in the case where |
6917 | // the content viewer cache is disabled. |
6918 | if (nsSHistory::GetMaxTotalViewers() == 0) { |
6919 | return false; |
6920 | } |
6921 | |
6922 | // Don't cache the content viewer if we're in a subframe. |
6923 | if (mBrowsingContext->GetParent()) { |
6924 | return false; // this is a subframe load |
6925 | } |
6926 | |
6927 | // If the document does not want its presentation cached, then don't. |
6928 | RefPtr<Document> doc = mScriptGlobal->GetExtantDoc(); |
6929 | |
6930 | uint32_t bfCacheCombo = 0; |
6931 | bool canSavePresentation = |
6932 | doc->CanSavePresentation(aNewRequest, bfCacheCombo, true); |
6933 | MOZ_ASSERT_IF(canSavePresentation, bfCacheCombo == 0)do { if (canSavePresentation) { do { static_assert( mozilla:: detail::AssertionConditionType<decltype(bfCacheCombo == 0) >::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(bfCacheCombo == 0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("bfCacheCombo == 0", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 6933); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bfCacheCombo == 0" ")"); do { MOZ_CrashSequence(__null, 6933); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); |
6934 | if (canSavePresentation && doc->IsTopLevelContentDocument()) { |
6935 | auto* browsingContextGroup = mBrowsingContext->Group(); |
6936 | nsTArray<RefPtr<BrowsingContext>>& topLevelContext = |
6937 | browsingContextGroup->Toplevels(); |
6938 | |
6939 | for (const auto& browsingContext : topLevelContext) { |
6940 | if (browsingContext != mBrowsingContext) { |
6941 | if (StaticPrefs::docshell_shistory_bfcache_require_no_opener()) { |
6942 | canSavePresentation = false; |
6943 | } |
6944 | bfCacheCombo |= BFCacheStatus::NOT_ONLY_TOPLEVEL_IN_BCG; |
6945 | break; |
6946 | } |
6947 | } |
6948 | } |
6949 | |
6950 | if (aReportBFCacheComboTelemetry) { |
6951 | ReportBFCacheComboTelemetry(bfCacheCombo); |
6952 | } |
6953 | return doc && canSavePresentation; |
6954 | } |
6955 | |
6956 | /* static */ |
6957 | void nsDocShell::ReportBFCacheComboTelemetry(uint32_t aCombo) { |
6958 | // There are 11 possible reasons to make a request fails to use BFCache |
6959 | // (see BFCacheStatus in dom/base/Document.h), and we'd like to record |
6960 | // the common combinations for reasons which make requests fail to use |
6961 | // BFCache. These combinations are generated based on some local browsings, |
6962 | // we need to adjust them when necessary. |
6963 | enum BFCacheStatusCombo : uint32_t { |
6964 | BFCACHE_SUCCESS, |
6965 | NOT_ONLY_TOPLEVEL = mozilla::dom::BFCacheStatus::NOT_ONLY_TOPLEVEL_IN_BCG, |
6966 | // If both unload and beforeunload listeners are presented, it'll be |
6967 | // recorded as unload |
6968 | UNLOAD = mozilla::dom::BFCacheStatus::UNLOAD_LISTENER, |
6969 | UNLOAD_REQUEST = mozilla::dom::BFCacheStatus::UNLOAD_LISTENER | |
6970 | mozilla::dom::BFCacheStatus::REQUEST, |
6971 | REQUEST = mozilla::dom::BFCacheStatus::REQUEST, |
6972 | UNLOAD_REQUEST_PEER = mozilla::dom::BFCacheStatus::UNLOAD_LISTENER | |
6973 | mozilla::dom::BFCacheStatus::REQUEST | |
6974 | mozilla::dom::BFCacheStatus::ACTIVE_PEER_CONNECTION, |
6975 | UNLOAD_REQUEST_PEER_MSE = |
6976 | mozilla::dom::BFCacheStatus::UNLOAD_LISTENER | |
6977 | mozilla::dom::BFCacheStatus::REQUEST | |
6978 | mozilla::dom::BFCacheStatus::ACTIVE_PEER_CONNECTION | |
6979 | mozilla::dom::BFCacheStatus::CONTAINS_MSE_CONTENT, |
6980 | UNLOAD_REQUEST_MSE = mozilla::dom::BFCacheStatus::UNLOAD_LISTENER | |
6981 | mozilla::dom::BFCacheStatus::REQUEST | |
6982 | mozilla::dom::BFCacheStatus::CONTAINS_MSE_CONTENT, |
6983 | SUSPENDED_UNLOAD_REQUEST_PEER = |
6984 | mozilla::dom::BFCacheStatus::SUSPENDED | |
6985 | mozilla::dom::BFCacheStatus::UNLOAD_LISTENER | |
6986 | mozilla::dom::BFCacheStatus::REQUEST | |
6987 | mozilla::dom::BFCacheStatus::ACTIVE_PEER_CONNECTION, |
6988 | REMOTE_SUBFRAMES = mozilla::dom::BFCacheStatus::CONTAINS_REMOTE_SUBFRAMES, |
6989 | BEFOREUNLOAD = mozilla::dom::BFCacheStatus::BEFOREUNLOAD_LISTENER, |
6990 | }; |
6991 | |
6992 | // Beforeunload is recorded as a blocker only if it is the only one to block |
6993 | // bfcache. |
6994 | if (aCombo != mozilla::dom::BFCacheStatus::BEFOREUNLOAD_LISTENER) { |
6995 | aCombo &= ~mozilla::dom::BFCacheStatus::BEFOREUNLOAD_LISTENER; |
6996 | } |
6997 | switch (aCombo) { |
6998 | case BFCACHE_SUCCESS: |
6999 | glean::bfcache::combo.EnumGet(glean::bfcache::ComboLabel::eBfcacheSuccess) |
7000 | .Add(); |
7001 | break; |
7002 | case NOT_ONLY_TOPLEVEL: |
7003 | if (StaticPrefs::docshell_shistory_bfcache_require_no_opener()) { |
7004 | glean::bfcache::combo.EnumGet(glean::bfcache::ComboLabel::eOther).Add(); |
7005 | break; |
7006 | } |
7007 | glean::bfcache::combo.EnumGet(glean::bfcache::ComboLabel::eBfcacheSuccess) |
7008 | .Add(); |
7009 | glean::bfcache::combo |
7010 | .EnumGet(glean::bfcache::ComboLabel::eSuccessNotToplevel) |
7011 | .Add(); |
7012 | break; |
7013 | case UNLOAD: |
7014 | glean::bfcache::combo.EnumGet(glean::bfcache::ComboLabel::eUnload).Add(); |
7015 | break; |
7016 | case BEFOREUNLOAD: |
7017 | glean::bfcache::combo.EnumGet(glean::bfcache::ComboLabel::eBeforeunload) |
7018 | .Add(); |
7019 | break; |
7020 | case UNLOAD_REQUEST: |
7021 | glean::bfcache::combo.EnumGet(glean::bfcache::ComboLabel::eUnloadReq) |
7022 | .Add(); |
7023 | break; |
7024 | case REQUEST: |
7025 | glean::bfcache::combo.EnumGet(glean::bfcache::ComboLabel::eReq).Add(); |
7026 | break; |
7027 | case UNLOAD_REQUEST_PEER: |
7028 | glean::bfcache::combo.EnumGet(glean::bfcache::ComboLabel::eUnloadReqPeer) |
7029 | .Add(); |
7030 | break; |
7031 | case UNLOAD_REQUEST_PEER_MSE: |
7032 | glean::bfcache::combo |
7033 | .EnumGet(glean::bfcache::ComboLabel::eUnloadReqPeerMse) |
7034 | .Add(); |
7035 | break; |
7036 | case UNLOAD_REQUEST_MSE: |
7037 | glean::bfcache::combo.EnumGet(glean::bfcache::ComboLabel::eUnloadReqMse) |
7038 | .Add(); |
7039 | break; |
7040 | case SUSPENDED_UNLOAD_REQUEST_PEER: |
7041 | glean::bfcache::combo |
7042 | .EnumGet(glean::bfcache::ComboLabel::eSpdUnloadReqPeer) |
7043 | .Add(); |
7044 | break; |
7045 | case REMOTE_SUBFRAMES: |
7046 | glean::bfcache::combo |
7047 | .EnumGet(glean::bfcache::ComboLabel::eRemoteSubframes) |
7048 | .Add(); |
7049 | break; |
7050 | default: |
7051 | glean::bfcache::combo.EnumGet(glean::bfcache::ComboLabel::eOther).Add(); |
7052 | break; |
7053 | } |
7054 | }; |
7055 | |
7056 | void nsDocShell::ReattachEditorToWindow(nsISHEntry* aSHEntry) { |
7057 | MOZ_ASSERT(!mozilla::SessionHistoryInParent())do { static_assert( mozilla::detail::AssertionConditionType< decltype(!mozilla::SessionHistoryInParent())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!mozilla::SessionHistoryInParent ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("!mozilla::SessionHistoryInParent()", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 7057); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()" ")"); do { MOZ_CrashSequence(__null, 7057); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
7058 | MOZ_ASSERT(!mIsBeingDestroyed)do { static_assert( mozilla::detail::AssertionConditionType< decltype(!mIsBeingDestroyed)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!mIsBeingDestroyed))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!mIsBeingDestroyed" , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 7058); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "!mIsBeingDestroyed" ")"); do { MOZ_CrashSequence (__null, 7058); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); |
7059 | |
7060 | NS_ASSERTION(!mEditorData,do { if (!(!mEditorData)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Why reattach an editor when we already have one?", "!mEditorData" , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 7061); MOZ_PretendNoReturn (); } } while (0) |
7061 | "Why reattach an editor when we already have one?")do { if (!(!mEditorData)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Why reattach an editor when we already have one?", "!mEditorData" , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 7061); MOZ_PretendNoReturn (); } } while (0); |
7062 | NS_ASSERTION(aSHEntry && aSHEntry->HasDetachedEditor(),do { if (!(aSHEntry && aSHEntry->HasDetachedEditor ())) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Reattaching when there's not a detached editor." , "aSHEntry && aSHEntry->HasDetachedEditor()", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 7063); MOZ_PretendNoReturn(); } } while (0) |
7063 | "Reattaching when there's not a detached editor.")do { if (!(aSHEntry && aSHEntry->HasDetachedEditor ())) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Reattaching when there's not a detached editor." , "aSHEntry && aSHEntry->HasDetachedEditor()", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 7063); MOZ_PretendNoReturn(); } } while (0); |
7064 | |
7065 | if (mEditorData || !aSHEntry) { |
7066 | return; |
7067 | } |
7068 | |
7069 | mEditorData = WrapUnique(aSHEntry->ForgetEditorData()); |
7070 | if (mEditorData) { |
7071 | #ifdef DEBUG1 |
7072 | nsresult rv = |
7073 | #endif |
7074 | mEditorData->ReattachToWindow(this); |
7075 | NS_ASSERTION(NS_SUCCEEDED(rv), "Failed to reattach editing session")do { if (!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1 ))))) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Failed to reattach editing session" , "NS_SUCCEEDED(rv)", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 7075); MOZ_PretendNoReturn(); } } while (0); |
7076 | } |
7077 | } |
7078 | |
7079 | void nsDocShell::DetachEditorFromWindow() { |
7080 | if (!mEditorData || mEditorData->WaitingForLoad()) { |
7081 | // If there's nothing to detach, or if the editor data is actually set |
7082 | // up for the _new_ page that's coming in, don't detach. |
7083 | return; |
7084 | } |
7085 | |
7086 | NS_ASSERTION(!mOSHE || !mOSHE->HasDetachedEditor(),do { if (!(!mOSHE || !mOSHE->HasDetachedEditor())) { NS_DebugBreak (NS_DEBUG_ASSERTION, "Detaching editor when it's already detached." , "!mOSHE || !mOSHE->HasDetachedEditor()", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 7087); MOZ_PretendNoReturn(); } } while (0) |
7087 | "Detaching editor when it's already detached.")do { if (!(!mOSHE || !mOSHE->HasDetachedEditor())) { NS_DebugBreak (NS_DEBUG_ASSERTION, "Detaching editor when it's already detached." , "!mOSHE || !mOSHE->HasDetachedEditor()", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 7087); MOZ_PretendNoReturn(); } } while (0); |
7088 | |
7089 | nsresult res = mEditorData->DetachFromWindow(); |
7090 | NS_ASSERTION(NS_SUCCEEDED(res), "Failed to detach editor")do { if (!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(res)), 1))))) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Failed to detach editor" , "NS_SUCCEEDED(res)", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 7090); MOZ_PretendNoReturn(); } } while (0); |
7091 | |
7092 | if (NS_SUCCEEDED(res)((bool)(__builtin_expect(!!(!NS_FAILED_impl(res)), 1)))) { |
7093 | // Make mOSHE hold the owning ref to the editor data. |
7094 | if (mOSHE) { |
7095 | MOZ_ASSERT(!mIsBeingDestroyed || !mOSHE->HasDetachedEditor(),do { static_assert( mozilla::detail::AssertionConditionType< decltype(!mIsBeingDestroyed || !mOSHE->HasDetachedEditor() )>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(!mIsBeingDestroyed || !mOSHE->HasDetachedEditor() ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "!mIsBeingDestroyed || !mOSHE->HasDetachedEditor()" " (" "We should not set the editor data again once after we " "detached the editor data during destroying this docshell" ")" , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 7097); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "!mIsBeingDestroyed || !mOSHE->HasDetachedEditor()" ") (" "We should not set the editor data again once after we " "detached the editor data during destroying this docshell" ")" ); do { MOZ_CrashSequence(__null, 7097); __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
7096 | "We should not set the editor data again once after we "do { static_assert( mozilla::detail::AssertionConditionType< decltype(!mIsBeingDestroyed || !mOSHE->HasDetachedEditor() )>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(!mIsBeingDestroyed || !mOSHE->HasDetachedEditor() ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "!mIsBeingDestroyed || !mOSHE->HasDetachedEditor()" " (" "We should not set the editor data again once after we " "detached the editor data during destroying this docshell" ")" , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 7097); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "!mIsBeingDestroyed || !mOSHE->HasDetachedEditor()" ") (" "We should not set the editor data again once after we " "detached the editor data during destroying this docshell" ")" ); do { MOZ_CrashSequence(__null, 7097); __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
7097 | "detached the editor data during destroying this docshell")do { static_assert( mozilla::detail::AssertionConditionType< decltype(!mIsBeingDestroyed || !mOSHE->HasDetachedEditor() )>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(!mIsBeingDestroyed || !mOSHE->HasDetachedEditor() ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "!mIsBeingDestroyed || !mOSHE->HasDetachedEditor()" " (" "We should not set the editor data again once after we " "detached the editor data during destroying this docshell" ")" , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 7097); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "!mIsBeingDestroyed || !mOSHE->HasDetachedEditor()" ") (" "We should not set the editor data again once after we " "detached the editor data during destroying this docshell" ")" ); do { MOZ_CrashSequence(__null, 7097); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
7098 | mOSHE->SetEditorData(mEditorData.release()); |
7099 | } else { |
7100 | mEditorData = nullptr; |
7101 | } |
7102 | } |
7103 | |
7104 | #ifdef DEBUG1 |
7105 | { |
7106 | bool isEditable; |
7107 | GetEditable(&isEditable); |
7108 | NS_ASSERTION(!isEditable,do { if (!(!isEditable)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Window is still editable after detaching editor." , "!isEditable", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 7109); MOZ_PretendNoReturn(); } } while (0) |
7109 | "Window is still editable after detaching editor.")do { if (!(!isEditable)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Window is still editable after detaching editor." , "!isEditable", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 7109); MOZ_PretendNoReturn(); } } while (0); |
7110 | } |
7111 | #endif // DEBUG |
7112 | } |
7113 | |
7114 | nsresult nsDocShell::CaptureState() { |
7115 | MOZ_ASSERT(!mozilla::SessionHistoryInParent())do { static_assert( mozilla::detail::AssertionConditionType< decltype(!mozilla::SessionHistoryInParent())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!mozilla::SessionHistoryInParent ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("!mozilla::SessionHistoryInParent()", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 7115); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()" ")"); do { MOZ_CrashSequence(__null, 7115); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
7116 | |
7117 | if (!mOSHE || mOSHE == mLSHE) { |
7118 | // No entry to save into, or we're replacing the existing entry. |
7119 | return NS_ERROR_FAILURE; |
7120 | } |
7121 | |
7122 | if (!mScriptGlobal) { |
7123 | return NS_ERROR_FAILURE; |
7124 | } |
7125 | |
7126 | nsCOMPtr<nsISupports> windowState = mScriptGlobal->SaveWindowState(); |
7127 | NS_ENSURE_TRUE(windowState, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(windowState)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "windowState" ") failed" , nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 7127); return NS_ERROR_FAILURE; } } while (false); |
7128 | |
7129 | if (MOZ_UNLIKELY(MOZ_LOG_TEST(gPageCacheLog, LogLevel::Debug))(__builtin_expect(!!((__builtin_expect(!!(mozilla::detail::log_test (gPageCacheLog, LogLevel::Debug)), 0))), 0))) { |
7130 | nsAutoCString spec; |
7131 | nsCOMPtr<nsIURI> uri = mOSHE->GetURI(); |
7132 | if (uri) { |
7133 | uri->GetSpec(spec); |
7134 | } |
7135 | MOZ_LOG(gPageCacheLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gPageCacheLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "Saving presentation into session history, URI: %s" , spec.get()); } } while (0) |
7136 | ("Saving presentation into session history, URI: %s", spec.get()))do { const ::mozilla::LogModule* moz_real_module = gPageCacheLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "Saving presentation into session history, URI: %s" , spec.get()); } } while (0); |
7137 | } |
7138 | |
7139 | mOSHE->SetWindowState(windowState); |
7140 | |
7141 | // Suspend refresh URIs and save off the timer queue |
7142 | mOSHE->SetRefreshURIList(mSavedRefreshURIList); |
7143 | |
7144 | // Capture the current content viewer bounds. |
7145 | if (mDocumentViewer) { |
7146 | LayoutDeviceIntRect bounds; |
7147 | mDocumentViewer->GetBounds(bounds); |
7148 | mOSHE->SetViewerBounds(bounds.ToUnknownRect()); |
7149 | } |
7150 | |
7151 | // Capture the docshell hierarchy. |
7152 | mOSHE->ClearChildShells(); |
7153 | |
7154 | uint32_t childCount = mChildList.Length(); |
7155 | for (uint32_t i = 0; i < childCount; ++i) { |
7156 | nsCOMPtr<nsIDocShellTreeItem> childShell = do_QueryInterface(ChildAt(i)); |
7157 | NS_ASSERTION(childShell, "null child shell")do { if (!(childShell)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "null child shell" , "childShell", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 7157); MOZ_PretendNoReturn(); } } while (0); |
7158 | |
7159 | mOSHE->AddChildShell(childShell); |
7160 | } |
7161 | |
7162 | return NS_OK; |
7163 | } |
7164 | |
7165 | NS_IMETHODIMPnsresult |
7166 | nsDocShell::RestorePresentationEvent::Run() { |
7167 | MOZ_ASSERT(!mozilla::SessionHistoryInParent())do { static_assert( mozilla::detail::AssertionConditionType< decltype(!mozilla::SessionHistoryInParent())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!mozilla::SessionHistoryInParent ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("!mozilla::SessionHistoryInParent()", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 7167); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()" ")"); do { MOZ_CrashSequence(__null, 7167); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
7168 | |
7169 | if (mDocShell && NS_FAILED(mDocShell->RestoreFromHistory())((bool)(__builtin_expect(!!(NS_FAILED_impl(mDocShell->RestoreFromHistory ())), 0)))) { |
7170 | NS_WARNING("RestoreFromHistory failed")NS_DebugBreak(NS_DEBUG_WARNING, "RestoreFromHistory failed", nullptr , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 7170); |
7171 | } |
7172 | return NS_OK; |
7173 | } |
7174 | |
7175 | NS_IMETHODIMPnsresult |
7176 | nsDocShell::BeginRestore(nsIDocumentViewer* aDocumentViewer, bool aTop) { |
7177 | MOZ_ASSERT(!mozilla::SessionHistoryInParent())do { static_assert( mozilla::detail::AssertionConditionType< decltype(!mozilla::SessionHistoryInParent())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!mozilla::SessionHistoryInParent ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("!mozilla::SessionHistoryInParent()", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 7177); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()" ")"); do { MOZ_CrashSequence(__null, 7177); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
7178 | |
7179 | nsresult rv; |
7180 | if (!aDocumentViewer) { |
7181 | rv = EnsureDocumentViewer(); |
7182 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 7182); return rv; } } while (false); |
7183 | |
7184 | aDocumentViewer = mDocumentViewer; |
7185 | } |
7186 | |
7187 | // Dispatch events for restoring the presentation. We try to simulate |
7188 | // the progress notifications loading the document would cause, so we add |
7189 | // the document's channel to the loadgroup to initiate stateChange |
7190 | // notifications. |
7191 | |
7192 | RefPtr<Document> doc = aDocumentViewer->GetDocument(); |
7193 | if (doc) { |
7194 | nsIChannel* channel = doc->GetChannel(); |
7195 | if (channel) { |
7196 | mEODForCurrentDocument = false; |
7197 | mIsRestoringDocument = true; |
7198 | mLoadGroup->AddRequest(channel, nullptr); |
7199 | mIsRestoringDocument = false; |
7200 | } |
7201 | } |
7202 | |
7203 | if (!aTop) { |
7204 | // This point corresponds to us having gotten OnStartRequest or |
7205 | // STATE_START, so do the same thing that CreateDocumentViewer does at |
7206 | // this point to ensure that unload/pagehide events for this document |
7207 | // will fire when it's unloaded again. |
7208 | mFiredUnloadEvent = false; |
7209 | |
7210 | // For non-top frames, there is no notion of making sure that the |
7211 | // previous document is in the domwindow when STATE_START notifications |
7212 | // happen. We can just call BeginRestore for all of the child shells |
7213 | // now. |
7214 | rv = BeginRestoreChildren(); |
7215 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 7215); return rv; } } while (false); |
7216 | } |
7217 | |
7218 | return NS_OK; |
7219 | } |
7220 | |
7221 | nsresult nsDocShell::BeginRestoreChildren() { |
7222 | MOZ_ASSERT(!mozilla::SessionHistoryInParent())do { static_assert( mozilla::detail::AssertionConditionType< decltype(!mozilla::SessionHistoryInParent())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!mozilla::SessionHistoryInParent ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("!mozilla::SessionHistoryInParent()", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 7222); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()" ")"); do { MOZ_CrashSequence(__null, 7222); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
7223 | |
7224 | for (auto* childDocLoader : mChildList.ForwardRange()) { |
7225 | nsCOMPtr<nsIDocShell> child = do_QueryObject(childDocLoader); |
7226 | if (child) { |
7227 | nsresult rv = child->BeginRestore(nullptr, false); |
7228 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 7228); return rv; } } while (false); |
7229 | } |
7230 | } |
7231 | return NS_OK; |
7232 | } |
7233 | |
7234 | NS_IMETHODIMPnsresult |
7235 | nsDocShell::FinishRestore() { |
7236 | MOZ_ASSERT(!mozilla::SessionHistoryInParent())do { static_assert( mozilla::detail::AssertionConditionType< decltype(!mozilla::SessionHistoryInParent())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!mozilla::SessionHistoryInParent ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("!mozilla::SessionHistoryInParent()", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 7236); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()" ")"); do { MOZ_CrashSequence(__null, 7236); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
7237 | |
7238 | // First we call finishRestore() on our children. In the simulated load, |
7239 | // all of the child frames finish loading before the main document. |
7240 | |
7241 | for (auto* childDocLoader : mChildList.ForwardRange()) { |
7242 | nsCOMPtr<nsIDocShell> child = do_QueryObject(childDocLoader); |
7243 | if (child) { |
7244 | child->FinishRestore(); |
7245 | } |
7246 | } |
7247 | |
7248 | if (mOSHE && mOSHE->HasDetachedEditor()) { |
7249 | ReattachEditorToWindow(mOSHE); |
7250 | } |
7251 | |
7252 | RefPtr<Document> doc = GetDocument(); |
7253 | if (doc) { |
7254 | // Finally, we remove the request from the loadgroup. This will |
7255 | // cause onStateChange(STATE_STOP) to fire, which will fire the |
7256 | // pageshow event to the chrome. |
7257 | |
7258 | nsIChannel* channel = doc->GetChannel(); |
7259 | if (channel) { |
7260 | mIsRestoringDocument = true; |
7261 | mLoadGroup->RemoveRequest(channel, nullptr, NS_OK); |
7262 | mIsRestoringDocument = false; |
7263 | } |
7264 | } |
7265 | |
7266 | return NS_OK; |
7267 | } |
7268 | |
7269 | NS_IMETHODIMPnsresult |
7270 | nsDocShell::GetRestoringDocument(bool* aRestoring) { |
7271 | *aRestoring = mIsRestoringDocument; |
7272 | return NS_OK; |
7273 | } |
7274 | |
7275 | nsresult nsDocShell::RestorePresentation(nsISHEntry* aSHEntry, |
7276 | bool* aRestoring) { |
7277 | MOZ_ASSERT(!mozilla::SessionHistoryInParent())do { static_assert( mozilla::detail::AssertionConditionType< decltype(!mozilla::SessionHistoryInParent())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!mozilla::SessionHistoryInParent ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("!mozilla::SessionHistoryInParent()", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 7277); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()" ")"); do { MOZ_CrashSequence(__null, 7277); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
7278 | MOZ_ASSERT(!mIsBeingDestroyed)do { static_assert( mozilla::detail::AssertionConditionType< decltype(!mIsBeingDestroyed)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!mIsBeingDestroyed))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!mIsBeingDestroyed" , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 7278); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "!mIsBeingDestroyed" ")"); do { MOZ_CrashSequence (__null, 7278); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); |
7279 | |
7280 | NS_ASSERTION(mLoadType & LOAD_CMD_HISTORY,do { if (!(mLoadType & LOAD_CMD_HISTORY)) { NS_DebugBreak (NS_DEBUG_ASSERTION, "RestorePresentation should only be called for history loads" , "mLoadType & LOAD_CMD_HISTORY", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 7281); MOZ_PretendNoReturn(); } } while (0) |
7281 | "RestorePresentation should only be called for history loads")do { if (!(mLoadType & LOAD_CMD_HISTORY)) { NS_DebugBreak (NS_DEBUG_ASSERTION, "RestorePresentation should only be called for history loads" , "mLoadType & LOAD_CMD_HISTORY", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 7281); MOZ_PretendNoReturn(); } } while (0); |
7282 | |
7283 | nsCOMPtr<nsIDocumentViewer> viewer = aSHEntry->GetDocumentViewer(); |
7284 | |
7285 | nsAutoCString spec; |
7286 | if (MOZ_UNLIKELY(MOZ_LOG_TEST(gPageCacheLog, LogLevel::Debug))(__builtin_expect(!!((__builtin_expect(!!(mozilla::detail::log_test (gPageCacheLog, LogLevel::Debug)), 0))), 0))) { |
7287 | nsCOMPtr<nsIURI> uri = aSHEntry->GetURI(); |
7288 | if (uri) { |
7289 | uri->GetSpec(spec); |
7290 | } |
7291 | } |
7292 | |
7293 | *aRestoring = false; |
7294 | |
7295 | if (!viewer) { |
7296 | MOZ_LOG(gPageCacheLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gPageCacheLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "no saved presentation for uri: %s", spec. get()); } } while (0) |
7297 | ("no saved presentation for uri: %s", spec.get()))do { const ::mozilla::LogModule* moz_real_module = gPageCacheLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "no saved presentation for uri: %s", spec. get()); } } while (0); |
7298 | return NS_OK; |
7299 | } |
7300 | |
7301 | // We need to make sure the content viewer's container is this docshell. |
7302 | // In subframe navigation, it's possible for the docshell that the |
7303 | // content viewer was originally loaded into to be replaced with a |
7304 | // different one. We don't currently support restoring the presentation |
7305 | // in that case. |
7306 | |
7307 | nsCOMPtr<nsIDocShell> container; |
7308 | viewer->GetContainer(getter_AddRefs(container)); |
7309 | if (!::SameCOMIdentity(container, GetAsSupports(this))) { |
7310 | MOZ_LOG(gPageCacheLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gPageCacheLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "No valid container, clearing presentation" ); } } while (0) |
7311 | ("No valid container, clearing presentation"))do { const ::mozilla::LogModule* moz_real_module = gPageCacheLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "No valid container, clearing presentation" ); } } while (0); |
7312 | aSHEntry->SetDocumentViewer(nullptr); |
7313 | return NS_ERROR_FAILURE; |
7314 | } |
7315 | |
7316 | NS_ASSERTION(mDocumentViewer != viewer, "Restoring existing presentation")do { if (!(mDocumentViewer != viewer)) { NS_DebugBreak(NS_DEBUG_ASSERTION , "Restoring existing presentation", "mDocumentViewer != viewer" , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 7316); MOZ_PretendNoReturn (); } } while (0); |
7317 | |
7318 | MOZ_LOG(gPageCacheLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gPageCacheLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "restoring presentation from session history: %s" , spec.get()); } } while (0) |
7319 | ("restoring presentation from session history: %s", spec.get()))do { const ::mozilla::LogModule* moz_real_module = gPageCacheLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "restoring presentation from session history: %s" , spec.get()); } } while (0); |
7320 | |
7321 | SetHistoryEntryAndUpdateBC(Some(aSHEntry), Nothing()); |
7322 | |
7323 | // Post an event that will remove the request after we've returned |
7324 | // to the event loop. This mimics the way it is called by nsIChannel |
7325 | // implementations. |
7326 | |
7327 | // Revoke any pending restore (just in case). |
7328 | NS_ASSERTION(!mRestorePresentationEvent.IsPending(),do { if (!(!mRestorePresentationEvent.IsPending())) { NS_DebugBreak (NS_DEBUG_ASSERTION, "should only have one RestorePresentationEvent" , "!mRestorePresentationEvent.IsPending()", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 7329); MOZ_PretendNoReturn(); } } while (0) |
7329 | "should only have one RestorePresentationEvent")do { if (!(!mRestorePresentationEvent.IsPending())) { NS_DebugBreak (NS_DEBUG_ASSERTION, "should only have one RestorePresentationEvent" , "!mRestorePresentationEvent.IsPending()", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 7329); MOZ_PretendNoReturn(); } } while (0); |
7330 | mRestorePresentationEvent.Revoke(); |
7331 | |
7332 | RefPtr<RestorePresentationEvent> evt = new RestorePresentationEvent(this); |
7333 | nsresult rv = Dispatch(do_AddRef(evt)); |
7334 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) { |
7335 | mRestorePresentationEvent = evt.get(); |
7336 | // The rest of the restore processing will happen on our event |
7337 | // callback. |
7338 | *aRestoring = true; |
7339 | } |
7340 | |
7341 | return rv; |
7342 | } |
7343 | |
7344 | namespace { |
7345 | class MOZ_STACK_CLASS PresentationEventForgetter { |
7346 | public: |
7347 | explicit PresentationEventForgetter( |
7348 | nsRevocableEventPtr<nsDocShell::RestorePresentationEvent>& |
7349 | aRestorePresentationEvent) |
7350 | : mRestorePresentationEvent(aRestorePresentationEvent), |
7351 | mEvent(aRestorePresentationEvent.get()) {} |
7352 | |
7353 | ~PresentationEventForgetter() { Forget(); } |
7354 | |
7355 | void Forget() { |
7356 | if (mRestorePresentationEvent.get() == mEvent) { |
7357 | mRestorePresentationEvent.Forget(); |
7358 | mEvent = nullptr; |
7359 | } |
7360 | } |
7361 | |
7362 | private: |
7363 | nsRevocableEventPtr<nsDocShell::RestorePresentationEvent>& |
7364 | mRestorePresentationEvent; |
7365 | RefPtr<nsDocShell::RestorePresentationEvent> mEvent; |
7366 | }; |
7367 | |
7368 | } // namespace |
7369 | |
7370 | bool nsDocShell::SandboxFlagsImplyCookies(const uint32_t& aSandboxFlags) { |
7371 | return (aSandboxFlags & (SANDBOXED_ORIGIN | SANDBOXED_SCRIPTS)) == 0; |
7372 | } |
7373 | |
7374 | nsresult nsDocShell::RestoreFromHistory() { |
7375 | MOZ_ASSERT(!mozilla::SessionHistoryInParent())do { static_assert( mozilla::detail::AssertionConditionType< decltype(!mozilla::SessionHistoryInParent())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!mozilla::SessionHistoryInParent ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("!mozilla::SessionHistoryInParent()", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 7375); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()" ")"); do { MOZ_CrashSequence(__null, 7375); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
7376 | MOZ_ASSERT(mRestorePresentationEvent.IsPending())do { static_assert( mozilla::detail::AssertionConditionType< decltype(mRestorePresentationEvent.IsPending())>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(! !(mRestorePresentationEvent.IsPending()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mRestorePresentationEvent.IsPending()" , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 7376); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "mRestorePresentationEvent.IsPending()" ")" ); do { MOZ_CrashSequence(__null, 7376); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
7377 | PresentationEventForgetter forgetter(mRestorePresentationEvent); |
7378 | |
7379 | // This section of code follows the same ordering as CreateDocumentViewer. |
7380 | if (!mLSHE) { |
7381 | return NS_ERROR_FAILURE; |
7382 | } |
7383 | |
7384 | nsCOMPtr<nsIDocumentViewer> viewer = mLSHE->GetDocumentViewer(); |
7385 | if (!viewer) { |
7386 | return NS_ERROR_FAILURE; |
7387 | } |
7388 | |
7389 | if (mSavingOldViewer) { |
7390 | // We determined that it was safe to cache the document presentation |
7391 | // at the time we initiated the new load. We need to check whether |
7392 | // it's still safe to do so, since there may have been DOM mutations |
7393 | // or new requests initiated. |
7394 | RefPtr<Document> doc = viewer->GetDocument(); |
7395 | nsIRequest* request = nullptr; |
7396 | if (doc) { |
7397 | request = doc->GetChannel(); |
7398 | } |
7399 | mSavingOldViewer = CanSavePresentation( |
7400 | mLoadType, request, doc, /* aReportBFCacheComboTelemetry */ false); |
7401 | } |
7402 | |
7403 | // Protect against mLSHE going away via a load triggered from |
7404 | // pagehide or unload. |
7405 | nsCOMPtr<nsISHEntry> origLSHE = mLSHE; |
7406 | |
7407 | // Make sure to blow away our mLoadingURI just in case. No loads |
7408 | // from inside this pagehide. |
7409 | mLoadingURI = nullptr; |
7410 | |
7411 | // Notify the old content viewer that it's being hidden. |
7412 | FirePageHideNotification(!mSavingOldViewer); |
7413 | // pagehide notification might destroy this docshell. |
7414 | if (mIsBeingDestroyed) { |
7415 | return NS_ERROR_DOCSHELL_DYING; |
7416 | } |
7417 | |
7418 | // If mLSHE was changed as a result of the pagehide event, then |
7419 | // something else was loaded. Don't finish restoring. |
7420 | if (mLSHE != origLSHE) { |
7421 | return NS_OK; |
7422 | } |
7423 | |
7424 | // Add the request to our load group. We do this before swapping out |
7425 | // the content viewers so that consumers of STATE_START can access |
7426 | // the old document. We only deal with the toplevel load at this time -- |
7427 | // to be consistent with normal document loading, subframes cannot start |
7428 | // loading until after data arrives, which is after STATE_START completes. |
7429 | |
7430 | RefPtr<RestorePresentationEvent> currentPresentationRestoration = |
7431 | mRestorePresentationEvent.get(); |
7432 | Stop(); |
7433 | // Make sure we're still restoring the same presentation. |
7434 | // If we aren't, docshell is in process doing another load already. |
7435 | NS_ENSURE_STATE(currentPresentationRestoration ==do { if ((__builtin_expect(!!(!(currentPresentationRestoration == mRestorePresentationEvent.get())), 0))) { NS_DebugBreak(NS_DEBUG_WARNING , "NS_ENSURE_TRUE(" "currentPresentationRestoration == mRestorePresentationEvent.get()" ") failed", nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 7436); return NS_ERROR_UNEXPECTED; } } while (false) |
7436 | mRestorePresentationEvent.get())do { if ((__builtin_expect(!!(!(currentPresentationRestoration == mRestorePresentationEvent.get())), 0))) { NS_DebugBreak(NS_DEBUG_WARNING , "NS_ENSURE_TRUE(" "currentPresentationRestoration == mRestorePresentationEvent.get()" ") failed", nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 7436); return NS_ERROR_UNEXPECTED; } } while (false); |
7437 | BeginRestore(viewer, true); |
7438 | NS_ENSURE_STATE(currentPresentationRestoration ==do { if ((__builtin_expect(!!(!(currentPresentationRestoration == mRestorePresentationEvent.get())), 0))) { NS_DebugBreak(NS_DEBUG_WARNING , "NS_ENSURE_TRUE(" "currentPresentationRestoration == mRestorePresentationEvent.get()" ") failed", nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 7439); return NS_ERROR_UNEXPECTED; } } while (false) |
7439 | mRestorePresentationEvent.get())do { if ((__builtin_expect(!!(!(currentPresentationRestoration == mRestorePresentationEvent.get())), 0))) { NS_DebugBreak(NS_DEBUG_WARNING , "NS_ENSURE_TRUE(" "currentPresentationRestoration == mRestorePresentationEvent.get()" ") failed", nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 7439); return NS_ERROR_UNEXPECTED; } } while (false); |
7440 | forgetter.Forget(); |
7441 | |
7442 | // Set mFiredUnloadEvent = false so that the unload handler for the |
7443 | // *new* document will fire. |
7444 | mFiredUnloadEvent = false; |
7445 | |
7446 | mURIResultedInDocument = true; |
7447 | RefPtr<ChildSHistory> rootSH = GetRootSessionHistory(); |
7448 | if (rootSH) { |
7449 | mPreviousEntryIndex = rootSH->Index(); |
7450 | rootSH->LegacySHistory()->UpdateIndex(); |
7451 | mLoadedEntryIndex = rootSH->Index(); |
7452 | MOZ_LOG(gPageCacheLog, LogLevel::Verbose,do { const ::mozilla::LogModule* moz_real_module = gPageCacheLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Verbose)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Verbose, "Previous index: %d, Loaded index: %d", mPreviousEntryIndex , mLoadedEntryIndex); } } while (0) |
7453 | ("Previous index: %d, Loaded index: %d", mPreviousEntryIndex,do { const ::mozilla::LogModule* moz_real_module = gPageCacheLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Verbose)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Verbose, "Previous index: %d, Loaded index: %d", mPreviousEntryIndex , mLoadedEntryIndex); } } while (0) |
7454 | mLoadedEntryIndex))do { const ::mozilla::LogModule* moz_real_module = gPageCacheLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Verbose)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Verbose, "Previous index: %d, Loaded index: %d", mPreviousEntryIndex , mLoadedEntryIndex); } } while (0); |
7455 | } |
7456 | |
7457 | // Rather than call Embed(), we will retrieve the viewer from the session |
7458 | // history entry and swap it in. |
7459 | // XXX can we refactor this so that we can just call Embed()? |
7460 | PersistLayoutHistoryState(); |
7461 | nsresult rv; |
7462 | if (mDocumentViewer) { |
7463 | if (mSavingOldViewer && NS_FAILED(CaptureState())((bool)(__builtin_expect(!!(NS_FAILED_impl(CaptureState())), 0 )))) { |
7464 | if (mOSHE) { |
7465 | mOSHE->SyncPresentationState(); |
7466 | } |
7467 | mSavingOldViewer = false; |
7468 | } |
7469 | } |
7470 | |
7471 | mSavedRefreshURIList = nullptr; |
7472 | |
7473 | // In cases where we use a transient about:blank viewer between loads, |
7474 | // we never show the transient viewer, so _its_ previous viewer is never |
7475 | // unhooked from the view hierarchy. Destroy any such previous viewer now, |
7476 | // before we grab the root view sibling, so that we don't grab a view |
7477 | // that's about to go away. |
7478 | |
7479 | if (mDocumentViewer) { |
7480 | // Make sure to hold a strong ref to previousViewer here while we |
7481 | // drop the reference to it from mDocumentViewer. |
7482 | nsCOMPtr<nsIDocumentViewer> previousViewer = |
7483 | mDocumentViewer->GetPreviousViewer(); |
7484 | if (previousViewer) { |
7485 | mDocumentViewer->SetPreviousViewer(nullptr); |
7486 | previousViewer->Destroy(); |
7487 | } |
7488 | } |
7489 | |
7490 | // Save off the root view's parent and sibling so that we can insert the |
7491 | // new content viewer's root view at the same position. Also save the |
7492 | // bounds of the root view's widget. |
7493 | |
7494 | nsView* rootViewSibling = nullptr; |
7495 | nsView* rootViewParent = nullptr; |
7496 | LayoutDeviceIntRect newBounds(0, 0, 0, 0); |
7497 | |
7498 | PresShell* oldPresShell = GetPresShell(); |
7499 | if (oldPresShell) { |
7500 | nsViewManager* vm = oldPresShell->GetViewManager(); |
7501 | if (vm) { |
7502 | nsView* oldRootView = vm->GetRootView(); |
7503 | |
7504 | if (oldRootView) { |
7505 | rootViewSibling = oldRootView->GetNextSibling(); |
7506 | rootViewParent = oldRootView->GetParent(); |
7507 | |
7508 | mDocumentViewer->GetBounds(newBounds); |
7509 | } |
7510 | } |
7511 | } |
7512 | |
7513 | nsCOMPtr<nsIContent> container; |
7514 | RefPtr<Document> sibling; |
7515 | if (rootViewParent && rootViewParent->GetParent()) { |
7516 | nsIFrame* frame = rootViewParent->GetParent()->GetFrame(); |
7517 | container = frame ? frame->GetContent() : nullptr; |
7518 | } |
7519 | if (rootViewSibling) { |
7520 | nsIFrame* frame = rootViewSibling->GetFrame(); |
7521 | sibling = frame ? frame->PresShell()->GetDocument() : nullptr; |
7522 | } |
7523 | |
7524 | // Transfer ownership to mDocumentViewer. By ensuring that either the |
7525 | // docshell or the session history, but not both, have references to the |
7526 | // content viewer, we prevent the viewer from being torn down after |
7527 | // Destroy() is called. |
7528 | |
7529 | if (mDocumentViewer) { |
7530 | mDocumentViewer->Close(mSavingOldViewer ? mOSHE.get() : nullptr); |
7531 | viewer->SetPreviousViewer(mDocumentViewer); |
7532 | } |
7533 | if (mOSHE && (!mDocumentViewer || !mSavingOldViewer)) { |
7534 | // We don't plan to save a viewer in mOSHE; tell it to drop |
7535 | // any other state it's holding. |
7536 | mOSHE->SyncPresentationState(); |
7537 | } |
7538 | |
7539 | // Order the mDocumentViewer setup just like Embed does. |
7540 | mDocumentViewer = nullptr; |
7541 | |
7542 | // Now that we're about to switch documents, forget all of our children. |
7543 | // Note that we cached them as needed up in CaptureState above. |
7544 | DestroyChildren(); |
7545 | |
7546 | mDocumentViewer.swap(viewer); |
7547 | |
7548 | // Grab all of the related presentation from the SHEntry now. |
7549 | // Clearing the viewer from the SHEntry will clear all of this state. |
7550 | nsCOMPtr<nsISupports> windowState = mLSHE->GetWindowState(); |
7551 | mLSHE->SetWindowState(nullptr); |
7552 | |
7553 | bool sticky = mLSHE->GetSticky(); |
7554 | |
7555 | RefPtr<Document> document = mDocumentViewer->GetDocument(); |
7556 | |
7557 | nsCOMArray<nsIDocShellTreeItem> childShells; |
7558 | int32_t i = 0; |
7559 | nsCOMPtr<nsIDocShellTreeItem> child; |
7560 | while (NS_SUCCEEDED(mLSHE->ChildShellAt(i++, getter_AddRefs(child)))((bool)(__builtin_expect(!!(!NS_FAILED_impl(mLSHE->ChildShellAt (i++, getter_AddRefs(child)))), 1))) && |
7561 | child) { |
7562 | childShells.AppendObject(child); |
7563 | } |
7564 | |
7565 | // get the previous content viewer size |
7566 | nsIntRect oldBounds(0, 0, 0, 0); |
7567 | mLSHE->GetViewerBounds(oldBounds); |
7568 | |
7569 | // Restore the refresh URI list. The refresh timers will be restarted |
7570 | // when EndPageLoad() is called. |
7571 | nsCOMPtr<nsIMutableArray> refreshURIList = mLSHE->GetRefreshURIList(); |
7572 | |
7573 | // Reattach to the window object. |
7574 | mIsRestoringDocument = true; // for MediaDocument::BecomeInteractive |
7575 | rv = mDocumentViewer->Open(windowState, mLSHE); |
7576 | mIsRestoringDocument = false; |
7577 | |
7578 | // Hack to keep nsDocShellEditorData alive across the |
7579 | // SetDocumentViewer(nullptr) call below. |
7580 | UniquePtr<nsDocShellEditorData> data(mLSHE->ForgetEditorData()); |
7581 | |
7582 | // Now remove it from the cached presentation. |
7583 | mLSHE->SetDocumentViewer(nullptr); |
7584 | mEODForCurrentDocument = false; |
7585 | |
7586 | mLSHE->SetEditorData(data.release()); |
7587 | |
7588 | #ifdef DEBUG1 |
7589 | { |
7590 | nsCOMPtr<nsIMutableArray> refreshURIs = mLSHE->GetRefreshURIList(); |
7591 | nsCOMPtr<nsIDocShellTreeItem> childShell; |
7592 | mLSHE->ChildShellAt(0, getter_AddRefs(childShell)); |
7593 | NS_ASSERTION(!refreshURIs && !childShell,do { if (!(!refreshURIs && !childShell)) { NS_DebugBreak (NS_DEBUG_ASSERTION, "SHEntry should have cleared presentation state" , "!refreshURIs && !childShell", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 7594); MOZ_PretendNoReturn(); } } while (0) |
7594 | "SHEntry should have cleared presentation state")do { if (!(!refreshURIs && !childShell)) { NS_DebugBreak (NS_DEBUG_ASSERTION, "SHEntry should have cleared presentation state" , "!refreshURIs && !childShell", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 7594); MOZ_PretendNoReturn(); } } while (0); |
7595 | } |
7596 | #endif |
7597 | |
7598 | // Restore the sticky state of the viewer. The viewer has set this state |
7599 | // on the history entry in Destroy() just before marking itself non-sticky, |
7600 | // to avoid teardown of the presentation. |
7601 | mDocumentViewer->SetSticky(sticky); |
7602 | |
7603 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 7603); return rv; } } while (false); |
7604 | |
7605 | // mLSHE is now our currently-loaded document. |
7606 | SetHistoryEntryAndUpdateBC(Nothing(), Some<nsISHEntry*>(mLSHE)); |
7607 | |
7608 | // We aren't going to restore any items from the LayoutHistoryState, |
7609 | // but we don't want them to stay around in case the page is reloaded. |
7610 | SetLayoutHistoryState(nullptr); |
7611 | |
7612 | // This is the end of our Embed() replacement |
7613 | |
7614 | mSavingOldViewer = false; |
7615 | mEODForCurrentDocument = false; |
7616 | |
7617 | if (document) { |
7618 | RefPtr<nsDocShell> parent = GetInProcessParentDocshell(); |
7619 | if (parent) { |
7620 | RefPtr<Document> d = parent->GetDocument(); |
7621 | if (d) { |
7622 | if (d->EventHandlingSuppressed()) { |
7623 | document->SuppressEventHandling(d->EventHandlingSuppressed()); |
7624 | } |
7625 | } |
7626 | } |
7627 | |
7628 | // Use the uri from the mLSHE we had when we entered this function |
7629 | // (which need not match the document's URI if anchors are involved), |
7630 | // since that's the history entry we're loading. Note that if we use |
7631 | // origLSHE we don't have to worry about whether the entry in question |
7632 | // is still mLSHE or whether it's now mOSHE. |
7633 | nsCOMPtr<nsIURI> uri = origLSHE->GetURI(); |
7634 | SetCurrentURI(uri, document->GetChannel(), /* aFireLocationChange */ true, |
7635 | /* aIsInitialAboutBlank */ false, |
7636 | /* aLocationFlags */ 0); |
7637 | } |
7638 | |
7639 | // This is the end of our CreateDocumentViewer() replacement. |
7640 | // Now we simulate a load. First, we restore the state of the javascript |
7641 | // window object. |
7642 | nsCOMPtr<nsPIDOMWindowOuter> privWin = GetWindow(); |
7643 | NS_ASSERTION(privWin, "could not get nsPIDOMWindow interface")do { if (!(privWin)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "could not get nsPIDOMWindow interface" , "privWin", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 7643); MOZ_PretendNoReturn(); } } while (0); |
7644 | |
7645 | // Now, dispatch a title change event which would happen as the |
7646 | // <head> is parsed. |
7647 | document->NotifyPossibleTitleChange(false); |
7648 | |
7649 | // Now we simulate appending child docshells for subframes. |
7650 | for (i = 0; i < childShells.Count(); ++i) { |
7651 | nsIDocShellTreeItem* childItem = childShells.ObjectAt(i); |
7652 | nsCOMPtr<nsIDocShell> childShell = do_QueryInterface(childItem); |
7653 | |
7654 | // Make sure to not clobber the state of the child. Since AddChild |
7655 | // always clobbers it, save it off first. |
7656 | bool allowRedirects; |
7657 | childShell->GetAllowMetaRedirects(&allowRedirects); |
7658 | |
7659 | bool allowSubframes; |
7660 | childShell->GetAllowSubframes(&allowSubframes); |
7661 | |
7662 | bool allowImages; |
7663 | childShell->GetAllowImages(&allowImages); |
7664 | |
7665 | bool allowMedia = childShell->GetAllowMedia(); |
7666 | |
7667 | bool allowDNSPrefetch; |
7668 | childShell->GetAllowDNSPrefetch(&allowDNSPrefetch); |
7669 | |
7670 | bool allowContentRetargeting = childShell->GetAllowContentRetargeting(); |
7671 | bool allowContentRetargetingOnChildren = |
7672 | childShell->GetAllowContentRetargetingOnChildren(); |
7673 | |
7674 | // this.AddChild(child) calls child.SetDocLoaderParent(this), meaning that |
7675 | // the child inherits our state. Among other things, this means that the |
7676 | // child inherits our mPrivateBrowsingId, which is what we want. |
7677 | AddChild(childItem); |
7678 | |
7679 | childShell->SetAllowMetaRedirects(allowRedirects); |
7680 | childShell->SetAllowSubframes(allowSubframes); |
7681 | childShell->SetAllowImages(allowImages); |
7682 | childShell->SetAllowMedia(allowMedia); |
7683 | childShell->SetAllowDNSPrefetch(allowDNSPrefetch); |
7684 | childShell->SetAllowContentRetargeting(allowContentRetargeting); |
7685 | childShell->SetAllowContentRetargetingOnChildren( |
7686 | allowContentRetargetingOnChildren); |
7687 | |
7688 | rv = childShell->BeginRestore(nullptr, false); |
7689 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 7689); return rv; } } while (false); |
7690 | } |
7691 | |
7692 | // Make sure to restore the window state after adding the child shells back |
7693 | // to the tree. This is necessary for Thaw() and Resume() to propagate |
7694 | // properly. |
7695 | rv = privWin->RestoreWindowState(windowState); |
7696 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 7696); return rv; } } while (false); |
7697 | |
7698 | RefPtr<PresShell> presShell = GetPresShell(); |
7699 | |
7700 | // We may be displayed on a different monitor (or in a different |
7701 | // HiDPI mode) than when we got into the history list. So we need |
7702 | // to check if this has happened. See bug 838239. |
7703 | |
7704 | // Because the prescontext normally handles resolution changes via |
7705 | // a runnable (see nsPresContext::UIResolutionChanged), its device |
7706 | // context won't be -immediately- updated as a result of calling |
7707 | // presShell->BackingScaleFactorChanged(). |
7708 | |
7709 | // But we depend on that device context when adjusting the view size |
7710 | // via mDocumentViewer->SetBounds(newBounds) below. So we need to |
7711 | // explicitly tell it to check for changed resolution here. |
7712 | if (presShell) { |
7713 | RefPtr<nsPresContext> pc = presShell->GetPresContext(); |
7714 | if (pc->DeviceContext()->CheckDPIChange()) { |
7715 | presShell->BackingScaleFactorChanged(); |
7716 | } |
7717 | // Recompute zoom and text-zoom and such. |
7718 | pc->RecomputeBrowsingContextDependentData(); |
7719 | } |
7720 | |
7721 | nsViewManager* newVM = presShell ? presShell->GetViewManager() : nullptr; |
7722 | nsView* newRootView = newVM ? newVM->GetRootView() : nullptr; |
7723 | |
7724 | // Insert the new root view at the correct location in the view tree. |
7725 | if (container) { |
7726 | nsSubDocumentFrame* subDocFrame = |
7727 | do_QueryFrame(container->GetPrimaryFrame()); |
7728 | rootViewParent = subDocFrame ? subDocFrame->EnsureInnerView() : nullptr; |
7729 | } else { |
7730 | rootViewParent = nullptr; |
7731 | } |
7732 | if (sibling && sibling->GetPresShell() && |
7733 | sibling->GetPresShell()->GetViewManager()) { |
7734 | rootViewSibling = sibling->GetPresShell()->GetViewManager()->GetRootView(); |
7735 | } else { |
7736 | rootViewSibling = nullptr; |
7737 | } |
7738 | if (rootViewParent && newRootView && |
7739 | newRootView->GetParent() != rootViewParent) { |
7740 | nsViewManager* parentVM = rootViewParent->GetViewManager(); |
7741 | if (parentVM) { |
7742 | // InsertChild(parent, child, sib, true) inserts the child after |
7743 | // sib in content order, which is before sib in view order. BUT |
7744 | // when sib is null it inserts at the end of the the document |
7745 | // order, i.e., first in view order. But when oldRootSibling is |
7746 | // null, the old root as at the end of the view list --- last in |
7747 | // content order --- and we want to call InsertChild(parent, child, |
7748 | // nullptr, false) in that case. |
7749 | parentVM->InsertChild(rootViewParent, newRootView, rootViewSibling, |
7750 | rootViewSibling ? true : false); |
7751 | |
7752 | NS_ASSERTION(newRootView->GetNextSibling() == rootViewSibling,do { if (!(newRootView->GetNextSibling() == rootViewSibling )) { NS_DebugBreak(NS_DEBUG_ASSERTION, "error in InsertChild" , "newRootView->GetNextSibling() == rootViewSibling", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 7753); MOZ_PretendNoReturn(); } } while (0) |
7753 | "error in InsertChild")do { if (!(newRootView->GetNextSibling() == rootViewSibling )) { NS_DebugBreak(NS_DEBUG_ASSERTION, "error in InsertChild" , "newRootView->GetNextSibling() == rootViewSibling", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 7753); MOZ_PretendNoReturn(); } } while (0); |
7754 | } |
7755 | } |
7756 | |
7757 | nsCOMPtr<nsPIDOMWindowInner> privWinInner = privWin->GetCurrentInnerWindow(); |
7758 | |
7759 | // If parent is suspended, increase suspension count. |
7760 | // This can't be done as early as event suppression since this |
7761 | // depends on docshell tree. |
7762 | privWinInner->SyncStateFromParentWindow(); |
7763 | |
7764 | // Now that all of the child docshells have been put into place, we can |
7765 | // restart the timers for the window and all of the child frames. |
7766 | privWinInner->Resume(); |
7767 | |
7768 | // Now that we have found the inner window of the page restored |
7769 | // from the history, we have to make sure that |
7770 | // performance.navigation.type is 2. |
7771 | Performance* performance = privWinInner->GetPerformance(); |
7772 | if (performance) { |
7773 | performance->GetDOMTiming()->NotifyRestoreStart(); |
7774 | } |
7775 | |
7776 | // Restore the refresh URI list. The refresh timers will be restarted |
7777 | // when EndPageLoad() is called. |
7778 | mRefreshURIList = refreshURIList; |
7779 | |
7780 | // Meta-refresh timers have been restarted for this shell, but not |
7781 | // for our children. Walk the child shells and restart their timers. |
7782 | for (auto* childDocLoader : mChildList.ForwardRange()) { |
7783 | nsCOMPtr<nsIDocShell> child = do_QueryObject(childDocLoader); |
7784 | if (child) { |
7785 | child->ResumeRefreshURIs(); |
7786 | } |
7787 | } |
7788 | |
7789 | // Make sure this presentation is the same size as the previous |
7790 | // presentation. If this is not the same size we showed it at last time, |
7791 | // then we need to resize the widget. |
7792 | |
7793 | // XXXbryner This interacts poorly with Firefox's infobar. If the old |
7794 | // presentation had the infobar visible, then we will resize the new |
7795 | // presentation to that smaller size. However, firing the locationchanged |
7796 | // event will hide the infobar, which will immediately resize the window |
7797 | // back to the larger size. A future optimization might be to restore |
7798 | // the presentation at the "wrong" size, then fire the locationchanged |
7799 | // event and check whether the docshell's new size is the same as the |
7800 | // cached viewer size (skipping the resize if they are equal). |
7801 | |
7802 | if (newRootView) { |
7803 | if (!newBounds.IsEmpty() && |
7804 | !newBounds.ToUnknownRect().IsEqualEdges(oldBounds)) { |
7805 | MOZ_LOG(gPageCacheLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gPageCacheLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "resize widget(%d, %d, %d, %d)", newBounds .x, newBounds.y, newBounds.width, newBounds.height); } } while (0) |
7806 | ("resize widget(%d, %d, %d, %d)", newBounds.x, newBounds.y,do { const ::mozilla::LogModule* moz_real_module = gPageCacheLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "resize widget(%d, %d, %d, %d)", newBounds .x, newBounds.y, newBounds.width, newBounds.height); } } while (0) |
7807 | newBounds.width, newBounds.height))do { const ::mozilla::LogModule* moz_real_module = gPageCacheLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "resize widget(%d, %d, %d, %d)", newBounds .x, newBounds.y, newBounds.width, newBounds.height); } } while (0); |
7808 | mDocumentViewer->SetBounds(newBounds); |
7809 | } else if (ScrollContainerFrame* sf = |
7810 | presShell->GetRootScrollContainerFrame()) { |
7811 | sf->PostScrolledAreaEventForCurrentArea(); |
7812 | } |
7813 | } |
7814 | |
7815 | // The FinishRestore call below can kill these, null them out so we don't |
7816 | // have invalid pointer lying around. |
7817 | newRootView = rootViewSibling = rootViewParent = nullptr; |
7818 | newVM = nullptr; |
7819 | |
7820 | // If the IsUnderHiddenEmbedderElement() state has been changed, we need to |
7821 | // update it. |
7822 | if (oldPresShell && presShell && |
7823 | presShell->IsUnderHiddenEmbedderElement() != |
7824 | oldPresShell->IsUnderHiddenEmbedderElement()) { |
7825 | presShell->SetIsUnderHiddenEmbedderElement( |
7826 | oldPresShell->IsUnderHiddenEmbedderElement()); |
7827 | } |
7828 | |
7829 | // Simulate the completion of the load. |
7830 | nsDocShell::FinishRestore(); |
7831 | |
7832 | // Restart plugins, and paint the content. |
7833 | if (presShell) { |
7834 | presShell->Thaw(); |
7835 | } |
7836 | |
7837 | return privWin->FireDelayedDOMEvents(true); |
7838 | } |
7839 | |
7840 | nsresult nsDocShell::CreateDocumentViewer(const nsACString& aContentType, |
7841 | nsIRequest* aRequest, |
7842 | nsIStreamListener** aContentHandler) { |
7843 | *aContentHandler = nullptr; |
7844 | |
7845 | if (!mTreeOwner || mIsBeingDestroyed) { |
7846 | // If we don't have a tree owner, then we're in the process of being |
7847 | // destroyed. Rather than continue trying to load something, just give up. |
7848 | return NS_ERROR_DOCSHELL_DYING; |
7849 | } |
7850 | |
7851 | if (!mBrowsingContext->AncestorsAreCurrent() || |
7852 | mBrowsingContext->IsInBFCache()) { |
7853 | mBrowsingContext->RemoveRootFromBFCacheSync(); |
7854 | return NS_ERROR_NOT_AVAILABLE; |
7855 | } |
7856 | |
7857 | // Can we check the content type of the current content viewer |
7858 | // and reuse it without destroying it and re-creating it? |
7859 | |
7860 | NS_ASSERTION(mLoadGroup, "Someone ignored return from Init()?")do { if (!(mLoadGroup)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Someone ignored return from Init()?" , "mLoadGroup", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 7860); MOZ_PretendNoReturn(); } } while (0); |
7861 | |
7862 | // Instantiate the content viewer object |
7863 | nsCOMPtr<nsIDocumentViewer> viewer; |
7864 | nsresult rv = NewDocumentViewerObj(aContentType, aRequest, mLoadGroup, |
7865 | aContentHandler, getter_AddRefs(viewer)); |
7866 | |
7867 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
7868 | return rv; |
7869 | } |
7870 | |
7871 | // Notify the current document that it is about to be unloaded!! |
7872 | // |
7873 | // It is important to fire the unload() notification *before* any state |
7874 | // is changed within the DocShell - otherwise, javascript will get the |
7875 | // wrong information :-( |
7876 | // |
7877 | |
7878 | if (mSavingOldViewer) { |
7879 | // We determined that it was safe to cache the document presentation |
7880 | // at the time we initiated the new load. We need to check whether |
7881 | // it's still safe to do so, since there may have been DOM mutations |
7882 | // or new requests initiated. |
7883 | RefPtr<Document> doc = viewer->GetDocument(); |
7884 | mSavingOldViewer = CanSavePresentation( |
7885 | mLoadType, aRequest, doc, /* aReportBFCacheComboTelemetry */ false); |
7886 | } |
7887 | |
7888 | NS_ASSERTION(!mLoadingURI, "Re-entering unload?")do { if (!(!mLoadingURI)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Re-entering unload?", "!mLoadingURI", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 7888); MOZ_PretendNoReturn(); } } while (0); |
7889 | |
7890 | nsCOMPtr<nsIChannel> aOpenedChannel = do_QueryInterface(aRequest); |
7891 | if (aOpenedChannel) { |
7892 | aOpenedChannel->GetURI(getter_AddRefs(mLoadingURI)); |
7893 | } |
7894 | |
7895 | // Grab the current URI, we need to pass it to Embed, and OnNewURI will reset |
7896 | // it before we do call Embed. |
7897 | nsCOMPtr<nsIURI> previousURI = mCurrentURI; |
7898 | |
7899 | FirePageHideNotification(!mSavingOldViewer); |
7900 | if (mIsBeingDestroyed) { |
7901 | // Force to stop the newly created orphaned viewer. |
7902 | viewer->Stop(); |
7903 | return NS_ERROR_DOCSHELL_DYING; |
7904 | } |
7905 | mLoadingURI = nullptr; |
7906 | |
7907 | // Set mFiredUnloadEvent = false so that the unload handler for the |
7908 | // *new* document will fire. |
7909 | mFiredUnloadEvent = false; |
7910 | |
7911 | // we've created a new document so go ahead and call |
7912 | // OnNewURI(), but don't fire OnLocationChange() |
7913 | // notifications before we've called Embed(). See bug 284993. |
7914 | mURIResultedInDocument = true; |
7915 | bool errorOnLocationChangeNeeded = false; |
7916 | nsCOMPtr<nsIChannel> failedChannel = mFailedChannel; |
7917 | nsCOMPtr<nsIURI> failedURI; |
7918 | |
7919 | if (mLoadType == LOAD_ERROR_PAGE) { |
7920 | // We need to set the SH entry and our current URI here and not |
7921 | // at the moment we load the page. We want the same behavior |
7922 | // of Stop() as for a normal page load. See bug 514232 for details. |
7923 | |
7924 | // Revert mLoadType to load type to state the page load failed, |
7925 | // following function calls need it. |
7926 | mLoadType = mFailedLoadType; |
7927 | |
7928 | Document* doc = viewer->GetDocument(); |
7929 | if (doc) { |
7930 | doc->SetFailedChannel(failedChannel); |
7931 | } |
7932 | |
7933 | nsCOMPtr<nsIPrincipal> triggeringPrincipal; |
7934 | if (failedChannel) { |
7935 | // Make sure we have a URI to set currentURI. |
7936 | NS_GetFinalChannelURI(failedChannel, getter_AddRefs(failedURI)); |
7937 | } else { |
7938 | // if there is no failed channel we have to explicitly provide |
7939 | // a triggeringPrincipal for the history entry. |
7940 | triggeringPrincipal = nsContentUtils::GetSystemPrincipal(); |
7941 | } |
7942 | |
7943 | if (!failedURI) { |
7944 | failedURI = mFailedURI; |
7945 | } |
7946 | if (!failedURI) { |
7947 | // We need a URI object to store a session history entry, so make up a URI |
7948 | NS_NewURI(getter_AddRefs(failedURI), "about:blank"); |
7949 | } |
7950 | |
7951 | // When we don't have failedURI, something wrong will happen. See |
7952 | // bug 291876. |
7953 | MOZ_ASSERT(failedURI, "We don't have a URI for history APIs.")do { static_assert( mozilla::detail::AssertionConditionType< decltype(failedURI)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(failedURI))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("failedURI" " (" "We don't have a URI for history APIs." ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 7953 ); AnnotateMozCrashReason("MOZ_ASSERT" "(" "failedURI" ") (" "We don't have a URI for history APIs." ")"); do { MOZ_CrashSequence(__null, 7953); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
7954 | |
7955 | mFailedChannel = nullptr; |
7956 | mFailedURI = nullptr; |
7957 | |
7958 | // Create an shistory entry for the old load. |
7959 | if (failedURI) { |
7960 | errorOnLocationChangeNeeded = |
7961 | OnNewURI(failedURI, failedChannel, triggeringPrincipal, nullptr, |
7962 | nullptr, nullptr, false, false); |
7963 | } |
7964 | |
7965 | // Be sure to have a correct mLSHE, it may have been cleared by |
7966 | // EndPageLoad. See bug 302115. |
7967 | ChildSHistory* shistory = GetSessionHistory(); |
7968 | if (!mozilla::SessionHistoryInParent() && shistory && !mLSHE) { |
7969 | int32_t idx = shistory->LegacySHistory()->GetRequestedIndex(); |
7970 | if (idx == -1) { |
7971 | idx = shistory->Index(); |
7972 | } |
7973 | shistory->LegacySHistory()->GetEntryAtIndex(idx, getter_AddRefs(mLSHE)); |
7974 | } |
7975 | |
7976 | mLoadType = LOAD_ERROR_PAGE; |
7977 | } |
7978 | |
7979 | nsCOMPtr<nsIURI> finalURI; |
7980 | // If this a redirect, use the final url (uri) |
7981 | // else use the original url |
7982 | // |
7983 | // Note that this should match what documents do (see Document::Reset). |
7984 | NS_GetFinalChannelURI(aOpenedChannel, getter_AddRefs(finalURI)); |
7985 | |
7986 | bool onLocationChangeNeeded = false; |
7987 | if (finalURI) { |
7988 | // Pass false for aCloneSHChildren, since we're loading a new page here. |
7989 | onLocationChangeNeeded = OnNewURI(finalURI, aOpenedChannel, nullptr, |
7990 | nullptr, nullptr, nullptr, true, false); |
7991 | } |
7992 | |
7993 | // We inherit the classification flags from the parent document if the |
7994 | // document is about:blank and the principal matches. |
7995 | nsCOMPtr<nsIDocShellTreeItem> parentItem; |
7996 | GetInProcessSameTypeParent(getter_AddRefs(parentItem)); |
7997 | if (parentItem && finalURI && NS_IsAboutBlank(finalURI)) { |
7998 | RefPtr<Document> doc = viewer->GetDocument(); |
7999 | RefPtr<Document> parentDocument = parentItem->GetDocument(); |
8000 | if (parentDocument && doc && |
8001 | doc->NodePrincipal()->Equals(parentDocument->NodePrincipal())) { |
8002 | doc->SetClassificationFlags(parentDocument->GetClassificationFlags()); |
8003 | } |
8004 | } |
8005 | |
8006 | // let's try resetting the load group if we need to... |
8007 | nsCOMPtr<nsILoadGroup> currentLoadGroup; |
8008 | NS_ENSURE_SUCCESS(do { nsresult __rv = aOpenedChannel->GetLoadGroup(getter_AddRefs (currentLoadGroup)); if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "aOpenedChannel->GetLoadGroup(getter_AddRefs(currentLoadGroup))" , "NS_ERROR_FAILURE", static_cast<uint32_t>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""); NS_DebugBreak (NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 8010); return NS_ERROR_FAILURE; } } while (false) |
8009 | aOpenedChannel->GetLoadGroup(getter_AddRefs(currentLoadGroup)),do { nsresult __rv = aOpenedChannel->GetLoadGroup(getter_AddRefs (currentLoadGroup)); if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "aOpenedChannel->GetLoadGroup(getter_AddRefs(currentLoadGroup))" , "NS_ERROR_FAILURE", static_cast<uint32_t>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""); NS_DebugBreak (NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 8010); return NS_ERROR_FAILURE; } } while (false) |
8010 | NS_ERROR_FAILURE)do { nsresult __rv = aOpenedChannel->GetLoadGroup(getter_AddRefs (currentLoadGroup)); if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "aOpenedChannel->GetLoadGroup(getter_AddRefs(currentLoadGroup))" , "NS_ERROR_FAILURE", static_cast<uint32_t>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""); NS_DebugBreak (NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 8010); return NS_ERROR_FAILURE; } } while (false); |
8011 | |
8012 | if (currentLoadGroup != mLoadGroup) { |
8013 | nsLoadFlags loadFlags = 0; |
8014 | |
8015 | // Cancel any URIs that are currently loading... |
8016 | // XXX: Need to do this eventually Stop(); |
8017 | // |
8018 | // Retarget the document to this loadgroup... |
8019 | // |
8020 | /* First attach the channel to the right loadgroup |
8021 | * and then remove from the old loadgroup. This |
8022 | * puts the notifications in the right order and |
8023 | * we don't null-out mLSHE in OnStateChange() for |
8024 | * all redirected urls |
8025 | */ |
8026 | aOpenedChannel->SetLoadGroup(mLoadGroup); |
8027 | |
8028 | // Mark the channel as being a document URI... |
8029 | aOpenedChannel->GetLoadFlags(&loadFlags); |
8030 | loadFlags |= nsIChannel::LOAD_DOCUMENT_URI; |
8031 | nsCOMPtr<nsILoadInfo> loadInfo = aOpenedChannel->LoadInfo(); |
8032 | if (SandboxFlagsImplyCookies(loadInfo->GetSandboxFlags())) { |
8033 | loadFlags |= nsIRequest::LOAD_DOCUMENT_NEEDS_COOKIE; |
8034 | } |
8035 | |
8036 | aOpenedChannel->SetLoadFlags(loadFlags); |
8037 | |
8038 | mLoadGroup->AddRequest(aRequest, nullptr); |
8039 | if (currentLoadGroup) { |
8040 | currentLoadGroup->RemoveRequest(aRequest, nullptr, NS_BINDING_RETARGETED); |
8041 | } |
8042 | |
8043 | // Update the notification callbacks, so that progress and |
8044 | // status information are sent to the right docshell... |
8045 | aOpenedChannel->SetNotificationCallbacks(this); |
8046 | } |
8047 | |
8048 | if (mLoadingEntry && mBrowsingContext->IsTop() && |
8049 | !ShouldAddToSessionHistory(finalURI, aOpenedChannel)) { |
8050 | mLoadingEntry->mInfo.SetTransient(); |
8051 | } |
8052 | NS_ENSURE_SUCCESS(Embed(viewer, nullptr, false, aOpenedChannel, previousURI),do { nsresult __rv = Embed(viewer, nullptr, false, aOpenedChannel , previousURI); if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "Embed(viewer, nullptr, false, aOpenedChannel, previousURI)" , "NS_ERROR_FAILURE", static_cast<uint32_t>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""); NS_DebugBreak (NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 8053); return NS_ERROR_FAILURE; } } while (false) |
8053 | NS_ERROR_FAILURE)do { nsresult __rv = Embed(viewer, nullptr, false, aOpenedChannel , previousURI); if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "Embed(viewer, nullptr, false, aOpenedChannel, previousURI)" , "NS_ERROR_FAILURE", static_cast<uint32_t>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""); NS_DebugBreak (NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 8053); return NS_ERROR_FAILURE; } } while (false); |
8054 | |
8055 | if (!mBrowsingContext->GetHasLoadedNonInitialDocument()) { |
8056 | MOZ_ALWAYS_SUCCEEDS(mBrowsingContext->SetHasLoadedNonInitialDocument(true))do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl (mBrowsingContext->SetHasLoadedNonInitialDocument(true))), 1)))), 1))) { } else { do { do { } while (false); MOZ_ReportCrash ("" "NS_SUCCEEDED(mBrowsingContext->SetHasLoadedNonInitialDocument(true))" , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 8056); AnnotateMozCrashReason ("MOZ_CRASH(" "NS_SUCCEEDED(mBrowsingContext->SetHasLoadedNonInitialDocument(true))" ")"); do { MOZ_CrashSequence(__null, 8056); __attribute__((nomerge )) ::abort(); } while (false); } while (false); } } while (false ); |
8057 | } |
8058 | |
8059 | mSavedRefreshURIList = nullptr; |
8060 | mSavingOldViewer = false; |
8061 | mEODForCurrentDocument = false; |
8062 | |
8063 | // if this document is part of a multipart document, |
8064 | // the ID can be used to distinguish it from the other parts. |
8065 | nsCOMPtr<nsIMultiPartChannel> multiPartChannel(do_QueryInterface(aRequest)); |
8066 | if (multiPartChannel) { |
8067 | if (PresShell* presShell = GetPresShell()) { |
8068 | if (Document* doc = presShell->GetDocument()) { |
8069 | uint32_t partID; |
8070 | multiPartChannel->GetPartID(&partID); |
8071 | doc->SetPartID(partID); |
8072 | } |
8073 | } |
8074 | } |
8075 | |
8076 | if (errorOnLocationChangeNeeded) { |
8077 | FireOnLocationChange(this, failedChannel, failedURI, |
8078 | LOCATION_CHANGE_ERROR_PAGE); |
8079 | } else if (onLocationChangeNeeded) { |
8080 | uint32_t locationFlags = |
8081 | (mLoadType & LOAD_CMD_RELOAD) ? uint32_t(LOCATION_CHANGE_RELOAD) : 0; |
8082 | FireOnLocationChange(this, aRequest, mCurrentURI, locationFlags); |
8083 | } |
8084 | |
8085 | return NS_OK; |
8086 | } |
8087 | |
8088 | nsresult nsDocShell::NewDocumentViewerObj(const nsACString& aContentType, |
8089 | nsIRequest* aRequest, |
8090 | nsILoadGroup* aLoadGroup, |
8091 | nsIStreamListener** aContentHandler, |
8092 | nsIDocumentViewer** aViewer) { |
8093 | nsCOMPtr<nsIChannel> aOpenedChannel = do_QueryInterface(aRequest); |
8094 | |
8095 | nsCOMPtr<nsIDocumentLoaderFactory> docLoaderFactory = |
8096 | nsContentUtils::FindInternalDocumentViewer(aContentType); |
8097 | if (!docLoaderFactory) { |
8098 | return NS_ERROR_FAILURE; |
8099 | } |
8100 | |
8101 | // Now create an instance of the content viewer nsLayoutDLF makes the |
8102 | // determination if it should be a "view-source" instead of "view" |
8103 | nsresult rv = docLoaderFactory->CreateInstance( |
8104 | "view", aOpenedChannel, aLoadGroup, aContentType, this, nullptr, |
8105 | aContentHandler, aViewer); |
8106 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 8106); return rv; } } while (false); |
8107 | |
8108 | (*aViewer)->SetContainer(this); |
8109 | return NS_OK; |
8110 | } |
8111 | |
8112 | nsresult nsDocShell::SetupNewViewer(nsIDocumentViewer* aNewViewer, |
8113 | WindowGlobalChild* aWindowActor) { |
8114 | MOZ_ASSERT(!mIsBeingDestroyed)do { static_assert( mozilla::detail::AssertionConditionType< decltype(!mIsBeingDestroyed)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!mIsBeingDestroyed))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!mIsBeingDestroyed" , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 8114); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "!mIsBeingDestroyed" ")"); do { MOZ_CrashSequence (__null, 8114); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); |
8115 | |
8116 | // |
8117 | // Copy content viewer state from previous or parent content viewer. |
8118 | // |
8119 | // The following logic is mirrored in nsHTMLDocument::StartDocumentLoad! |
8120 | // |
8121 | // Do NOT to maintain a reference to the old content viewer outside |
8122 | // of this "copying" block, or it will not be destroyed until the end of |
8123 | // this routine and all <SCRIPT>s and event handlers fail! (bug 20315) |
8124 | // |
8125 | // In this block of code, if we get an error result, we return it |
8126 | // but if we get a null pointer, that's perfectly legal for parent |
8127 | // and parentDocumentViewer. |
8128 | // |
8129 | |
8130 | int32_t x = 0; |
8131 | int32_t y = 0; |
8132 | int32_t cx = 0; |
8133 | int32_t cy = 0; |
8134 | |
8135 | // This will get the size from the current content viewer or from the |
8136 | // Init settings |
8137 | DoGetPositionAndSize(&x, &y, &cx, &cy); |
8138 | |
8139 | nsCOMPtr<nsIDocShellTreeItem> parentAsItem; |
8140 | NS_ENSURE_SUCCESS(GetInProcessSameTypeParent(getter_AddRefs(parentAsItem)),do { nsresult __rv = GetInProcessSameTypeParent(getter_AddRefs (parentAsItem)); if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "GetInProcessSameTypeParent(getter_AddRefs(parentAsItem))" , "NS_ERROR_FAILURE", static_cast<uint32_t>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""); NS_DebugBreak (NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 8141); return NS_ERROR_FAILURE; } } while (false) |
8141 | NS_ERROR_FAILURE)do { nsresult __rv = GetInProcessSameTypeParent(getter_AddRefs (parentAsItem)); if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "GetInProcessSameTypeParent(getter_AddRefs(parentAsItem))" , "NS_ERROR_FAILURE", static_cast<uint32_t>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""); NS_DebugBreak (NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 8141); return NS_ERROR_FAILURE; } } while (false); |
8142 | nsCOMPtr<nsIDocShell> parent(do_QueryInterface(parentAsItem)); |
8143 | |
8144 | const Encoding* reloadEncoding = nullptr; |
8145 | int32_t reloadEncodingSource = kCharsetUninitialized; |
8146 | // |newMUDV| also serves as a flag to set the data from the above vars |
8147 | nsCOMPtr<nsIDocumentViewer> newViewer; |
8148 | |
8149 | if (mDocumentViewer || parent) { |
8150 | nsCOMPtr<nsIDocumentViewer> oldViewer; |
8151 | if (mDocumentViewer) { |
8152 | // Get any interesting state from old content viewer |
8153 | // XXX: it would be far better to just reuse the document viewer , |
8154 | // since we know we're just displaying the same document as before |
8155 | oldViewer = mDocumentViewer; |
8156 | |
8157 | // Tell the old content viewer to hibernate in session history when |
8158 | // it is destroyed. |
8159 | |
8160 | if (mSavingOldViewer && NS_FAILED(CaptureState())((bool)(__builtin_expect(!!(NS_FAILED_impl(CaptureState())), 0 )))) { |
8161 | if (mOSHE) { |
8162 | mOSHE->SyncPresentationState(); |
8163 | } |
8164 | mSavingOldViewer = false; |
8165 | } |
8166 | } else { |
8167 | // No old content viewer, so get state from parent's content viewer |
8168 | parent->GetDocViewer(getter_AddRefs(oldViewer)); |
8169 | } |
8170 | |
8171 | if (oldViewer) { |
8172 | newViewer = aNewViewer; |
8173 | if (newViewer) { |
8174 | reloadEncoding = |
8175 | oldViewer->GetReloadEncodingAndSource(&reloadEncodingSource); |
8176 | } |
8177 | } |
8178 | } |
8179 | |
8180 | nscolor bgcolor = NS_RGBA(0, 0, 0, 0)((nscolor)(((0) << 24) | ((0) << 16) | ((0) << 8) | (0))); |
8181 | bool isUnderHiddenEmbedderElement = false; |
8182 | // Ensure that the content viewer is destroyed *after* the GC - bug 71515 |
8183 | nsCOMPtr<nsIDocumentViewer> viewer = mDocumentViewer; |
8184 | if (viewer) { |
8185 | // Stop any activity that may be happening in the old document before |
8186 | // releasing it... |
8187 | viewer->Stop(); |
8188 | |
8189 | // Try to extract the canvas background color from the old |
8190 | // presentation shell, so we can use it for the next document. |
8191 | if (PresShell* presShell = viewer->GetPresShell()) { |
8192 | bgcolor = presShell->GetCanvasBackground(); |
8193 | isUnderHiddenEmbedderElement = presShell->IsUnderHiddenEmbedderElement(); |
8194 | } |
8195 | |
8196 | viewer->Close(mSavingOldViewer ? mOSHE.get() : nullptr); |
8197 | aNewViewer->SetPreviousViewer(viewer); |
8198 | } |
8199 | if (mOSHE && (!mDocumentViewer || !mSavingOldViewer)) { |
8200 | // We don't plan to save a viewer in mOSHE; tell it to drop |
8201 | // any other state it's holding. |
8202 | mOSHE->SyncPresentationState(); |
8203 | } |
8204 | |
8205 | mDocumentViewer = nullptr; |
8206 | |
8207 | // Now that we're about to switch documents, forget all of our children. |
8208 | // Note that we cached them as needed up in CaptureState above. |
8209 | DestroyChildren(); |
8210 | |
8211 | mDocumentViewer = aNewViewer; |
8212 | |
8213 | nsCOMPtr<nsIWidget> widget; |
8214 | NS_ENSURE_SUCCESS(GetMainWidget(getter_AddRefs(widget)), NS_ERROR_FAILURE)do { nsresult __rv = GetMainWidget(getter_AddRefs(widget)); if (((bool)(__builtin_expect(!!(NS_FAILED_impl(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "GetMainWidget(getter_AddRefs(widget))" , "NS_ERROR_FAILURE", static_cast<uint32_t>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""); NS_DebugBreak (NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 8214); return NS_ERROR_FAILURE; } } while (false); |
8215 | |
8216 | LayoutDeviceIntRect bounds(x, y, cx, cy); |
8217 | |
8218 | mDocumentViewer->SetNavigationTiming(mTiming); |
8219 | |
8220 | if (NS_FAILED(mDocumentViewer->Init(widget, bounds, aWindowActor))((bool)(__builtin_expect(!!(NS_FAILED_impl(mDocumentViewer-> Init(widget, bounds, aWindowActor))), 0)))) { |
8221 | nsCOMPtr<nsIDocumentViewer> viewer = mDocumentViewer; |
8222 | viewer->Close(nullptr); |
8223 | viewer->Destroy(); |
8224 | mDocumentViewer = nullptr; |
8225 | SetCurrentURIInternal(nullptr); |
8226 | NS_WARNING("DocumentViewer Initialization failed")NS_DebugBreak(NS_DEBUG_WARNING, "DocumentViewer Initialization failed" , nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 8226); |
8227 | return NS_ERROR_FAILURE; |
8228 | } |
8229 | |
8230 | // If we have old state to copy, set the old state onto the new content |
8231 | // viewer |
8232 | if (newViewer) { |
8233 | newViewer->SetReloadEncodingAndSource(reloadEncoding, reloadEncodingSource); |
8234 | } |
8235 | |
8236 | NS_ENSURE_TRUE(mDocumentViewer, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(mDocumentViewer)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "mDocumentViewer" ") failed" , nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 8236); return NS_ERROR_FAILURE; } } while (false); |
8237 | |
8238 | // Stuff the bgcolor from the old pres shell into the new |
8239 | // pres shell. This improves page load continuity. |
8240 | if (RefPtr<PresShell> presShell = mDocumentViewer->GetPresShell()) { |
8241 | presShell->SetCanvasBackground(bgcolor); |
8242 | presShell->ActivenessMaybeChanged(); |
8243 | if (isUnderHiddenEmbedderElement) { |
8244 | presShell->SetIsUnderHiddenEmbedderElement(isUnderHiddenEmbedderElement); |
8245 | } |
8246 | } |
8247 | |
8248 | // XXX: It looks like the LayoutState gets restored again in Embed() |
8249 | // right after the call to SetupNewViewer(...) |
8250 | |
8251 | // We don't show the mDocumentViewer yet, since we want to draw the old page |
8252 | // until we have enough of the new page to show. Just return with the new |
8253 | // viewer still set to hidden. |
8254 | |
8255 | return NS_OK; |
8256 | } |
8257 | |
8258 | void nsDocShell::SetDocCurrentStateObj(nsISHEntry* aShEntry, |
8259 | SessionHistoryInfo* aInfo) { |
8260 | NS_ENSURE_TRUE_VOID(mDocumentViewer)do { if ((__builtin_expect(!!(!(mDocumentViewer)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "mDocumentViewer" ") failed" , nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 8260); return; } } while (false); |
8261 | |
8262 | RefPtr<Document> document = GetDocument(); |
8263 | NS_ENSURE_TRUE_VOID(document)do { if ((__builtin_expect(!!(!(document)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "document" ") failed", nullptr , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 8263); return ; } } while (false); |
8264 | |
8265 | nsCOMPtr<nsIStructuredCloneContainer> scContainer; |
8266 | if (mozilla::SessionHistoryInParent()) { |
8267 | // If aInfo is null, just set the document's state object to null. |
8268 | if (aInfo) { |
8269 | scContainer = aInfo->GetStateData(); |
8270 | } |
8271 | MOZ_LOG(gSHLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gSHLog; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "nsDocShell %p SetCurrentDocState %p", this , scContainer.get()); } } while (0) |
8272 | ("nsDocShell %p SetCurrentDocState %p", this, scContainer.get()))do { const ::mozilla::LogModule* moz_real_module = gSHLog; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "nsDocShell %p SetCurrentDocState %p", this , scContainer.get()); } } while (0); |
8273 | } else { |
8274 | if (aShEntry) { |
8275 | scContainer = aShEntry->GetStateData(); |
8276 | |
8277 | // If aShEntry is null, just set the document's state object to null. |
8278 | } |
8279 | } |
8280 | |
8281 | // It's OK for scContainer too be null here; that just means there's no |
8282 | // state data associated with this history entry. |
8283 | document->SetStateObject(scContainer); |
8284 | } |
8285 | |
8286 | nsresult nsDocShell::CheckLoadingPermissions() { |
8287 | // This method checks whether the caller may load content into |
8288 | // this docshell. Even though we've done our best to hide windows |
8289 | // from code that doesn't have the right to access them, it's |
8290 | // still possible for an evil site to open a window and access |
8291 | // frames in the new window through window.frames[] (which is |
8292 | // allAccess for historic reasons), so we still need to do this |
8293 | // check on load. |
8294 | nsresult rv = NS_OK; |
8295 | |
8296 | if (!IsSubframe()) { |
8297 | // We're not a frame. Permit all loads. |
8298 | return rv; |
8299 | } |
8300 | |
8301 | // Note - The check for a current JSContext here isn't necessarily sensical. |
8302 | // It's just designed to preserve the old semantics during a mass-conversion |
8303 | // patch. |
8304 | if (!nsContentUtils::GetCurrentJSContext()) { |
8305 | return NS_OK; |
8306 | } |
8307 | |
8308 | // Check if the caller is from the same origin as this docshell, |
8309 | // or any of its ancestors. |
8310 | nsIPrincipal* subjectPrincipal = nsContentUtils::SubjectPrincipal(); |
8311 | for (RefPtr<BrowsingContext> bc = mBrowsingContext; bc; |
8312 | bc = bc->GetParent()) { |
8313 | // If the BrowsingContext is not in process, then it |
8314 | // is true by construction that its principal will not |
8315 | // subsume the current docshell principal. |
8316 | if (!bc->IsInProcess()) { |
8317 | continue; |
8318 | } |
8319 | |
8320 | nsCOMPtr<nsIScriptGlobalObject> sgo = |
8321 | bc->GetDocShell()->GetScriptGlobalObject(); |
8322 | nsCOMPtr<nsIScriptObjectPrincipal> sop(do_QueryInterface(sgo)); |
8323 | |
8324 | nsIPrincipal* p; |
8325 | if (!sop || !(p = sop->GetPrincipal())) { |
8326 | return NS_ERROR_UNEXPECTED; |
8327 | } |
8328 | |
8329 | // file: URIs are considered the same domain for the purpose of frame |
8330 | // navigation by clicking a targeted link, regardless of script |
8331 | // accessibility (bug 1934807). |
8332 | if (subjectPrincipal->Subsumes(p) || |
8333 | (subjectPrincipal->SchemeIs("file") && p->SchemeIs("file"))) { |
8334 | // Same origin, permit load |
8335 | return NS_OK; |
8336 | } |
8337 | } |
8338 | |
8339 | return NS_ERROR_DOM_PROP_ACCESS_DENIED; |
8340 | } |
8341 | |
8342 | //***************************************************************************** |
8343 | // nsDocShell: Site Loading |
8344 | //***************************************************************************** |
8345 | |
8346 | void nsDocShell::CopyFavicon(nsIURI* aOldURI, nsIURI* aNewURI, |
8347 | bool aInPrivateBrowsing) { |
8348 | if (XRE_IsContentProcess()) { |
8349 | dom::ContentChild* contentChild = dom::ContentChild::GetSingleton(); |
8350 | if (contentChild) { |
8351 | contentChild->SendCopyFavicon(aOldURI, aNewURI, aInPrivateBrowsing); |
8352 | } |
8353 | return; |
8354 | } |
8355 | |
8356 | #ifdef MOZ_PLACES1 |
8357 | auto* faviconService = nsFaviconService::GetFaviconService(); |
8358 | if (faviconService) { |
8359 | faviconService->AsyncTryCopyFavicons( |
8360 | aOldURI, aNewURI, |
8361 | aInPrivateBrowsing ? nsIFaviconService::FAVICON_LOAD_PRIVATE |
8362 | : nsIFaviconService::FAVICON_LOAD_NON_PRIVATE); |
8363 | } |
8364 | #endif |
8365 | } |
8366 | |
8367 | class InternalLoadEvent : public Runnable { |
8368 | public: |
8369 | InternalLoadEvent(nsDocShell* aDocShell, nsDocShellLoadState* aLoadState) |
8370 | : mozilla::Runnable("InternalLoadEvent"), |
8371 | mDocShell(aDocShell), |
8372 | mLoadState(aLoadState) { |
8373 | // For events, both target and filename should be the version of "null" they |
8374 | // expect. By the time the event is fired, both window targeting and file |
8375 | // downloading have been handled, so we should never have an internal load |
8376 | // event that retargets or had a download. |
8377 | mLoadState->SetTarget(u""_ns); |
8378 | mLoadState->SetFileName(VoidString()); |
8379 | } |
8380 | |
8381 | NS_IMETHODvirtual nsresult |
8382 | Run() override { |
8383 | #ifndef ANDROID |
8384 | MOZ_ASSERT(mLoadState->TriggeringPrincipal(),do { static_assert( mozilla::detail::AssertionConditionType< decltype(mLoadState->TriggeringPrincipal())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mLoadState->TriggeringPrincipal ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("mLoadState->TriggeringPrincipal()" " (" "InternalLoadEvent: Should always have a principal here" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 8385 ); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLoadState->TriggeringPrincipal()" ") (" "InternalLoadEvent: Should always have a principal here" ")"); do { MOZ_CrashSequence(__null, 8385); __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
8385 | "InternalLoadEvent: Should always have a principal here")do { static_assert( mozilla::detail::AssertionConditionType< decltype(mLoadState->TriggeringPrincipal())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mLoadState->TriggeringPrincipal ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("mLoadState->TriggeringPrincipal()" " (" "InternalLoadEvent: Should always have a principal here" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 8385 ); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLoadState->TriggeringPrincipal()" ") (" "InternalLoadEvent: Should always have a principal here" ")"); do { MOZ_CrashSequence(__null, 8385); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
8386 | #endif |
8387 | return mDocShell->InternalLoad(mLoadState); |
8388 | } |
8389 | |
8390 | private: |
8391 | RefPtr<nsDocShell> mDocShell; |
8392 | RefPtr<nsDocShellLoadState> mLoadState; |
8393 | }; |
8394 | |
8395 | /** |
8396 | * Returns true if we started an asynchronous load (i.e., from the network), but |
8397 | * the document we're loading there hasn't yet become this docshell's active |
8398 | * document. |
8399 | * |
8400 | * When JustStartedNetworkLoad is true, you should be careful about modifying |
8401 | * mLoadType and mLSHE. These are both set when the asynchronous load first |
8402 | * starts, and the load expects that, when it eventually runs InternalLoad, |
8403 | * mLoadType and mLSHE will have their original values. |
8404 | */ |
8405 | bool nsDocShell::JustStartedNetworkLoad() { |
8406 | return mDocumentRequest && mDocumentRequest != GetCurrentDocChannel(); |
8407 | } |
8408 | |
8409 | // The contentType will be INTERNAL_(I)FRAME if this docshell is for a |
8410 | // non-toplevel browsing context in spec terms. (frame, iframe, <object>, |
8411 | // <embed>, etc) |
8412 | // |
8413 | // This return value will be used when we call NS_CheckContentLoadPolicy, and |
8414 | // later when we call DoURILoad. |
8415 | nsContentPolicyType nsDocShell::DetermineContentType() { |
8416 | if (!IsSubframe()) { |
8417 | return nsIContentPolicy::TYPE_DOCUMENT; |
8418 | } |
8419 | |
8420 | const auto& maybeEmbedderElementType = |
8421 | GetBrowsingContext()->GetEmbedderElementType(); |
8422 | if (!maybeEmbedderElementType) { |
8423 | // If the EmbedderElementType hasn't been set yet, just assume we're |
8424 | // an iframe since that's more common. |
8425 | return nsIContentPolicy::TYPE_INTERNAL_IFRAME; |
8426 | } |
8427 | |
8428 | return maybeEmbedderElementType->EqualsLiteral("iframe") |
8429 | ? nsIContentPolicy::TYPE_INTERNAL_IFRAME |
8430 | : nsIContentPolicy::TYPE_INTERNAL_FRAME; |
8431 | } |
8432 | |
8433 | bool nsDocShell::NoopenerForceEnabled() { |
8434 | // If current's top-level browsing context's active document's |
8435 | // cross-origin-opener-policy is "same-origin" or "same-origin + COEP" then |
8436 | // if currentDoc's origin is not same origin with currentDoc's top-level |
8437 | // origin, noopener is force enabled, and name is cleared to "_blank". |
8438 | auto topPolicy = mBrowsingContext->Top()->GetOpenerPolicy(); |
8439 | return (topPolicy == nsILoadInfo::OPENER_POLICY_SAME_ORIGIN || |
8440 | topPolicy == |
8441 | nsILoadInfo:: |
8442 | OPENER_POLICY_SAME_ORIGIN_EMBEDDER_POLICY_REQUIRE_CORP) && |
8443 | !mBrowsingContext->SameOriginWithTop(); |
8444 | } |
8445 | |
8446 | nsresult nsDocShell::PerformRetargeting(nsDocShellLoadState* aLoadState) { |
8447 | MOZ_ASSERT(aLoadState, "need a load state!")do { static_assert( mozilla::detail::AssertionConditionType< decltype(aLoadState)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aLoadState))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aLoadState" " (" "need a load state!" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 8447 ); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState" ") (" "need a load state!" ")"); do { MOZ_CrashSequence(__null, 8447 ); __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
8448 | MOZ_ASSERT(!aLoadState->Target().IsEmpty(), "should have a target here!")do { static_assert( mozilla::detail::AssertionConditionType< decltype(!aLoadState->Target().IsEmpty())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!aLoadState->Target().IsEmpty ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("!aLoadState->Target().IsEmpty()" " (" "should have a target here!" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 8448 ); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aLoadState->Target().IsEmpty()" ") (" "should have a target here!" ")"); do { MOZ_CrashSequence (__null, 8448); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); |
8449 | MOZ_ASSERT(aLoadState->TargetBrowsingContext().IsNull(),do { static_assert( mozilla::detail::AssertionConditionType< decltype(aLoadState->TargetBrowsingContext().IsNull())> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(aLoadState->TargetBrowsingContext().IsNull()))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("aLoadState->TargetBrowsingContext().IsNull()" " (" "should not have picked target yet" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 8450); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->TargetBrowsingContext().IsNull()" ") (" "should not have picked target yet" ")"); do { MOZ_CrashSequence (__null, 8450); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false) |
8450 | "should not have picked target yet")do { static_assert( mozilla::detail::AssertionConditionType< decltype(aLoadState->TargetBrowsingContext().IsNull())> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(aLoadState->TargetBrowsingContext().IsNull()))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("aLoadState->TargetBrowsingContext().IsNull()" " (" "should not have picked target yet" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 8450); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->TargetBrowsingContext().IsNull()" ") (" "should not have picked target yet" ")"); do { MOZ_CrashSequence (__null, 8450); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); |
8451 | |
8452 | nsresult rv = NS_OK; |
8453 | RefPtr<BrowsingContext> targetContext; |
8454 | |
8455 | // Only _self, _parent, and _top are supported in noopener case. But we |
8456 | // have to be careful to not apply that to the noreferrer case. See bug |
8457 | // 1358469. |
8458 | bool allowNamedTarget = |
8459 | !aLoadState->HasInternalLoadFlags(INTERNAL_LOAD_FLAGS_NO_OPENER) || |
8460 | aLoadState->HasInternalLoadFlags(INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER); |
8461 | if (allowNamedTarget || |
8462 | aLoadState->Target().LowerCaseEqualsLiteral("_self") || |
8463 | aLoadState->Target().LowerCaseEqualsLiteral("_parent") || |
8464 | aLoadState->Target().LowerCaseEqualsLiteral("_top")) { |
8465 | Document* document = GetDocument(); |
8466 | NS_ENSURE_TRUE(document, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(document)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "document" ") failed", nullptr , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 8466); return NS_ERROR_FAILURE; } } while (false); |
8467 | WindowGlobalChild* wgc = document->GetWindowGlobalChild(); |
8468 | NS_ENSURE_TRUE(wgc, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(wgc)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING , "NS_ENSURE_TRUE(" "wgc" ") failed", nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 8468); return NS_ERROR_FAILURE; } } while (false); |
8469 | targetContext = wgc->FindBrowsingContextWithName( |
8470 | aLoadState->Target(), /* aUseEntryGlobalForAccessCheck */ false); |
8471 | } |
8472 | |
8473 | if (!targetContext) { |
8474 | // If the targetContext doesn't exist, then this is a new docShell and we |
8475 | // should consider this a TYPE_DOCUMENT load |
8476 | // |
8477 | // For example, when target="_blank" |
8478 | |
8479 | // If there's no targetContext, that means we are about to create a new |
8480 | // window. Perform a content policy check before creating the window. Please |
8481 | // note for all other docshell loads content policy checks are performed |
8482 | // within the contentSecurityManager when the channel is about to be |
8483 | // openend. |
8484 | nsISupports* requestingContext = nullptr; |
8485 | if (XRE_IsContentProcess()) { |
8486 | // In e10s the child process doesn't have access to the element that |
8487 | // contains the browsing context (because that element is in the chrome |
8488 | // process). So we just pass mScriptGlobal. |
8489 | requestingContext = ToSupports(mScriptGlobal); |
8490 | } else { |
8491 | // This is for loading non-e10s tabs and toplevel windows of various |
8492 | // sorts. |
8493 | // For the toplevel window cases, requestingElement will be null. |
8494 | nsCOMPtr<Element> requestingElement = |
8495 | mScriptGlobal->GetFrameElementInternal(); |
8496 | requestingContext = requestingElement; |
8497 | } |
8498 | |
8499 | // Ideally we should use the same loadinfo as within DoURILoad which |
8500 | // should match this one when both are applicable. |
8501 | nsCOMPtr<nsILoadInfo> secCheckLoadInfo = |
8502 | new LoadInfo(mScriptGlobal, aLoadState->URI(), |
8503 | aLoadState->TriggeringPrincipal(), requestingContext, |
8504 | nsILoadInfo::SEC_ONLY_FOR_EXPLICIT_CONTENTSEC_CHECK, 0); |
8505 | |
8506 | // Since Content Policy checks are performed within docShell as well as |
8507 | // the ContentSecurityManager we need a reliable way to let certain |
8508 | // nsIContentPolicy consumers ignore duplicate calls. |
8509 | secCheckLoadInfo->SetSkipContentPolicyCheckForWebRequest(true); |
8510 | |
8511 | int16_t shouldLoad = nsIContentPolicy::ACCEPT; |
8512 | rv = NS_CheckContentLoadPolicy(aLoadState->URI(), secCheckLoadInfo, |
8513 | &shouldLoad); |
8514 | |
8515 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || NS_CP_REJECTED(shouldLoad)((shouldLoad) != nsIContentPolicy::ACCEPT)) { |
8516 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) { |
8517 | if (shouldLoad == nsIContentPolicy::REJECT_TYPE) { |
8518 | return NS_ERROR_CONTENT_BLOCKED_SHOW_ALT; |
8519 | } |
8520 | if (shouldLoad == nsIContentPolicy::REJECT_POLICY) { |
8521 | return NS_ERROR_BLOCKED_BY_POLICY; |
8522 | } |
8523 | } |
8524 | |
8525 | return NS_ERROR_CONTENT_BLOCKED; |
8526 | } |
8527 | } |
8528 | |
8529 | // |
8530 | // Resolve the window target before going any further... |
8531 | // If the load has been targeted to another DocShell, then transfer the |
8532 | // load to it... |
8533 | // |
8534 | |
8535 | // We've already done our owner-inheriting. Mask out that bit, so we |
8536 | // don't try inheriting an owner from the target window if we came up |
8537 | // with a null owner above. |
8538 | aLoadState->UnsetInternalLoadFlag(INTERNAL_LOAD_FLAGS_INHERIT_PRINCIPAL); |
8539 | |
8540 | if (!targetContext) { |
8541 | // If the docshell's document is sandboxed, only open a new window |
8542 | // if the document's SANDBOXED_AUXILLARY_NAVIGATION flag is not set. |
8543 | // (i.e. if allow-popups is specified) |
8544 | NS_ENSURE_TRUE(mDocumentViewer, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(mDocumentViewer)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "mDocumentViewer" ") failed" , nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 8544); return NS_ERROR_FAILURE; } } while (false); |
8545 | Document* doc = mDocumentViewer->GetDocument(); |
8546 | |
8547 | const bool isDocumentAuxSandboxed = |
8548 | doc && (doc->GetSandboxFlags() & SANDBOXED_AUXILIARY_NAVIGATION); |
8549 | |
8550 | if (isDocumentAuxSandboxed) { |
8551 | return NS_ERROR_DOM_INVALID_ACCESS_ERR; |
8552 | } |
8553 | |
8554 | nsCOMPtr<nsPIDOMWindowOuter> win = GetWindow(); |
8555 | NS_ENSURE_TRUE(win, NS_ERROR_NOT_AVAILABLE)do { if ((__builtin_expect(!!(!(win)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING , "NS_ENSURE_TRUE(" "win" ") failed", nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 8555); return NS_ERROR_NOT_AVAILABLE; } } while (false); |
8556 | |
8557 | RefPtr<BrowsingContext> newBC; |
8558 | nsAutoCString spec; |
8559 | aLoadState->URI()->GetSpec(spec); |
8560 | |
8561 | // If we are a noopener load, we just hand the whole thing over to our |
8562 | // window. |
8563 | if (aLoadState->HasInternalLoadFlags(INTERNAL_LOAD_FLAGS_NO_OPENER) || |
8564 | NoopenerForceEnabled()) { |
8565 | // Various asserts that we know to hold because NO_OPENER loads can only |
8566 | // happen for links. |
8567 | MOZ_ASSERT(!aLoadState->LoadReplace())do { static_assert( mozilla::detail::AssertionConditionType< decltype(!aLoadState->LoadReplace())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!aLoadState->LoadReplace( )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("!aLoadState->LoadReplace()", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 8567); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aLoadState->LoadReplace()" ")"); do { MOZ_CrashSequence(__null, 8567); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
8568 | MOZ_ASSERT(aLoadState->PrincipalToInherit() ==do { static_assert( mozilla::detail::AssertionConditionType< decltype(aLoadState->PrincipalToInherit() == aLoadState-> TriggeringPrincipal())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aLoadState->PrincipalToInherit () == aLoadState->TriggeringPrincipal()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aLoadState->PrincipalToInherit() == aLoadState->TriggeringPrincipal()" , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 8569); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "aLoadState->PrincipalToInherit() == aLoadState->TriggeringPrincipal()" ")"); do { MOZ_CrashSequence(__null, 8569); __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
8569 | aLoadState->TriggeringPrincipal())do { static_assert( mozilla::detail::AssertionConditionType< decltype(aLoadState->PrincipalToInherit() == aLoadState-> TriggeringPrincipal())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aLoadState->PrincipalToInherit () == aLoadState->TriggeringPrincipal()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aLoadState->PrincipalToInherit() == aLoadState->TriggeringPrincipal()" , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 8569); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "aLoadState->PrincipalToInherit() == aLoadState->TriggeringPrincipal()" ")"); do { MOZ_CrashSequence(__null, 8569); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
8570 | MOZ_ASSERT(!(aLoadState->InternalLoadFlags() &do { static_assert( mozilla::detail::AssertionConditionType< decltype(!(aLoadState->InternalLoadFlags() & ~(INTERNAL_LOAD_FLAGS_NO_OPENER | INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER)))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!(aLoadState->InternalLoadFlags () & ~(INTERNAL_LOAD_FLAGS_NO_OPENER | INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER ))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("!(aLoadState->InternalLoadFlags() & ~(INTERNAL_LOAD_FLAGS_NO_OPENER | INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER))" " (" "Only INTERNAL_LOAD_FLAGS_NO_OPENER and " "INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER can be set" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 8574 ); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!(aLoadState->InternalLoadFlags() & ~(INTERNAL_LOAD_FLAGS_NO_OPENER | INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER))" ") (" "Only INTERNAL_LOAD_FLAGS_NO_OPENER and " "INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER can be set" ")"); do { MOZ_CrashSequence(__null, 8574); __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
8571 | ~(INTERNAL_LOAD_FLAGS_NO_OPENER |do { static_assert( mozilla::detail::AssertionConditionType< decltype(!(aLoadState->InternalLoadFlags() & ~(INTERNAL_LOAD_FLAGS_NO_OPENER | INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER)))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!(aLoadState->InternalLoadFlags () & ~(INTERNAL_LOAD_FLAGS_NO_OPENER | INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER ))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("!(aLoadState->InternalLoadFlags() & ~(INTERNAL_LOAD_FLAGS_NO_OPENER | INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER))" " (" "Only INTERNAL_LOAD_FLAGS_NO_OPENER and " "INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER can be set" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 8574 ); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!(aLoadState->InternalLoadFlags() & ~(INTERNAL_LOAD_FLAGS_NO_OPENER | INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER))" ") (" "Only INTERNAL_LOAD_FLAGS_NO_OPENER and " "INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER can be set" ")"); do { MOZ_CrashSequence(__null, 8574); __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
8572 | INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER)),do { static_assert( mozilla::detail::AssertionConditionType< decltype(!(aLoadState->InternalLoadFlags() & ~(INTERNAL_LOAD_FLAGS_NO_OPENER | INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER)))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!(aLoadState->InternalLoadFlags () & ~(INTERNAL_LOAD_FLAGS_NO_OPENER | INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER ))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("!(aLoadState->InternalLoadFlags() & ~(INTERNAL_LOAD_FLAGS_NO_OPENER | INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER))" " (" "Only INTERNAL_LOAD_FLAGS_NO_OPENER and " "INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER can be set" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 8574 ); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!(aLoadState->InternalLoadFlags() & ~(INTERNAL_LOAD_FLAGS_NO_OPENER | INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER))" ") (" "Only INTERNAL_LOAD_FLAGS_NO_OPENER and " "INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER can be set" ")"); do { MOZ_CrashSequence(__null, 8574); __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
8573 | "Only INTERNAL_LOAD_FLAGS_NO_OPENER and "do { static_assert( mozilla::detail::AssertionConditionType< decltype(!(aLoadState->InternalLoadFlags() & ~(INTERNAL_LOAD_FLAGS_NO_OPENER | INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER)))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!(aLoadState->InternalLoadFlags () & ~(INTERNAL_LOAD_FLAGS_NO_OPENER | INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER ))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("!(aLoadState->InternalLoadFlags() & ~(INTERNAL_LOAD_FLAGS_NO_OPENER | INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER))" " (" "Only INTERNAL_LOAD_FLAGS_NO_OPENER and " "INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER can be set" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 8574 ); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!(aLoadState->InternalLoadFlags() & ~(INTERNAL_LOAD_FLAGS_NO_OPENER | INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER))" ") (" "Only INTERNAL_LOAD_FLAGS_NO_OPENER and " "INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER can be set" ")"); do { MOZ_CrashSequence(__null, 8574); __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
8574 | "INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER can be set")do { static_assert( mozilla::detail::AssertionConditionType< decltype(!(aLoadState->InternalLoadFlags() & ~(INTERNAL_LOAD_FLAGS_NO_OPENER | INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER)))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!(aLoadState->InternalLoadFlags () & ~(INTERNAL_LOAD_FLAGS_NO_OPENER | INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER ))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("!(aLoadState->InternalLoadFlags() & ~(INTERNAL_LOAD_FLAGS_NO_OPENER | INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER))" " (" "Only INTERNAL_LOAD_FLAGS_NO_OPENER and " "INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER can be set" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 8574 ); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!(aLoadState->InternalLoadFlags() & ~(INTERNAL_LOAD_FLAGS_NO_OPENER | INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER))" ") (" "Only INTERNAL_LOAD_FLAGS_NO_OPENER and " "INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER can be set" ")"); do { MOZ_CrashSequence(__null, 8574); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
8575 | MOZ_ASSERT_IF(aLoadState->PostDataStream(),do { if (aLoadState->PostDataStream()) { do { static_assert ( mozilla::detail::AssertionConditionType<decltype(aLoadState ->IsFormSubmission())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aLoadState->IsFormSubmission ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("aLoadState->IsFormSubmission()", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 8576); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->IsFormSubmission()" ")"); do { MOZ_CrashSequence(__null, 8576); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) |
8576 | aLoadState->IsFormSubmission())do { if (aLoadState->PostDataStream()) { do { static_assert ( mozilla::detail::AssertionConditionType<decltype(aLoadState ->IsFormSubmission())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aLoadState->IsFormSubmission ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("aLoadState->IsFormSubmission()", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 8576); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->IsFormSubmission()" ")"); do { MOZ_CrashSequence(__null, 8576); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); |
8577 | MOZ_ASSERT(!aLoadState->HeadersStream())do { static_assert( mozilla::detail::AssertionConditionType< decltype(!aLoadState->HeadersStream())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!aLoadState->HeadersStream ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("!aLoadState->HeadersStream()", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 8577); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aLoadState->HeadersStream()" ")"); do { MOZ_CrashSequence(__null, 8577); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
8578 | // If OnLinkClickSync was invoked inside the onload handler, the load |
8579 | // type would be set to LOAD_NORMAL_REPLACE; otherwise it should be |
8580 | // LOAD_LINK. |
8581 | MOZ_ASSERT(aLoadState->LoadType() == LOAD_LINK ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(aLoadState->LoadType() == LOAD_LINK || aLoadState ->LoadType() == LOAD_NORMAL_REPLACE)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aLoadState->LoadType() == LOAD_LINK || aLoadState->LoadType() == LOAD_NORMAL_REPLACE ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "aLoadState->LoadType() == LOAD_LINK || aLoadState->LoadType() == LOAD_NORMAL_REPLACE" , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 8582); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "aLoadState->LoadType() == LOAD_LINK || aLoadState->LoadType() == LOAD_NORMAL_REPLACE" ")"); do { MOZ_CrashSequence(__null, 8582); __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
8582 | aLoadState->LoadType() == LOAD_NORMAL_REPLACE)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aLoadState->LoadType() == LOAD_LINK || aLoadState ->LoadType() == LOAD_NORMAL_REPLACE)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aLoadState->LoadType() == LOAD_LINK || aLoadState->LoadType() == LOAD_NORMAL_REPLACE ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "aLoadState->LoadType() == LOAD_LINK || aLoadState->LoadType() == LOAD_NORMAL_REPLACE" , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 8582); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "aLoadState->LoadType() == LOAD_LINK || aLoadState->LoadType() == LOAD_NORMAL_REPLACE" ")"); do { MOZ_CrashSequence(__null, 8582); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
8583 | MOZ_ASSERT(!aLoadState->LoadIsFromSessionHistory())do { static_assert( mozilla::detail::AssertionConditionType< decltype(!aLoadState->LoadIsFromSessionHistory())>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(!aLoadState->LoadIsFromSessionHistory()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!aLoadState->LoadIsFromSessionHistory()" , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 8583); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "!aLoadState->LoadIsFromSessionHistory()" ")"); do { MOZ_CrashSequence(__null, 8583); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
8584 | MOZ_ASSERT(aLoadState->FirstParty())do { static_assert( mozilla::detail::AssertionConditionType< decltype(aLoadState->FirstParty())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aLoadState->FirstParty()) )), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aLoadState->FirstParty()" , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 8584); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "aLoadState->FirstParty()" ")"); do { MOZ_CrashSequence (__null, 8584); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); // Windowwatcher will assume this. |
8585 | |
8586 | RefPtr<nsDocShellLoadState> loadState = |
8587 | new nsDocShellLoadState(aLoadState->URI()); |
8588 | |
8589 | // Set up our loadinfo so it will do the load as much like we would have |
8590 | // as possible. |
8591 | loadState->SetReferrerInfo(aLoadState->GetReferrerInfo()); |
8592 | loadState->SetOriginalURI(aLoadState->OriginalURI()); |
8593 | |
8594 | Maybe<nsCOMPtr<nsIURI>> resultPrincipalURI; |
8595 | aLoadState->GetMaybeResultPrincipalURI(resultPrincipalURI); |
8596 | |
8597 | loadState->SetMaybeResultPrincipalURI(resultPrincipalURI); |
8598 | loadState->SetKeepResultPrincipalURIIfSet( |
8599 | aLoadState->KeepResultPrincipalURIIfSet()); |
8600 | // LoadReplace will always be false due to asserts above, skip setting |
8601 | // it. |
8602 | loadState->SetTriggeringPrincipal(aLoadState->TriggeringPrincipal()); |
8603 | loadState->SetTriggeringSandboxFlags( |
8604 | aLoadState->TriggeringSandboxFlags()); |
8605 | loadState->SetTriggeringWindowId(aLoadState->TriggeringWindowId()); |
8606 | loadState->SetTriggeringStorageAccess( |
8607 | aLoadState->TriggeringStorageAccess()); |
8608 | loadState->SetTriggeringClassificationFlags( |
8609 | aLoadState->TriggeringClassificationFlags()); |
8610 | loadState->SetCsp(aLoadState->Csp()); |
8611 | loadState->SetInheritPrincipal(aLoadState->HasInternalLoadFlags( |
8612 | INTERNAL_LOAD_FLAGS_INHERIT_PRINCIPAL)); |
8613 | // Explicit principal because we do not want any guesses as to what the |
8614 | // principal to inherit is: it should be aTriggeringPrincipal. |
8615 | loadState->SetPrincipalIsExplicit(true); |
8616 | loadState->SetLoadType(aLoadState->LoadType()); |
8617 | loadState->SetForceAllowDataURI(aLoadState->HasInternalLoadFlags( |
8618 | INTERNAL_LOAD_FLAGS_FORCE_ALLOW_DATA_URI)); |
8619 | |
8620 | loadState->SetHasValidUserGestureActivation( |
8621 | aLoadState->HasValidUserGestureActivation()); |
8622 | |
8623 | loadState->SetTextDirectiveUserActivation( |
8624 | aLoadState->GetTextDirectiveUserActivation()); |
8625 | |
8626 | // Propagate POST data to the new load. |
8627 | loadState->SetPostDataStream(aLoadState->PostDataStream()); |
8628 | loadState->SetIsFormSubmission(aLoadState->IsFormSubmission()); |
8629 | |
8630 | rv = win->Open(spec, |
8631 | aLoadState->Target(), // window name |
8632 | u""_ns, // Features |
8633 | loadState, |
8634 | true, // aForceNoOpener |
8635 | getter_AddRefs(newBC)); |
8636 | MOZ_ASSERT(!newBC)do { static_assert( mozilla::detail::AssertionConditionType< decltype(!newBC)>::isValid, "invalid assertion condition") ; if ((__builtin_expect(!!(!(!!(!newBC))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!newBC", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 8636); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!newBC" ")" ); do { MOZ_CrashSequence(__null, 8636); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
8637 | return rv; |
8638 | } |
8639 | |
8640 | rv = win->OpenNoNavigate(spec, |
8641 | aLoadState->Target(), // window name |
8642 | u""_ns, // Features |
8643 | getter_AddRefs(newBC)); |
8644 | |
8645 | // In some cases the Open call doesn't actually result in a new |
8646 | // window being opened. We can detect these cases by examining the |
8647 | // document in |newBC|, if any. |
8648 | nsCOMPtr<nsPIDOMWindowOuter> piNewWin = |
8649 | newBC ? newBC->GetDOMWindow() : nullptr; |
8650 | if (piNewWin) { |
8651 | RefPtr<Document> newDoc = piNewWin->GetExtantDoc(); |
8652 | if (!newDoc || newDoc->IsInitialDocument()) { |
8653 | aLoadState->SetInternalLoadFlag(INTERNAL_LOAD_FLAGS_FIRST_LOAD); |
8654 | } |
8655 | } |
8656 | |
8657 | if (newBC) { |
8658 | targetContext = newBC; |
8659 | } |
8660 | } |
8661 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 8661); return rv; } } while (false); |
8662 | NS_ENSURE_TRUE(targetContext, rv)do { if ((__builtin_expect(!!(!(targetContext)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "targetContext" ") failed" , nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 8662); return rv; } } while (false); |
8663 | |
8664 | // If our target BrowsingContext is still pending initialization, ignore the |
8665 | // navigation request targeting it. |
8666 | if (NS_WARN_IF(targetContext->GetPendingInitialization())NS_warn_if_impl(targetContext->GetPendingInitialization(), "targetContext->GetPendingInitialization()", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 8666)) { |
8667 | return NS_OK; |
8668 | } |
8669 | |
8670 | aLoadState->SetTargetBrowsingContext(targetContext); |
8671 | if (aLoadState->IsFormSubmission()) { |
8672 | aLoadState->SetLoadType( |
8673 | GetLoadTypeForFormSubmission(targetContext, aLoadState)); |
8674 | } |
8675 | |
8676 | // |
8677 | // Transfer the load to the target BrowsingContext... Clear the window target |
8678 | // name to the empty string to prevent recursive retargeting! |
8679 | // |
8680 | // No window target |
8681 | aLoadState->SetTarget(u""_ns); |
8682 | // No forced download |
8683 | aLoadState->SetFileName(VoidString()); |
8684 | return targetContext->InternalLoad(aLoadState); |
8685 | } |
8686 | |
8687 | static nsAutoCString RefMaybeNull(nsIURI* aURI) { |
8688 | nsAutoCString result; |
8689 | if (NS_FAILED(aURI->GetRef(result))((bool)(__builtin_expect(!!(NS_FAILED_impl(aURI->GetRef(result ))), 0)))) { |
8690 | result.SetIsVoid(true); |
8691 | } |
8692 | return result; |
8693 | } |
8694 | |
8695 | uint32_t nsDocShell::GetSameDocumentNavigationFlags(nsIURI* aNewURI) { |
8696 | uint32_t flags = LOCATION_CHANGE_SAME_DOCUMENT; |
8697 | |
8698 | bool equal = false; |
8699 | if (mCurrentURI && |
8700 | NS_SUCCEEDED(mCurrentURI->EqualsExceptRef(aNewURI, &equal))((bool)(__builtin_expect(!!(!NS_FAILED_impl(mCurrentURI->EqualsExceptRef (aNewURI, &equal))), 1))) && equal && |
8701 | RefMaybeNull(mCurrentURI) != RefMaybeNull(aNewURI)) { |
8702 | flags |= LOCATION_CHANGE_HASHCHANGE; |
8703 | } |
8704 | |
8705 | return flags; |
8706 | } |
8707 | |
8708 | struct SameDocumentNavigationState { |
8709 | nsAutoCString mCurrentHash; |
8710 | nsAutoCString mNewHash; |
8711 | nsTArray<TextDirective> mTextDirectives; |
8712 | bool mCurrentURIHasRef = false; |
8713 | bool mNewURIHasRef = false; |
8714 | bool mSameExceptHashes = false; |
8715 | bool mSecureUpgradeURI = false; |
8716 | bool mHistoryNavBetweenSameDoc = false; |
8717 | }; |
8718 | |
8719 | bool nsDocShell::IsSameDocumentNavigation(nsDocShellLoadState* aLoadState, |
8720 | SameDocumentNavigationState& aState) { |
8721 | MOZ_ASSERT(aLoadState)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aLoadState)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aLoadState))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aLoadState", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 8721); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState" ")"); do { MOZ_CrashSequence(__null, 8721); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
8722 | if (!(aLoadState->LoadType() == LOAD_NORMAL || |
8723 | aLoadState->LoadType() == LOAD_STOP_CONTENT || |
8724 | LOAD_TYPE_HAS_FLAGS(aLoadState->LoadType(),((aLoadState->LoadType()) & ((LOAD_FLAGS_REPLACE_HISTORY ) << 16)) |
8725 | LOAD_FLAGS_REPLACE_HISTORY)((aLoadState->LoadType()) & ((LOAD_FLAGS_REPLACE_HISTORY ) << 16)) || |
8726 | aLoadState->LoadType() == LOAD_HISTORY || |
8727 | aLoadState->LoadType() == LOAD_LINK)) { |
8728 | return false; |
8729 | } |
8730 | |
8731 | nsCOMPtr<nsIURI> currentURI = mCurrentURI; |
8732 | |
8733 | nsresult rvURINew = aLoadState->URI()->GetRef(aState.mNewHash); |
8734 | if (NS_SUCCEEDED(rvURINew)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rvURINew)), 1)))) { |
8735 | rvURINew = aLoadState->URI()->GetHasRef(&aState.mNewURIHasRef); |
8736 | } |
8737 | |
8738 | // A Fragment Directive must be removed from the new hash in order to allow |
8739 | // fallback element id scroll. |
8740 | FragmentDirective::ParseAndRemoveFragmentDirectiveFromFragmentString( |
8741 | aState.mNewHash, &aState.mTextDirectives, aLoadState->URI()); |
8742 | |
8743 | if (currentURI && NS_SUCCEEDED(rvURINew)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rvURINew)), 1)))) { |
8744 | nsresult rvURIOld = currentURI->GetRef(aState.mCurrentHash); |
8745 | if (NS_SUCCEEDED(rvURIOld)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rvURIOld)), 1)))) { |
8746 | rvURIOld = currentURI->GetHasRef(&aState.mCurrentURIHasRef); |
8747 | } |
8748 | if (NS_SUCCEEDED(rvURIOld)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rvURIOld)), 1)))) { |
8749 | if (NS_FAILED(currentURI->EqualsExceptRef(aLoadState->URI(),((bool)(__builtin_expect(!!(NS_FAILED_impl(currentURI->EqualsExceptRef (aLoadState->URI(), &aState.mSameExceptHashes))), 0))) |
8750 | &aState.mSameExceptHashes))((bool)(__builtin_expect(!!(NS_FAILED_impl(currentURI->EqualsExceptRef (aLoadState->URI(), &aState.mSameExceptHashes))), 0)))) { |
8751 | aState.mSameExceptHashes = false; |
8752 | } |
8753 | } |
8754 | } |
8755 | |
8756 | if (!aState.mSameExceptHashes && currentURI && NS_SUCCEEDED(rvURINew)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rvURINew)), 1)))) { |
8757 | // Maybe aLoadState->URI() came from the exposable form of currentURI? |
8758 | nsCOMPtr<nsIURI> currentExposableURI = |
8759 | nsIOService::CreateExposableURI(currentURI); |
8760 | nsresult rvURIOld = currentExposableURI->GetRef(aState.mCurrentHash); |
8761 | if (NS_SUCCEEDED(rvURIOld)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rvURIOld)), 1)))) { |
8762 | rvURIOld = currentExposableURI->GetHasRef(&aState.mCurrentURIHasRef); |
8763 | } |
8764 | if (NS_SUCCEEDED(rvURIOld)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rvURIOld)), 1)))) { |
8765 | if (NS_FAILED(currentExposableURI->EqualsExceptRef(((bool)(__builtin_expect(!!(NS_FAILED_impl(currentExposableURI ->EqualsExceptRef( aLoadState->URI(), &aState.mSameExceptHashes ))), 0))) |
8766 | aLoadState->URI(), &aState.mSameExceptHashes))((bool)(__builtin_expect(!!(NS_FAILED_impl(currentExposableURI ->EqualsExceptRef( aLoadState->URI(), &aState.mSameExceptHashes ))), 0)))) { |
8767 | aState.mSameExceptHashes = false; |
8768 | } |
8769 | // HTTPS-Only Mode upgrades schemes from http to https in Necko, hence we |
8770 | // have to perform a special check here to avoid an actual navigation. If |
8771 | // HTTPS-Only Mode is enabled and the two URIs are same-origin (modulo the |
8772 | // fact that the new URI is currently http), then set mSameExceptHashes to |
8773 | // true and only perform a fragment navigation. |
8774 | if (!aState.mSameExceptHashes) { |
8775 | if (nsCOMPtr<nsIChannel> docChannel = GetCurrentDocChannel()) { |
8776 | nsCOMPtr<nsILoadInfo> docLoadInfo = docChannel->LoadInfo(); |
8777 | nsHTTPSOnlyUtils::UpgradeMode upgradeMode = |
8778 | nsHTTPSOnlyUtils::GetUpgradeMode(docLoadInfo); |
8779 | if (!docLoadInfo->GetLoadErrorPage() && |
8780 | (upgradeMode == nsHTTPSOnlyUtils::HTTPS_ONLY_MODE || |
8781 | upgradeMode == nsHTTPSOnlyUtils::HTTPS_FIRST_MODE) && |
8782 | nsHTTPSOnlyUtils::IsHttpDowngrade(currentExposableURI, |
8783 | aLoadState->URI())) { |
8784 | uint32_t status = docLoadInfo->GetHttpsOnlyStatus(); |
8785 | if ((status & |
8786 | (nsILoadInfo::HTTPS_ONLY_UPGRADED_LISTENER_REGISTERED | |
8787 | nsILoadInfo::HTTPS_ONLY_UPGRADED_HTTPS_FIRST)) && |
8788 | !(status & nsILoadInfo::HTTPS_ONLY_EXEMPT)) { |
8789 | // At this point the requested URI is for sure a fragment |
8790 | // navigation via HTTP and HTTPS-Only mode or HTTPS-First is |
8791 | // enabled. Also it is not interfering the upgrade order of |
8792 | // https://searchfox.org/mozilla-central/source/netwerk/base/nsNetUtil.cpp#2948-2953. |
8793 | // Since we are on an HTTPS site the fragment |
8794 | // navigation should also be an HTTPS. |
8795 | // For that reason we should upgrade the URI to HTTPS. |
8796 | aState.mSecureUpgradeURI = true; |
8797 | aState.mSameExceptHashes = true; |
8798 | } |
8799 | } |
8800 | } |
8801 | } |
8802 | } |
8803 | } |
8804 | |
8805 | if (mozilla::SessionHistoryInParent()) { |
8806 | if (mActiveEntry && aLoadState->LoadIsFromSessionHistory()) { |
8807 | aState.mHistoryNavBetweenSameDoc = mActiveEntry->SharesDocumentWith( |
8808 | aLoadState->GetLoadingSessionHistoryInfo()->mInfo); |
8809 | } |
8810 | MOZ_LOG(gSHLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gSHLog; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "nsDocShell::IsSameDocumentNavigation %p NavBetweenSameDoc=%d" , this, aState.mHistoryNavBetweenSameDoc); } } while (0) |
8811 | ("nsDocShell::IsSameDocumentNavigation %p NavBetweenSameDoc=%d",do { const ::mozilla::LogModule* moz_real_module = gSHLog; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "nsDocShell::IsSameDocumentNavigation %p NavBetweenSameDoc=%d" , this, aState.mHistoryNavBetweenSameDoc); } } while (0) |
8812 | this, aState.mHistoryNavBetweenSameDoc))do { const ::mozilla::LogModule* moz_real_module = gSHLog; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "nsDocShell::IsSameDocumentNavigation %p NavBetweenSameDoc=%d" , this, aState.mHistoryNavBetweenSameDoc); } } while (0); |
8813 | } else { |
8814 | if (mOSHE && aLoadState->LoadIsFromSessionHistory()) { |
8815 | // We're doing a history load. |
8816 | |
8817 | mOSHE->SharesDocumentWith(aLoadState->SHEntry(), |
8818 | &aState.mHistoryNavBetweenSameDoc); |
8819 | } |
8820 | } |
8821 | |
8822 | // A same document navigation happens when we navigate between two SHEntries |
8823 | // for the same document. We do a same document navigation under two |
8824 | // circumstances. Either |
8825 | // |
8826 | // a) we're navigating between two different SHEntries which share a |
8827 | // document, or |
8828 | // |
8829 | // b) we're navigating to a new shentry whose URI differs from the |
8830 | // current URI only in its hash, the new hash is non-empty, and |
8831 | // we're not doing a POST. |
8832 | // |
8833 | // The restriction that the SHEntries in (a) must be different ensures |
8834 | // that history.go(0) and the like trigger full refreshes, rather than |
8835 | // same document navigations. |
8836 | if (!mozilla::SessionHistoryInParent()) { |
8837 | bool doSameDocumentNavigation = |
8838 | (aState.mHistoryNavBetweenSameDoc && mOSHE != aLoadState->SHEntry()) || |
8839 | (!aLoadState->SHEntry() && !aLoadState->PostDataStream() && |
8840 | aState.mSameExceptHashes && aState.mNewURIHasRef); |
8841 | MOZ_LOG(gSHLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gSHLog; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "nsDocShell %p NavBetweenSameDoc=%d is same doc = %d" , this, aState.mHistoryNavBetweenSameDoc, doSameDocumentNavigation ); } } while (0) |
8842 | ("nsDocShell %p NavBetweenSameDoc=%d is same doc = %d", this,do { const ::mozilla::LogModule* moz_real_module = gSHLog; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "nsDocShell %p NavBetweenSameDoc=%d is same doc = %d" , this, aState.mHistoryNavBetweenSameDoc, doSameDocumentNavigation ); } } while (0) |
8843 | aState.mHistoryNavBetweenSameDoc, doSameDocumentNavigation))do { const ::mozilla::LogModule* moz_real_module = gSHLog; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "nsDocShell %p NavBetweenSameDoc=%d is same doc = %d" , this, aState.mHistoryNavBetweenSameDoc, doSameDocumentNavigation ); } } while (0); |
8844 | return doSameDocumentNavigation; |
8845 | } |
8846 | |
8847 | if (aState.mHistoryNavBetweenSameDoc && |
8848 | !aLoadState->GetLoadingSessionHistoryInfo()->mLoadingCurrentEntry) { |
8849 | return true; |
8850 | } |
8851 | |
8852 | MOZ_LOG(do { const ::mozilla::LogModule* moz_real_module = gSHLog; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "nsDocShell::IsSameDocumentNavigation %p !LoadIsFromSessionHistory=%s " "!PostDataStream: %s mSameExceptHashes: %s mNewURIHasRef: %s" , this, !aLoadState->LoadIsFromSessionHistory() ? "true" : "false", !aLoadState->PostDataStream() ? "true" : "false" , aState.mSameExceptHashes ? "true" : "false", aState.mNewURIHasRef ? "true" : "false"); } } while (0) |
8853 | gSHLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gSHLog; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "nsDocShell::IsSameDocumentNavigation %p !LoadIsFromSessionHistory=%s " "!PostDataStream: %s mSameExceptHashes: %s mNewURIHasRef: %s" , this, !aLoadState->LoadIsFromSessionHistory() ? "true" : "false", !aLoadState->PostDataStream() ? "true" : "false" , aState.mSameExceptHashes ? "true" : "false", aState.mNewURIHasRef ? "true" : "false"); } } while (0) |
8854 | ("nsDocShell::IsSameDocumentNavigation %p !LoadIsFromSessionHistory=%s "do { const ::mozilla::LogModule* moz_real_module = gSHLog; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "nsDocShell::IsSameDocumentNavigation %p !LoadIsFromSessionHistory=%s " "!PostDataStream: %s mSameExceptHashes: %s mNewURIHasRef: %s" , this, !aLoadState->LoadIsFromSessionHistory() ? "true" : "false", !aLoadState->PostDataStream() ? "true" : "false" , aState.mSameExceptHashes ? "true" : "false", aState.mNewURIHasRef ? "true" : "false"); } } while (0) |
8855 | "!PostDataStream: %s mSameExceptHashes: %s mNewURIHasRef: %s",do { const ::mozilla::LogModule* moz_real_module = gSHLog; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "nsDocShell::IsSameDocumentNavigation %p !LoadIsFromSessionHistory=%s " "!PostDataStream: %s mSameExceptHashes: %s mNewURIHasRef: %s" , this, !aLoadState->LoadIsFromSessionHistory() ? "true" : "false", !aLoadState->PostDataStream() ? "true" : "false" , aState.mSameExceptHashes ? "true" : "false", aState.mNewURIHasRef ? "true" : "false"); } } while (0) |
8856 | this, !aLoadState->LoadIsFromSessionHistory() ? "true" : "false",do { const ::mozilla::LogModule* moz_real_module = gSHLog; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "nsDocShell::IsSameDocumentNavigation %p !LoadIsFromSessionHistory=%s " "!PostDataStream: %s mSameExceptHashes: %s mNewURIHasRef: %s" , this, !aLoadState->LoadIsFromSessionHistory() ? "true" : "false", !aLoadState->PostDataStream() ? "true" : "false" , aState.mSameExceptHashes ? "true" : "false", aState.mNewURIHasRef ? "true" : "false"); } } while (0) |
8857 | !aLoadState->PostDataStream() ? "true" : "false",do { const ::mozilla::LogModule* moz_real_module = gSHLog; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "nsDocShell::IsSameDocumentNavigation %p !LoadIsFromSessionHistory=%s " "!PostDataStream: %s mSameExceptHashes: %s mNewURIHasRef: %s" , this, !aLoadState->LoadIsFromSessionHistory() ? "true" : "false", !aLoadState->PostDataStream() ? "true" : "false" , aState.mSameExceptHashes ? "true" : "false", aState.mNewURIHasRef ? "true" : "false"); } } while (0) |
8858 | aState.mSameExceptHashes ? "true" : "false",do { const ::mozilla::LogModule* moz_real_module = gSHLog; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "nsDocShell::IsSameDocumentNavigation %p !LoadIsFromSessionHistory=%s " "!PostDataStream: %s mSameExceptHashes: %s mNewURIHasRef: %s" , this, !aLoadState->LoadIsFromSessionHistory() ? "true" : "false", !aLoadState->PostDataStream() ? "true" : "false" , aState.mSameExceptHashes ? "true" : "false", aState.mNewURIHasRef ? "true" : "false"); } } while (0) |
8859 | aState.mNewURIHasRef ? "true" : "false"))do { const ::mozilla::LogModule* moz_real_module = gSHLog; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "nsDocShell::IsSameDocumentNavigation %p !LoadIsFromSessionHistory=%s " "!PostDataStream: %s mSameExceptHashes: %s mNewURIHasRef: %s" , this, !aLoadState->LoadIsFromSessionHistory() ? "true" : "false", !aLoadState->PostDataStream() ? "true" : "false" , aState.mSameExceptHashes ? "true" : "false", aState.mNewURIHasRef ? "true" : "false"); } } while (0); |
8860 | return !aLoadState->LoadIsFromSessionHistory() && |
8861 | !aLoadState->PostDataStream() && aState.mSameExceptHashes && |
8862 | aState.mNewURIHasRef; |
8863 | } |
8864 | |
8865 | static bool IsSamePrincipalForDocumentURI(nsIPrincipal* aCurrentPrincipal, |
8866 | nsIURI* aCurrentURI, |
8867 | nsIURI* aNewURI) { |
8868 | if (!StaticPrefs::dom_security_setdocumenturi()) { |
8869 | return true; |
8870 | } |
8871 | nsCOMPtr<nsIURI> principalURI = aCurrentPrincipal->GetURI(); |
8872 | if (aCurrentPrincipal->GetIsNullPrincipal()) { |
8873 | nsCOMPtr<nsIPrincipal> precursor = |
8874 | aCurrentPrincipal->GetPrecursorPrincipal(); |
8875 | if (precursor) { |
8876 | principalURI = precursor->GetURI(); |
8877 | } |
8878 | } |
8879 | |
8880 | return !nsScriptSecurityManager::IsHttpOrHttpsAndCrossOrigin(principalURI, |
8881 | aNewURI) && |
8882 | !nsScriptSecurityManager::IsHttpOrHttpsAndCrossOrigin(principalURI, |
8883 | aCurrentURI) && |
8884 | !nsScriptSecurityManager::IsHttpOrHttpsAndCrossOrigin(aCurrentURI, |
8885 | aNewURI); |
8886 | } |
8887 | |
8888 | nsresult nsDocShell::HandleSameDocumentNavigation( |
8889 | nsDocShellLoadState* aLoadState, SameDocumentNavigationState& aState, |
8890 | bool& aSameDocument) { |
8891 | aSameDocument = true; |
8892 | #ifdef DEBUG1 |
8893 | SameDocumentNavigationState state; |
8894 | MOZ_ASSERT(IsSameDocumentNavigation(aLoadState, state))do { static_assert( mozilla::detail::AssertionConditionType< decltype(IsSameDocumentNavigation(aLoadState, state))>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(IsSameDocumentNavigation(aLoadState, state)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("IsSameDocumentNavigation(aLoadState, state)" , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 8894); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "IsSameDocumentNavigation(aLoadState, state)" ")"); do { MOZ_CrashSequence(__null, 8894); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
8895 | #endif |
8896 | |
8897 | MOZ_LOG(gSHLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gSHLog; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "nsDocShell::HandleSameDocumentNavigation %p %s -> %s" , this, mCurrentURI->GetSpecOrDefault().get(), aLoadState-> URI()->GetSpecOrDefault().get()); } } while (0) |
8898 | ("nsDocShell::HandleSameDocumentNavigation %p %s -> %s", this,do { const ::mozilla::LogModule* moz_real_module = gSHLog; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "nsDocShell::HandleSameDocumentNavigation %p %s -> %s" , this, mCurrentURI->GetSpecOrDefault().get(), aLoadState-> URI()->GetSpecOrDefault().get()); } } while (0) |
8899 | mCurrentURI->GetSpecOrDefault().get(),do { const ::mozilla::LogModule* moz_real_module = gSHLog; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "nsDocShell::HandleSameDocumentNavigation %p %s -> %s" , this, mCurrentURI->GetSpecOrDefault().get(), aLoadState-> URI()->GetSpecOrDefault().get()); } } while (0) |
8900 | aLoadState->URI()->GetSpecOrDefault().get()))do { const ::mozilla::LogModule* moz_real_module = gSHLog; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "nsDocShell::HandleSameDocumentNavigation %p %s -> %s" , this, mCurrentURI->GetSpecOrDefault().get(), aLoadState-> URI()->GetSpecOrDefault().get()); } } while (0); |
8901 | |
8902 | RefPtr<Document> doc = GetDocument(); |
8903 | NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(doc)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING , "NS_ENSURE_TRUE(" "doc" ") failed", nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 8903); return NS_ERROR_FAILURE; } } while (false); |
8904 | |
8905 | nsCOMPtr<nsIURI> currentURI = mCurrentURI; |
8906 | |
8907 | // We need to upgrade the new URI from http: to https: |
8908 | nsCOMPtr<nsIURI> newURI = aLoadState->URI(); |
8909 | if (aState.mSecureUpgradeURI) { |
8910 | MOZ_TRY(NS_GetSecureUpgradedURI(aLoadState->URI(), getter_AddRefs(newURI)))__extension__({ auto mozTryVarTempResult = ::mozilla::ToResult (NS_GetSecureUpgradedURI(aLoadState->URI(), getter_AddRefs (newURI))); if ((__builtin_expect(!!(mozTryVarTempResult.isErr ()), 0))) { return mozTryVarTempResult.propagateErr(); } mozTryVarTempResult .unwrap(); }); |
8911 | MOZ_LOG(gSHLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gSHLog; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "Upgraded URI to %s", newURI->GetSpecOrDefault ().get()); } } while (0) |
8912 | ("Upgraded URI to %s", newURI->GetSpecOrDefault().get()))do { const ::mozilla::LogModule* moz_real_module = gSHLog; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "Upgraded URI to %s", newURI->GetSpecOrDefault ().get()); } } while (0); |
8913 | } |
8914 | |
8915 | // check if documentPrincipal, mCurrentURI, and aLoadState->URI() are same |
8916 | // origin skip handling otherwise |
8917 | if (!IsSamePrincipalForDocumentURI(doc->NodePrincipal(), mCurrentURI, |
8918 | newURI)) { |
8919 | MOZ_LOG(gSHLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gSHLog; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "nsDocShell[%p]: possible violation of the same origin policy " "during same document navigation", this); } } while (0) |
8920 | ("nsDocShell[%p]: possible violation of the same origin policy "do { const ::mozilla::LogModule* moz_real_module = gSHLog; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "nsDocShell[%p]: possible violation of the same origin policy " "during same document navigation", this); } } while (0) |
8921 | "during same document navigation",do { const ::mozilla::LogModule* moz_real_module = gSHLog; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "nsDocShell[%p]: possible violation of the same origin policy " "during same document navigation", this); } } while (0) |
8922 | this))do { const ::mozilla::LogModule* moz_real_module = gSHLog; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "nsDocShell[%p]: possible violation of the same origin policy " "during same document navigation", this); } } while (0); |
8923 | return NS_OK; |
8924 | } |
8925 | |
8926 | if (nsCOMPtr<nsPIDOMWindowInner> window = doc->GetInnerWindow()) { |
8927 | // https://html.spec.whatwg.org/#navigate-fragid |
8928 | // Step 1 |
8929 | if (RefPtr<Navigation> navigation = window->Navigation()) { |
8930 | // Step 2 |
8931 | RefPtr<nsIStructuredCloneContainer> destinationNavigationAPIState = |
8932 | mActiveEntry ? mActiveEntry->GetNavigationState() : nullptr; |
8933 | // Step 3 |
8934 | if (aLoadState->GetNavigationAPIState()) { |
8935 | destinationNavigationAPIState = aLoadState->GetNavigationAPIState(); |
8936 | } |
8937 | |
8938 | AutoJSAPI jsapi; |
8939 | if (jsapi.Init(window)) { |
8940 | RefPtr<Element> sourceElement = aLoadState->GetSourceElement(); |
8941 | // Step 4 |
8942 | bool shouldContinue = navigation->FirePushReplaceReloadNavigateEvent( |
8943 | jsapi.cx(), aLoadState->GetNavigationType(), newURI, |
8944 | /* aIsSameDocument */ true, /* aIsSync */ true, |
8945 | Some(aLoadState->UserNavigationInvolvement()), sourceElement, |
8946 | /* aFormDataEntryList */ nullptr, |
8947 | /* aNavigationAPIState */ destinationNavigationAPIState, |
8948 | /* aClassicHistoryAPIState */ nullptr); |
8949 | |
8950 | // Step 5 |
8951 | if (!shouldContinue) { |
8952 | return NS_OK; |
8953 | } |
8954 | } |
8955 | } |
8956 | } |
8957 | |
8958 | doc->DoNotifyPossibleTitleChange(); |
8959 | |
8960 | // Store the pending uninvoked directives if it is a same document |
8961 | // navigation. We need to set it here, in case the navigation happens before |
8962 | // the document has actually finished loading. |
8963 | doc->FragmentDirective()->SetTextDirectives( |
8964 | std::move(aState.mTextDirectives)); |
8965 | |
8966 | #ifdef DEBUG1 |
8967 | if (aState.mSameExceptHashes) { |
8968 | bool sameExceptHashes = false; |
8969 | currentURI->EqualsExceptRef(newURI, &sameExceptHashes); |
8970 | MOZ_ASSERT(sameExceptHashes)do { static_assert( mozilla::detail::AssertionConditionType< decltype(sameExceptHashes)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(sameExceptHashes))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("sameExceptHashes" , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 8970); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "sameExceptHashes" ")"); do { MOZ_CrashSequence (__null, 8970); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); |
8971 | } |
8972 | #endif |
8973 | const nsCOMPtr<nsILoadInfo> loadInfo = |
8974 | doc->GetChannel() ? doc->GetChannel()->LoadInfo() : nullptr; |
8975 | if (loadInfo) { |
8976 | loadInfo->SetIsSameDocumentNavigation(true); |
8977 | } |
8978 | // Save the position of the scrollers. |
8979 | nsPoint scrollPos = GetCurScrollPos(); |
8980 | |
8981 | // Reset mLoadType to its original value once we exit this block, because this |
8982 | // same document navigation might have started after a normal, network load, |
8983 | // and we don't want to clobber its load type. See bug 737307. |
8984 | Maybe<AutoRestore<uint32_t>> loadTypeResetter; |
8985 | if (StaticPrefs:: |
8986 | docshell_shistory_sameDocumentNavigationOverridesLoadType() && |
8987 | !doc->NodePrincipal()->IsURIInPrefList( |
8988 | "docshell.shistory.sameDocumentNavigationOverridesLoadType." |
8989 | "forceDisable")) { |
8990 | loadTypeResetter.emplace(mLoadType); |
8991 | } |
8992 | if (JustStartedNetworkLoad() && !loadTypeResetter.isSome()) { |
8993 | loadTypeResetter.emplace(mLoadType); |
8994 | } |
8995 | |
8996 | // If a non-same-document-navigation (i.e., a network load) is pending, make |
8997 | // this a replacement load, so that we don't add a SHEntry here and the |
8998 | // network load goes into the SHEntry it expects to. |
8999 | if (JustStartedNetworkLoad() && (aLoadState->LoadType() & LOAD_CMD_NORMAL)) { |
9000 | mLoadType = LOAD_NORMAL_REPLACE; |
9001 | } else { |
9002 | mLoadType = aLoadState->LoadType(); |
9003 | } |
9004 | |
9005 | mURIResultedInDocument = true; |
9006 | |
9007 | nsCOMPtr<nsISHEntry> oldLSHE = mLSHE; |
9008 | |
9009 | // we need to assign aLoadState->SHEntry() to mLSHE right here, so that on |
9010 | // History loads, SetCurrentURI() called from OnNewURI() will send proper |
9011 | // onLocationChange() notifications to the browser to update back/forward |
9012 | // buttons. |
9013 | SetHistoryEntryAndUpdateBC(Some<nsISHEntry*>(aLoadState->SHEntry()), |
9014 | Nothing()); |
9015 | UniquePtr<mozilla::dom::LoadingSessionHistoryInfo> oldLoadingEntry; |
9016 | mLoadingEntry.swap(oldLoadingEntry); |
9017 | if (aLoadState->GetLoadingSessionHistoryInfo()) { |
9018 | mLoadingEntry = MakeUnique<LoadingSessionHistoryInfo>( |
9019 | *aLoadState->GetLoadingSessionHistoryInfo()); |
9020 | mNeedToReportActiveAfterLoadingBecomesActive = false; |
9021 | } |
9022 | |
9023 | // Set the doc's URI according to the new history entry's URI. |
9024 | doc->SetDocumentURI(newURI); |
9025 | |
9026 | /* This is a anchor traversal within the same page. |
9027 | * call OnNewURI() so that, this traversal will be |
9028 | * recorded in session and global history. |
9029 | */ |
9030 | nsCOMPtr<nsIPrincipal> newURITriggeringPrincipal, newURIPrincipalToInherit, |
9031 | newURIPartitionedPrincipalToInherit; |
9032 | nsCOMPtr<nsIContentSecurityPolicy> newCsp; |
9033 | if (mozilla::SessionHistoryInParent() ? !!mActiveEntry : !!mOSHE) { |
9034 | if (mozilla::SessionHistoryInParent()) { |
9035 | newURITriggeringPrincipal = mActiveEntry->GetTriggeringPrincipal(); |
9036 | newURIPrincipalToInherit = mActiveEntry->GetPrincipalToInherit(); |
9037 | newURIPartitionedPrincipalToInherit = |
9038 | mActiveEntry->GetPartitionedPrincipalToInherit(); |
9039 | newCsp = mActiveEntry->GetCsp(); |
9040 | } else { |
9041 | newURITriggeringPrincipal = mOSHE->GetTriggeringPrincipal(); |
9042 | newURIPrincipalToInherit = mOSHE->GetPrincipalToInherit(); |
9043 | newURIPartitionedPrincipalToInherit = |
9044 | mOSHE->GetPartitionedPrincipalToInherit(); |
9045 | newCsp = mOSHE->GetCsp(); |
9046 | } |
9047 | } else { |
9048 | newURITriggeringPrincipal = aLoadState->TriggeringPrincipal(); |
9049 | newURIPrincipalToInherit = doc->NodePrincipal(); |
9050 | newURIPartitionedPrincipalToInherit = doc->PartitionedPrincipal(); |
9051 | newCsp = doc->GetCsp(); |
9052 | } |
9053 | |
9054 | uint32_t locationChangeFlags = GetSameDocumentNavigationFlags(newURI); |
9055 | |
9056 | // Pass true for aCloneSHChildren, since we're not |
9057 | // changing documents here, so all of our subframes are |
9058 | // still relevant to the new session history entry. |
9059 | // |
9060 | // It also makes OnNewURI(...) set LOCATION_CHANGE_SAME_DOCUMENT |
9061 | // flag on firing onLocationChange(...). |
9062 | // Anyway, aCloneSHChildren param is simply reflecting |
9063 | // doSameDocumentNavigation in this scope. |
9064 | // |
9065 | // Note: we'll actually fire onLocationChange later, in order to preserve |
9066 | // ordering of HistoryCommit() in the parent vs onLocationChange (bug |
9067 | // 1668126) |
9068 | bool locationChangeNeeded = OnNewURI( |
9069 | newURI, nullptr, newURITriggeringPrincipal, newURIPrincipalToInherit, |
9070 | newURIPartitionedPrincipalToInherit, newCsp, true, true); |
9071 | |
9072 | nsCOMPtr<nsIInputStream> postData; |
9073 | nsCOMPtr<nsIReferrerInfo> referrerInfo; |
9074 | uint32_t cacheKey = 0; |
9075 | |
9076 | bool scrollRestorationIsManual = false; |
9077 | if (!mozilla::SessionHistoryInParent()) { |
9078 | if (mOSHE) { |
9079 | /* save current position of scroller(s) (bug 59774) */ |
9080 | mOSHE->SetScrollPosition(scrollPos.x, scrollPos.y); |
9081 | scrollRestorationIsManual = mOSHE->GetScrollRestorationIsManual(); |
9082 | // Get the postdata, page ident and referrer info from the current page, |
9083 | // if the new load is being done via normal means. Note that "normal |
9084 | // means" can be checked for just by checking for LOAD_CMD_NORMAL, given |
9085 | // the loadType and allowScroll check above -- it filters out some |
9086 | // LOAD_CMD_NORMAL cases that we wouldn't want here. |
9087 | if (aLoadState->LoadType() & LOAD_CMD_NORMAL) { |
9088 | postData = mOSHE->GetPostData(); |
9089 | cacheKey = mOSHE->GetCacheKey(); |
9090 | referrerInfo = mOSHE->GetReferrerInfo(); |
9091 | } |
9092 | |
9093 | // Link our new SHEntry to the old SHEntry's back/forward |
9094 | // cache data, since the two SHEntries correspond to the |
9095 | // same document. |
9096 | if (mLSHE) { |
9097 | if (!aLoadState->LoadIsFromSessionHistory()) { |
9098 | // If we're not doing a history load, scroll restoration |
9099 | // should be inherited from the previous session history entry. |
9100 | SetScrollRestorationIsManualOnHistoryEntry(mLSHE, |
9101 | scrollRestorationIsManual); |
9102 | } |
9103 | mLSHE->AdoptBFCacheEntry(mOSHE); |
9104 | } |
9105 | } |
9106 | } else { |
9107 | if (mActiveEntry) { |
9108 | mActiveEntry->SetScrollPosition(scrollPos.x, scrollPos.y); |
9109 | if (mBrowsingContext) { |
9110 | CollectWireframe(); |
9111 | if (XRE_IsParentProcess()) { |
9112 | SessionHistoryEntry* entry = |
9113 | mBrowsingContext->Canonical()->GetActiveSessionHistoryEntry(); |
9114 | if (entry) { |
9115 | entry->SetScrollPosition(scrollPos.x, scrollPos.y); |
9116 | } |
9117 | } else { |
9118 | mozilla::Unused << ContentChild::GetSingleton() |
9119 | ->SendSessionHistoryEntryScrollPosition( |
9120 | mBrowsingContext, scrollPos.x, |
9121 | scrollPos.y); |
9122 | } |
9123 | } |
9124 | } |
9125 | if (mLoadingEntry) { |
9126 | if (!mLoadingEntry->mLoadIsFromSessionHistory) { |
9127 | // If we're not doing a history load, scroll restoration |
9128 | // should be inherited from the previous session history entry. |
9129 | // XXX This needs most probably tweaks once fragment navigation is |
9130 | // fixed to work with session-history-in-parent. |
9131 | SetScrollRestorationIsManualOnHistoryEntry(nullptr, |
9132 | scrollRestorationIsManual); |
9133 | } |
9134 | } |
9135 | } |
9136 | |
9137 | // If we're doing a history load, use its scroll restoration state. |
9138 | if (aLoadState->LoadIsFromSessionHistory()) { |
9139 | if (mozilla::SessionHistoryInParent()) { |
9140 | scrollRestorationIsManual = aLoadState->GetLoadingSessionHistoryInfo() |
9141 | ->mInfo.GetScrollRestorationIsManual(); |
9142 | } else { |
9143 | scrollRestorationIsManual = |
9144 | aLoadState->SHEntry()->GetScrollRestorationIsManual(); |
9145 | } |
9146 | } |
9147 | |
9148 | /* Assign mLSHE to mOSHE. This will either be a new entry created |
9149 | * by OnNewURI() for normal loads or aLoadState->SHEntry() for history |
9150 | * loads. |
9151 | */ |
9152 | if (!mozilla::SessionHistoryInParent()) { |
9153 | if (mLSHE) { |
9154 | SetHistoryEntryAndUpdateBC(Nothing(), Some<nsISHEntry*>(mLSHE)); |
9155 | // Save the postData obtained from the previous page |
9156 | // in to the session history entry created for the |
9157 | // anchor page, so that any history load of the anchor |
9158 | // page will restore the appropriate postData. |
9159 | if (postData) { |
9160 | mOSHE->SetPostData(postData); |
9161 | } |
9162 | |
9163 | // Make sure we won't just repost without hitting the |
9164 | // cache first |
9165 | if (cacheKey != 0) { |
9166 | mOSHE->SetCacheKey(cacheKey); |
9167 | } |
9168 | |
9169 | // As the document has not changed, the referrer info hasn't changed too, |
9170 | // so we can just copy it over. |
9171 | if (referrerInfo) { |
9172 | mOSHE->SetReferrerInfo(referrerInfo); |
9173 | } |
9174 | } |
9175 | |
9176 | /* Set the title for the SH entry for this target url so that |
9177 | * SH menus in go/back/forward buttons won't be empty for this. |
9178 | * Note, this happens on mOSHE (and mActiveEntry in the future) because of |
9179 | * the code above. |
9180 | * Note, when session history lives in the parent process, this does not |
9181 | * update the title there. |
9182 | */ |
9183 | SetTitleOnHistoryEntry(false); |
9184 | } else { |
9185 | if (aLoadState->LoadIsFromSessionHistory()) { |
9186 | MOZ_LOG(do { const ::mozilla::LogModule* moz_real_module = gSHLog; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "Moving the loading entry to the active entry on nsDocShell %p to " "%s", this, mLoadingEntry->mInfo.GetURI()->GetSpecOrDefault ().get()); } } while (0) |
9187 | gSHLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gSHLog; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "Moving the loading entry to the active entry on nsDocShell %p to " "%s", this, mLoadingEntry->mInfo.GetURI()->GetSpecOrDefault ().get()); } } while (0) |
9188 | ("Moving the loading entry to the active entry on nsDocShell %p to "do { const ::mozilla::LogModule* moz_real_module = gSHLog; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "Moving the loading entry to the active entry on nsDocShell %p to " "%s", this, mLoadingEntry->mInfo.GetURI()->GetSpecOrDefault ().get()); } } while (0) |
9189 | "%s",do { const ::mozilla::LogModule* moz_real_module = gSHLog; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "Moving the loading entry to the active entry on nsDocShell %p to " "%s", this, mLoadingEntry->mInfo.GetURI()->GetSpecOrDefault ().get()); } } while (0) |
9190 | this, mLoadingEntry->mInfo.GetURI()->GetSpecOrDefault().get()))do { const ::mozilla::LogModule* moz_real_module = gSHLog; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "Moving the loading entry to the active entry on nsDocShell %p to " "%s", this, mLoadingEntry->mInfo.GetURI()->GetSpecOrDefault ().get()); } } while (0); |
9191 | |
9192 | nsCOMPtr<nsILayoutHistoryState> currentLayoutHistoryState; |
9193 | if (mActiveEntry) { |
9194 | currentLayoutHistoryState = mActiveEntry->GetLayoutHistoryState(); |
9195 | } |
9196 | |
9197 | UniquePtr<SessionHistoryInfo> previousActiveEntry(mActiveEntry.release()); |
9198 | mActiveEntry = MakeUnique<SessionHistoryInfo>(mLoadingEntry->mInfo); |
9199 | if (currentLayoutHistoryState) { |
9200 | // Restore the existing nsILayoutHistoryState object, since it is |
9201 | // possibly being used by the layout. When doing a new load, the |
9202 | // shared state is copied from the existing active entry, so this |
9203 | // special case is needed only with the history loads. |
9204 | mActiveEntry->SetLayoutHistoryState(currentLayoutHistoryState); |
9205 | } |
9206 | |
9207 | if (cacheKey != 0) { |
9208 | mActiveEntry->SetCacheKey(cacheKey); |
9209 | } |
9210 | |
9211 | mActiveEntry->SetPartitionedPrincipalToInherit( |
9212 | doc->PartitionedPrincipal()); |
9213 | // We're passing in mCurrentURI, which could be null. SessionHistoryCommit |
9214 | // does require a non-null uri if this is for a refresh load of the same |
9215 | // URI, but in that case mCurrentURI won't be null here. |
9216 | mBrowsingContext->SessionHistoryCommit( |
9217 | *mLoadingEntry, mLoadType, mCurrentURI, previousActiveEntry.get(), |
9218 | true, |
9219 | /* No expiration update on the same document loads*/ |
9220 | false, cacheKey, doc->PartitionedPrincipal()); |
9221 | // FIXME Need to set postdata. |
9222 | |
9223 | // Set the title for the SH entry for this target url so that |
9224 | // SH menus in go/back/forward buttons won't be empty for this. |
9225 | // Note, when session history lives in the parent process, this does not |
9226 | // update the title there. |
9227 | SetTitleOnHistoryEntry(false); |
9228 | } else { |
9229 | Maybe<bool> scrollRestorationIsManual; |
9230 | if (mActiveEntry) { |
9231 | scrollRestorationIsManual.emplace( |
9232 | mActiveEntry->GetScrollRestorationIsManual()); |
9233 | |
9234 | // Get the postdata, page ident and referrer info from the current page, |
9235 | // if the new load is being done via normal means. Note that "normal |
9236 | // means" can be checked for just by checking for LOAD_CMD_NORMAL, given |
9237 | // the loadType and allowScroll check above -- it filters out some |
9238 | // LOAD_CMD_NORMAL cases that we wouldn't want here. |
9239 | if (aLoadState->LoadType() & LOAD_CMD_NORMAL) { |
9240 | postData = mActiveEntry->GetPostData(); |
9241 | cacheKey = mActiveEntry->GetCacheKey(); |
9242 | referrerInfo = mActiveEntry->GetReferrerInfo(); |
9243 | } |
9244 | } |
9245 | |
9246 | MOZ_LOG(gSHLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gSHLog; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "Creating an active entry on nsDocShell %p to %s" , this, newURI->GetSpecOrDefault().get()); } } while (0) |
9247 | ("Creating an active entry on nsDocShell %p to %s", this,do { const ::mozilla::LogModule* moz_real_module = gSHLog; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "Creating an active entry on nsDocShell %p to %s" , this, newURI->GetSpecOrDefault().get()); } } while (0) |
9248 | newURI->GetSpecOrDefault().get()))do { const ::mozilla::LogModule* moz_real_module = gSHLog; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "Creating an active entry on nsDocShell %p to %s" , this, newURI->GetSpecOrDefault().get()); } } while (0); |
9249 | UniquePtr<SessionHistoryInfo> previousActiveEntry(mActiveEntry.release()); |
9250 | if (previousActiveEntry) { |
9251 | mActiveEntry = |
9252 | MakeUnique<SessionHistoryInfo>(*previousActiveEntry, newURI); |
9253 | } else { |
9254 | mActiveEntry = MakeUnique<SessionHistoryInfo>( |
9255 | newURI, newURITriggeringPrincipal, newURIPrincipalToInherit, |
9256 | newURIPartitionedPrincipalToInherit, newCsp, mContentTypeHint); |
9257 | } |
9258 | |
9259 | // Save the postData obtained from the previous page in to the session |
9260 | // history entry created for the anchor page, so that any history load of |
9261 | // the anchor page will restore the appropriate postData. |
9262 | if (postData) { |
9263 | mActiveEntry->SetPostData(postData); |
9264 | } |
9265 | |
9266 | // Make sure we won't just repost without hitting the |
9267 | // cache first |
9268 | if (cacheKey != 0) { |
9269 | mActiveEntry->SetCacheKey(cacheKey); |
9270 | } |
9271 | |
9272 | // As the document has not changed, the referrer info hasn't changed too, |
9273 | // so we can just copy it over. |
9274 | if (referrerInfo) { |
9275 | mActiveEntry->SetReferrerInfo(referrerInfo); |
9276 | } |
9277 | |
9278 | // Set the title for the SH entry for this target url so that |
9279 | // SH menus in go/back/forward buttons won't be empty for this. |
9280 | mActiveEntry->SetTitle(mTitle); |
9281 | |
9282 | mActiveEntry->SetPartitionedPrincipalToInherit( |
9283 | doc->PartitionedPrincipal()); |
9284 | |
9285 | if (scrollRestorationIsManual.isSome()) { |
9286 | mActiveEntry->SetScrollRestorationIsManual( |
9287 | scrollRestorationIsManual.value()); |
9288 | } |
9289 | |
9290 | if (LOAD_TYPE_HAS_FLAGS(mLoadType, LOAD_FLAGS_REPLACE_HISTORY)((mLoadType) & ((LOAD_FLAGS_REPLACE_HISTORY) << 16) )) { |
9291 | mBrowsingContext->ReplaceActiveSessionHistoryEntry(mActiveEntry.get()); |
9292 | } else { |
9293 | mBrowsingContext->IncrementHistoryEntryCountForBrowsingContext(); |
9294 | // FIXME We should probably just compute mChildOffset in the parent |
9295 | // instead of passing it over IPC here. |
9296 | mBrowsingContext->SetActiveSessionHistoryEntry( |
9297 | Some(scrollPos), mActiveEntry.get(), previousActiveEntry.get(), |
9298 | mLoadType, cacheKey); |
9299 | // FIXME Do we need to update mPreviousEntryIndex and mLoadedEntryIndex? |
9300 | } |
9301 | } |
9302 | } |
9303 | |
9304 | if (locationChangeNeeded) { |
9305 | FireOnLocationChange(this, nullptr, newURI, locationChangeFlags); |
9306 | } |
9307 | |
9308 | /* Restore the original LSHE if we were loading something |
9309 | * while same document navigation was initiated. |
9310 | */ |
9311 | SetHistoryEntryAndUpdateBC(Some<nsISHEntry*>(oldLSHE), Nothing()); |
9312 | mLoadingEntry.swap(oldLoadingEntry); |
9313 | |
9314 | /* Set the title for the Global History entry for this anchor url. |
9315 | */ |
9316 | UpdateGlobalHistoryTitle(newURI); |
9317 | |
9318 | SetDocCurrentStateObj(mOSHE, mActiveEntry.get()); |
9319 | |
9320 | // Inform the favicon service that the favicon for oldURI also |
9321 | // applies to newURI. |
9322 | CopyFavicon(currentURI, newURI, UsePrivateBrowsing()); |
9323 | |
9324 | RefPtr<nsGlobalWindowOuter> scriptGlobal = mScriptGlobal; |
9325 | nsCOMPtr<nsPIDOMWindowInner> win = |
9326 | scriptGlobal ? scriptGlobal->GetCurrentInnerWindow() : nullptr; |
9327 | |
9328 | // The check for uninvoked directives must come before ScrollToAnchor() is |
9329 | // called. |
9330 | const bool hasTextDirectives = |
9331 | doc->FragmentDirective()->HasUninvokedDirectives(); |
9332 | |
9333 | // ScrollToAnchor doesn't necessarily cause us to scroll the window; |
9334 | // the function decides whether a scroll is appropriate based on the |
9335 | // arguments it receives. But even if we don't end up scrolling, |
9336 | // ScrollToAnchor performs other important tasks, such as informing |
9337 | // the presShell that we have a new hash. See bug 680257. |
9338 | nsresult rv = ScrollToAnchor(aState.mCurrentURIHasRef, aState.mNewURIHasRef, |
9339 | aState.mNewHash, aLoadState->LoadType()); |
9340 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 9340); return rv; } } while (false); |
9341 | |
9342 | /* restore previous position of scroller(s), if we're moving |
9343 | * back in history (bug 59774) |
9344 | */ |
9345 | nscoord bx = 0; |
9346 | nscoord by = 0; |
9347 | bool needsScrollPosUpdate = false; |
9348 | if ((mozilla::SessionHistoryInParent() ? !!mActiveEntry : !!mOSHE) && |
9349 | (aLoadState->LoadType() == LOAD_HISTORY || |
9350 | aLoadState->LoadType() == LOAD_RELOAD_NORMAL) && |
9351 | !scrollRestorationIsManual) { |
9352 | needsScrollPosUpdate = true; |
9353 | if (mozilla::SessionHistoryInParent()) { |
9354 | mActiveEntry->GetScrollPosition(&bx, &by); |
9355 | } else { |
9356 | mOSHE->GetScrollPosition(&bx, &by); |
9357 | } |
9358 | } |
9359 | |
9360 | // Dispatch the popstate and hashchange events, as appropriate. |
9361 | // |
9362 | // The event dispatch below can cause us to re-enter script and |
9363 | // destroy the docshell, nulling out mScriptGlobal. Hold a stack |
9364 | // reference to avoid null derefs. See bug 914521. |
9365 | if (win) { |
9366 | if (RefPtr navigation = win->Navigation()) { |
9367 | MOZ_LOG(gNavigationLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gNavigationLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "nsDocShell %p triggering a navigation event from " "HandleSameDocumentNavigation", this); } } while (0) |
9368 | ("nsDocShell %p triggering a navigation event from "do { const ::mozilla::LogModule* moz_real_module = gNavigationLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "nsDocShell %p triggering a navigation event from " "HandleSameDocumentNavigation", this); } } while (0) |
9369 | "HandleSameDocumentNavigation",do { const ::mozilla::LogModule* moz_real_module = gNavigationLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "nsDocShell %p triggering a navigation event from " "HandleSameDocumentNavigation", this); } } while (0) |
9370 | this))do { const ::mozilla::LogModule* moz_real_module = gNavigationLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "nsDocShell %p triggering a navigation event from " "HandleSameDocumentNavigation", this); } } while (0); |
9371 | // Corresponds to step 6.4.2 from the Updating the document algorithm: |
9372 | // https://html.spec.whatwg.org/multipage/browsing-the-web.html#updating-the-document |
9373 | navigation->UpdateEntriesForSameDocumentNavigation( |
9374 | mActiveEntry.get(), |
9375 | LOAD_TYPE_HAS_FLAGS(mLoadType, LOAD_FLAGS_REPLACE_HISTORY)((mLoadType) & ((LOAD_FLAGS_REPLACE_HISTORY) << 16) ) |
9376 | ? NavigationType::Replace |
9377 | : aLoadState->LoadIsFromSessionHistory() ? NavigationType::Traverse |
9378 | : NavigationType::Push); |
9379 | } |
9380 | |
9381 | // Fire a hashchange event URIs differ, and only in their hashes. |
9382 | // If the fragment contains a directive, compare hasRef. |
9383 | bool doHashchange = aState.mSameExceptHashes && |
9384 | (!aState.mCurrentHash.Equals(aState.mNewHash) || |
9385 | (hasTextDirectives && |
9386 | aState.mCurrentURIHasRef != aState.mNewURIHasRef)); |
9387 | |
9388 | if (aState.mHistoryNavBetweenSameDoc || doHashchange) { |
9389 | win->DispatchSyncPopState(); |
9390 | } |
9391 | |
9392 | if (needsScrollPosUpdate && win->HasActiveDocument()) { |
9393 | SetCurScrollPosEx(bx, by); |
9394 | } |
9395 | |
9396 | if (doHashchange) { |
9397 | // Note that currentURI hasn't changed because it's on the |
9398 | // stack, so we can just use it directly as the old URI. |
9399 | win->DispatchAsyncHashchange(currentURI, newURI); |
9400 | } |
9401 | } |
9402 | |
9403 | return NS_OK; |
9404 | } |
9405 | |
9406 | static bool NavigationShouldTakeFocus(nsDocShell* aDocShell, |
9407 | nsDocShellLoadState* aLoadState) { |
9408 | if (!aLoadState->AllowFocusMove()) { |
9409 | return false; |
9410 | } |
9411 | if (!aLoadState->HasValidUserGestureActivation()) { |
9412 | return false; |
9413 | } |
9414 | const auto& sourceBC = aLoadState->SourceBrowsingContext(); |
9415 | if (!sourceBC || !sourceBC->IsActive()) { |
9416 | // If the navigation didn't come from a foreground tab, then we don't steal |
9417 | // focus. |
9418 | return false; |
9419 | } |
9420 | auto* bc = aDocShell->GetBrowsingContext(); |
9421 | if (sourceBC.get() == bc) { |
9422 | // If it comes from the same tab / frame, don't steal focus either. |
9423 | return false; |
9424 | } |
9425 | auto* fm = nsFocusManager::GetFocusManager(); |
9426 | if (fm && bc->IsActive() && fm->IsInActiveWindow(bc)) { |
9427 | // If we're already on the foreground tab of the foreground window, then we |
9428 | // don't need to do this. This helps to e.g. not steal focus from the |
9429 | // browser chrome unnecessarily. |
9430 | return false; |
9431 | } |
9432 | if (auto* doc = aDocShell->GetExtantDocument()) { |
9433 | if (doc->IsInitialDocument()) { |
9434 | // If we're the initial load for the browsing context, the browser |
9435 | // chrome determines what to focus. This is important because the |
9436 | // browser chrome may want to e.g focus the url-bar |
9437 | return false; |
9438 | } |
9439 | } |
9440 | // Take loadDivertedInBackground into account so the behavior would be the |
9441 | // same as how the tab first opened. |
9442 | return !Preferences::GetBool("browser.tabs.loadDivertedInBackground", false); |
9443 | } |
9444 | |
9445 | uint32_t nsDocShell::GetLoadTypeForFormSubmission( |
9446 | BrowsingContext* aTargetBC, nsDocShellLoadState* aLoadState) { |
9447 | MOZ_ASSERT(aLoadState->IsFormSubmission())do { static_assert( mozilla::detail::AssertionConditionType< decltype(aLoadState->IsFormSubmission())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aLoadState->IsFormSubmission ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("aLoadState->IsFormSubmission()", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 9447); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->IsFormSubmission()" ")"); do { MOZ_CrashSequence(__null, 9447); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
9448 | |
9449 | // https://html.spec.whatwg.org/#form-submission-algorithm |
9450 | // 22. Let historyHandling be "push". |
9451 | // 23. If form document equals targetNavigable's active document, and |
9452 | // form document has not yet completely loaded, then set |
9453 | // historyHandling to "replace". |
9454 | return GetBrowsingContext() == aTargetBC && !mEODForCurrentDocument |
9455 | ? LOAD_NORMAL_REPLACE |
9456 | : LOAD_LINK; |
9457 | } |
9458 | |
9459 | // InternalLoad performs several of the steps from |
9460 | // https://html.spec.whatwg.org/#navigate. |
9461 | nsresult nsDocShell::InternalLoad(nsDocShellLoadState* aLoadState, |
9462 | Maybe<uint32_t> aCacheKey) { |
9463 | MOZ_ASSERT(aLoadState, "need a load state!")do { static_assert( mozilla::detail::AssertionConditionType< decltype(aLoadState)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aLoadState))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aLoadState" " (" "need a load state!" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 9463 ); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState" ") (" "need a load state!" ")"); do { MOZ_CrashSequence(__null, 9463 ); __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
9464 | MOZ_ASSERT(aLoadState->TriggeringPrincipal(),do { static_assert( mozilla::detail::AssertionConditionType< decltype(aLoadState->TriggeringPrincipal())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aLoadState->TriggeringPrincipal ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("aLoadState->TriggeringPrincipal()" " (" "need a valid TriggeringPrincipal" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 9465 ); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->TriggeringPrincipal()" ") (" "need a valid TriggeringPrincipal" ")"); do { MOZ_CrashSequence (__null, 9465); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false) |
9465 | "need a valid TriggeringPrincipal")do { static_assert( mozilla::detail::AssertionConditionType< decltype(aLoadState->TriggeringPrincipal())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aLoadState->TriggeringPrincipal ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("aLoadState->TriggeringPrincipal()" " (" "need a valid TriggeringPrincipal" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 9465 ); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->TriggeringPrincipal()" ") (" "need a valid TriggeringPrincipal" ")"); do { MOZ_CrashSequence (__null, 9465); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); |
9466 | |
9467 | if (!aLoadState->TriggeringPrincipal()) { |
9468 | MOZ_ASSERT(false, "InternalLoad needs a valid triggeringPrincipal")do { static_assert( mozilla::detail::AssertionConditionType< decltype(false)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("false" " (" "InternalLoad needs a valid triggeringPrincipal" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 9468 ); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "InternalLoad needs a valid triggeringPrincipal" ")"); do { MOZ_CrashSequence(__null, 9468); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
9469 | return NS_ERROR_FAILURE; |
9470 | } |
9471 | if (NS_WARN_IF(mBrowsingContext->GetPendingInitialization())NS_warn_if_impl(mBrowsingContext->GetPendingInitialization (), "mBrowsingContext->GetPendingInitialization()", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 9471)) { |
9472 | return NS_ERROR_NOT_AVAILABLE; |
9473 | } |
9474 | |
9475 | const bool shouldTakeFocus = NavigationShouldTakeFocus(this, aLoadState); |
9476 | |
9477 | mOriginalUriString.Truncate(); |
9478 | |
9479 | MOZ_LOG(gDocShellLeakLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gDocShellLeakLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "DOCSHELL %p InternalLoad %s\n", this, aLoadState ->URI()->GetSpecOrDefault().get()); } } while (0) |
9480 | ("DOCSHELL %p InternalLoad %s\n", this,do { const ::mozilla::LogModule* moz_real_module = gDocShellLeakLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "DOCSHELL %p InternalLoad %s\n", this, aLoadState ->URI()->GetSpecOrDefault().get()); } } while (0) |
9481 | aLoadState->URI()->GetSpecOrDefault().get()))do { const ::mozilla::LogModule* moz_real_module = gDocShellLeakLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "DOCSHELL %p InternalLoad %s\n", this, aLoadState ->URI()->GetSpecOrDefault().get()); } } while (0); |
9482 | |
9483 | NS_ENSURE_TRUE(IsValidLoadType(aLoadState->LoadType()), NS_ERROR_INVALID_ARG)do { if ((__builtin_expect(!!(!(IsValidLoadType(aLoadState-> LoadType()))), 0))) { NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "IsValidLoadType(aLoadState->LoadType())" ") failed", nullptr , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 9483); return NS_ERROR_INVALID_ARG; } } while (false); |
9484 | |
9485 | // Cancel loads coming from Docshells that are being destroyed. |
9486 | if (mIsBeingDestroyed) { |
9487 | return NS_ERROR_NOT_AVAILABLE; |
9488 | } |
9489 | |
9490 | nsresult rv = EnsureScriptEnvironment(); |
9491 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
9492 | return rv; |
9493 | } |
9494 | |
9495 | // If we have a target to move to, do that now. |
9496 | if (!aLoadState->Target().IsEmpty()) { |
9497 | return PerformRetargeting(aLoadState); |
9498 | } |
9499 | |
9500 | // This is the non-retargeting load path, we've already set the right loadtype |
9501 | // for form submissions in nsDocShell::OnLinkClickSync. |
9502 | if (aLoadState->TargetBrowsingContext().IsNull()) { |
9503 | aLoadState->SetTargetBrowsingContext(GetBrowsingContext()); |
9504 | } |
9505 | |
9506 | MOZ_DIAGNOSTIC_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType< decltype(aLoadState->TargetBrowsingContext() == GetBrowsingContext ())>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(aLoadState->TargetBrowsingContext() == GetBrowsingContext ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("aLoadState->TargetBrowsingContext() == GetBrowsingContext()" " (" "Load must be targeting this BrowsingContext" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 9508); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "aLoadState->TargetBrowsingContext() == GetBrowsingContext()" ") (" "Load must be targeting this BrowsingContext" ")"); do { MOZ_CrashSequence(__null, 9508); __attribute__((nomerge)) :: abort(); } while (false); } } while (false) |
9507 | aLoadState->TargetBrowsingContext() == GetBrowsingContext(),do { static_assert( mozilla::detail::AssertionConditionType< decltype(aLoadState->TargetBrowsingContext() == GetBrowsingContext ())>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(aLoadState->TargetBrowsingContext() == GetBrowsingContext ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("aLoadState->TargetBrowsingContext() == GetBrowsingContext()" " (" "Load must be targeting this BrowsingContext" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 9508); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "aLoadState->TargetBrowsingContext() == GetBrowsingContext()" ") (" "Load must be targeting this BrowsingContext" ")"); do { MOZ_CrashSequence(__null, 9508); __attribute__((nomerge)) :: abort(); } while (false); } } while (false) |
9508 | "Load must be targeting this BrowsingContext")do { static_assert( mozilla::detail::AssertionConditionType< decltype(aLoadState->TargetBrowsingContext() == GetBrowsingContext ())>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(aLoadState->TargetBrowsingContext() == GetBrowsingContext ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("aLoadState->TargetBrowsingContext() == GetBrowsingContext()" " (" "Load must be targeting this BrowsingContext" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 9508); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "aLoadState->TargetBrowsingContext() == GetBrowsingContext()" ") (" "Load must be targeting this BrowsingContext" ")"); do { MOZ_CrashSequence(__null, 9508); __attribute__((nomerge)) :: abort(); } while (false); } } while (false); |
9509 | |
9510 | MOZ_TRY(CheckDisallowedJavascriptLoad(aLoadState))__extension__({ auto mozTryVarTempResult = ::mozilla::ToResult (CheckDisallowedJavascriptLoad(aLoadState)); if ((__builtin_expect (!!(mozTryVarTempResult.isErr()), 0))) { return mozTryVarTempResult .propagateErr(); } mozTryVarTempResult.unwrap(); }); |
9511 | |
9512 | // If we don't have a target, we're loading into ourselves, and our load |
9513 | // delegate may want to intercept that load. |
9514 | SameDocumentNavigationState sameDocumentNavigationState; |
9515 | bool sameDocument = |
9516 | IsSameDocumentNavigation(aLoadState, sameDocumentNavigationState) && |
9517 | !aLoadState->GetPendingRedirectedChannel(); |
9518 | |
9519 | // Note: We do this check both here and in BrowsingContext:: |
9520 | // LoadURI/InternalLoad, since document-specific sandbox flags are only |
9521 | // available in the process triggering the load, and we don't want the target |
9522 | // process to have to trust the triggering process to do the appropriate |
9523 | // checks for the BrowsingContext's sandbox flags. |
9524 | MOZ_TRY(mBrowsingContext->CheckSandboxFlags(aLoadState))__extension__({ auto mozTryVarTempResult = ::mozilla::ToResult (mBrowsingContext->CheckSandboxFlags(aLoadState)); if ((__builtin_expect (!!(mozTryVarTempResult.isErr()), 0))) { return mozTryVarTempResult .propagateErr(); } mozTryVarTempResult.unwrap(); }); |
9525 | |
9526 | NS_ENSURE_STATE(!HasUnloadedParent())do { if ((__builtin_expect(!!(!(!HasUnloadedParent())), 0))) { NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "!HasUnloadedParent()" ") failed", nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 9526); return NS_ERROR_UNEXPECTED; } } while (false); |
9527 | |
9528 | rv = CheckLoadingPermissions(); |
9529 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
9530 | return rv; |
9531 | } |
9532 | |
9533 | if (mFiredUnloadEvent) { |
9534 | if (IsOKToLoadURI(aLoadState->URI())) { |
9535 | MOZ_ASSERT(aLoadState->Target().IsEmpty(),do { static_assert( mozilla::detail::AssertionConditionType< decltype(aLoadState->Target().IsEmpty())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aLoadState->Target().IsEmpty ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("aLoadState->Target().IsEmpty()" " (" "Shouldn't have a window target here!" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 9536 ); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->Target().IsEmpty()" ") (" "Shouldn't have a window target here!" ")"); do { MOZ_CrashSequence (__null, 9536); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false) |
9536 | "Shouldn't have a window target here!")do { static_assert( mozilla::detail::AssertionConditionType< decltype(aLoadState->Target().IsEmpty())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aLoadState->Target().IsEmpty ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("aLoadState->Target().IsEmpty()" " (" "Shouldn't have a window target here!" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 9536 ); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->Target().IsEmpty()" ") (" "Shouldn't have a window target here!" ")"); do { MOZ_CrashSequence (__null, 9536); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); |
9537 | |
9538 | // If this is a replace load, make whatever load triggered |
9539 | // the unload event also a replace load, so we don't |
9540 | // create extra history entries. |
9541 | if (LOAD_TYPE_HAS_FLAGS(aLoadState->LoadType(),((aLoadState->LoadType()) & ((LOAD_FLAGS_REPLACE_HISTORY ) << 16)) |
9542 | LOAD_FLAGS_REPLACE_HISTORY)((aLoadState->LoadType()) & ((LOAD_FLAGS_REPLACE_HISTORY ) << 16))) { |
9543 | mLoadType = LOAD_NORMAL_REPLACE; |
9544 | } |
9545 | |
9546 | // Do this asynchronously |
9547 | nsCOMPtr<nsIRunnable> ev = new InternalLoadEvent(this, aLoadState); |
9548 | return Dispatch(ev.forget()); |
9549 | } |
9550 | |
9551 | // Just ignore this load attempt |
9552 | return NS_OK; |
9553 | } |
9554 | |
9555 | // If we are loading a URI that should inherit a security context (basically |
9556 | // javascript: at this point), and the caller has said that principal |
9557 | // inheritance is allowed, there are a few possible cases: |
9558 | // |
9559 | // 1) We are provided with the principal to inherit. In that case, we just use |
9560 | // it. |
9561 | // |
9562 | // 2) The load is coming from some other application. In this case we don't |
9563 | // want to inherit from whatever document we have loaded now, since the |
9564 | // load is unrelated to it. |
9565 | // |
9566 | // 3) It's a load from our application, but does not provide an explicit |
9567 | // principal to inherit. In that case, we want to inherit the principal of |
9568 | // our current document, or of our parent document (if any) if we don't |
9569 | // have a current document. |
9570 | { |
9571 | bool inherits; |
9572 | |
9573 | if (!aLoadState->HasLoadFlags(LOAD_FLAGS_FROM_EXTERNAL) && |
9574 | !aLoadState->PrincipalToInherit() && |
9575 | (aLoadState->HasInternalLoadFlags( |
9576 | INTERNAL_LOAD_FLAGS_INHERIT_PRINCIPAL)) && |
9577 | NS_SUCCEEDED(nsContentUtils::URIInheritsSecurityContext(((bool)(__builtin_expect(!!(!NS_FAILED_impl(nsContentUtils::URIInheritsSecurityContext ( aLoadState->URI(), &inherits))), 1))) |
9578 | aLoadState->URI(), &inherits))((bool)(__builtin_expect(!!(!NS_FAILED_impl(nsContentUtils::URIInheritsSecurityContext ( aLoadState->URI(), &inherits))), 1))) && |
9579 | inherits) { |
9580 | aLoadState->SetPrincipalToInherit(GetInheritedPrincipal(true)); |
9581 | } |
9582 | // If principalToInherit is still null (e.g. if some of the conditions of |
9583 | // were not satisfied), then no inheritance of any sort will happen: the |
9584 | // load will just get a principal based on the URI being loaded. |
9585 | } |
9586 | |
9587 | // If this docshell is owned by a frameloader, make sure to cancel |
9588 | // possible frameloader initialization before loading a new page. |
9589 | nsCOMPtr<nsIDocShellTreeItem> parent = GetInProcessParentDocshell(); |
9590 | if (parent) { |
9591 | RefPtr<Document> doc = parent->GetDocument(); |
9592 | if (doc) { |
9593 | doc->TryCancelFrameLoaderInitialization(this); |
9594 | } |
9595 | } |
9596 | |
9597 | // Before going any further vet loads initiated by external programs. |
9598 | if (aLoadState->HasLoadFlags(LOAD_FLAGS_FROM_EXTERNAL)) { |
9599 | MOZ_DIAGNOSTIC_ASSERT(aLoadState->LoadType() == LOAD_NORMAL)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aLoadState->LoadType() == LOAD_NORMAL)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(aLoadState->LoadType() == LOAD_NORMAL))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aLoadState->LoadType() == LOAD_NORMAL" , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 9599); AnnotateMozCrashReason ("MOZ_DIAGNOSTIC_ASSERT" "(" "aLoadState->LoadType() == LOAD_NORMAL" ")"); do { MOZ_CrashSequence(__null, 9599); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
9600 | |
9601 | // Disallow external chrome: loads targetted at content windows |
9602 | if (aLoadState->URI()->SchemeIs("chrome")) { |
9603 | NS_WARNING("blocked external chrome: url -- use '--chrome' option")NS_DebugBreak(NS_DEBUG_WARNING, "blocked external chrome: url -- use '--chrome' option" , nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 9603); |
9604 | return NS_ERROR_FAILURE; |
9605 | } |
9606 | |
9607 | // clear the decks to prevent context bleed-through (bug 298255) |
9608 | rv = CreateAboutBlankDocumentViewer(nullptr, nullptr, nullptr, nullptr, |
9609 | /* aIsInitialDocument */ false); |
9610 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
9611 | return NS_ERROR_FAILURE; |
9612 | } |
9613 | } |
9614 | |
9615 | mAllowKeywordFixup = aLoadState->HasInternalLoadFlags( |
9616 | INTERNAL_LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP); |
9617 | mURIResultedInDocument = false; // reset the clock... |
9618 | |
9619 | // If container is an iframe element and will lazy load element steps given |
9620 | // container returns true, then stop intersection-observing a lazy loading |
9621 | // element container and set container's lazy load resumption steps to null. |
9622 | if (IsSubframe()) { |
9623 | if (auto* iframe = HTMLIFrameElement::FromNodeOrNull( |
9624 | mBrowsingContext->GetEmbedderElement())) { |
9625 | // Per spec, reload doesn't cancel lazy loading iframes. |
9626 | if (!(aLoadState->LoadType() & LOAD_RELOAD_NORMAL)) { |
9627 | iframe->CancelLazyLoading(true /* aClearLazyLoadState */); |
9628 | } |
9629 | } |
9630 | } |
9631 | |
9632 | // See if this is actually a load between two history entries for the same |
9633 | // document. If the process fails, or if we successfully navigate within the |
9634 | // same document, return. |
9635 | if (sameDocument) { |
9636 | nsresult rv = HandleSameDocumentNavigation( |
9637 | aLoadState, sameDocumentNavigationState, sameDocument); |
9638 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 9638); return rv; } } while (false); |
9639 | if (shouldTakeFocus) { |
9640 | mBrowsingContext->Focus(CallerType::System, IgnoreErrors()); |
9641 | } |
9642 | if (sameDocument) { |
9643 | return rv; |
9644 | } |
9645 | } |
9646 | |
9647 | // mDocumentViewer->PermitUnload can destroy |this| docShell, which |
9648 | // causes the next call of CanSavePresentation to crash. |
9649 | // Hold onto |this| until we return, to prevent a crash from happening. |
9650 | // (bug#331040) |
9651 | nsCOMPtr<nsIDocShell> kungFuDeathGrip(this); |
9652 | |
9653 | // Don't init timing for javascript:, since it generally doesn't |
9654 | // actually start a load or anything. If it does, we'll init |
9655 | // timing then, from OnStateChange. |
9656 | |
9657 | // XXXbz mTiming should know what channel it's for, so we don't |
9658 | // need this hackery. |
9659 | const bool isJavaScript = aLoadState->URI()->SchemeIs("javascript"); |
9660 | const bool isExternalProtocol = |
9661 | nsContentUtils::IsExternalProtocol(aLoadState->URI()); |
9662 | const bool isDownload = !aLoadState->FileName().IsVoid(); |
9663 | const bool toBeReset = !isJavaScript && MaybeInitTiming(); |
9664 | |
9665 | // FIXME(emilio): Should this be done by javascript: uris? What about external |
9666 | // protocols? |
9667 | if (mTiming && !isDownload) { |
9668 | mTiming->NotifyBeforeUnload(); |
9669 | } |
9670 | |
9671 | // The following steps are from https://html.spec.whatwg.org/#navigate |
9672 | // Step 19, and here we actually also perform step 2 from |
9673 | // #navigate-to-a-javascript:-url (step 20) where the ongoing navigation is |
9674 | // set to null. |
9675 | SetOngoingNavigation(isJavaScript ? Nothing() |
9676 | : Some(OngoingNavigation::NavigationID)); |
9677 | |
9678 | // Step 21 |
9679 | if (RefPtr<Document> document = GetDocument(); |
9680 | document && |
9681 | aLoadState->UserNavigationInvolvement() != |
9682 | UserNavigationInvolvement::BrowserUI && |
9683 | !document->IsInitialDocument() && |
9684 | !NS_IsAboutBlankAllowQueryAndFragment(document->GetDocumentURI()) && |
9685 | NS_IsFetchScheme(aLoadState->URI()) && |
9686 | document->NodePrincipal()->Subsumes(aLoadState->TriggeringPrincipal())) { |
9687 | if (nsCOMPtr<nsPIDOMWindowInner> window = document->GetInnerWindow()) { |
9688 | // Step 21.1 |
9689 | if (RefPtr<Navigation> navigation = window->Navigation()) { |
9690 | AutoJSAPI jsapi; |
9691 | if (jsapi.Init(window)) { |
9692 | RefPtr<Element> sourceElement = aLoadState->GetSourceElement(); |
9693 | |
9694 | // Step 21.2 |
9695 | RefPtr<FormData> formData = aLoadState->GetFormDataEntryList(); |
9696 | |
9697 | // Step 21.3 |
9698 | RefPtr<nsIStructuredCloneContainer> navigationAPIStateForFiring = |
9699 | aLoadState->GetNavigationAPIState(); |
9700 | if (!navigationAPIStateForFiring) { |
9701 | navigationAPIStateForFiring = nullptr; |
9702 | } |
9703 | |
9704 | nsCOMPtr<nsIURI> destinationURL = aLoadState->URI(); |
9705 | // Step 21.4 |
9706 | bool shouldContinue = navigation->FirePushReplaceReloadNavigateEvent( |
9707 | jsapi.cx(), aLoadState->GetNavigationType(), destinationURL, |
9708 | /* aIsSameDocument */ false, /* aIsSync */ false, |
9709 | Some(aLoadState->UserNavigationInvolvement()), sourceElement, |
9710 | formData.forget(), navigationAPIStateForFiring, |
9711 | /* aClassicHistoryAPIState */ nullptr); |
9712 | |
9713 | // Step 21.5 |
9714 | if (!shouldContinue) { |
9715 | return NS_OK; |
9716 | } |
9717 | } |
9718 | } |
9719 | } |
9720 | } |
9721 | |
9722 | // Check if the page doesn't want to be unloaded. The javascript: |
9723 | // protocol handler deals with this for javascript: URLs. |
9724 | // NOTE(emilio): As of this writing, other browsers fire beforeunload for |
9725 | // external protocols, so keep doing that even though they don't return data |
9726 | // and thus we won't really unload this... |
9727 | if (!isJavaScript && !isDownload && |
9728 | !aLoadState->NotifiedBeforeUnloadListeners() && mDocumentViewer) { |
9729 | // Check if request is exempted from HTTPSOnlyMode and if https-first is |
9730 | // enabled, if so it means: |
9731 | // * https-first failed to upgrade request to https |
9732 | // * we already asked for permission to unload and the user accepted |
9733 | // otherwise we wouldn't be here. |
9734 | const bool isPrivateWin = GetOriginAttributes().IsPrivateBrowsing(); |
9735 | const uint32_t loadType = aLoadState->LoadType(); |
9736 | |
9737 | // Check if request is a reload. |
9738 | const bool isHistoryOrReload = |
9739 | loadType == LOAD_RELOAD_NORMAL || |
9740 | loadType == LOAD_RELOAD_BYPASS_CACHE || |
9741 | loadType == LOAD_RELOAD_BYPASS_PROXY || |
9742 | loadType == LOAD_RELOAD_BYPASS_PROXY_AND_CACHE || |
9743 | loadType == LOAD_HISTORY; |
9744 | |
9745 | // If it isn't a reload, the request already failed to be upgraded and |
9746 | // https-first is enabled then don't ask the user again for permission to |
9747 | // unload and just unload. |
9748 | bool okToUnload; |
9749 | if (!isHistoryOrReload && aLoadState->IsExemptFromHTTPSFirstMode() && |
9750 | nsHTTPSOnlyUtils::GetUpgradeMode(isPrivateWin) == |
9751 | nsHTTPSOnlyUtils::HTTPS_FIRST_MODE) { |
9752 | rv = mDocumentViewer->PermitUnload( |
9753 | nsIDocumentViewer::PermitUnloadAction::eDontPromptAndUnload, |
9754 | &okToUnload); |
9755 | } else { |
9756 | rv = mDocumentViewer->PermitUnload(&okToUnload); |
9757 | } |
9758 | |
9759 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && !okToUnload) { |
9760 | // The user chose not to unload the page, interrupt the |
9761 | // load. |
9762 | MaybeResetInitTiming(toBeReset); |
9763 | return NS_OK; |
9764 | } |
9765 | } |
9766 | |
9767 | if (mTiming && !isDownload) { |
9768 | mTiming->NotifyUnloadAccepted(mCurrentURI); |
9769 | } |
9770 | |
9771 | // In e10s, in the parent process, we refuse to load anything other than |
9772 | // "safe" resources that we ship or trust enough to give "special" URLs. |
9773 | // Similar check will be performed by the ParentProcessDocumentChannel if in |
9774 | // use. |
9775 | if (XRE_IsE10sParentProcess() && |
9776 | !DocumentChannel::CanUseDocumentChannel(aLoadState->URI()) && |
9777 | !CanLoadInParentProcess(aLoadState->URI())) { |
9778 | return NS_ERROR_FAILURE; |
9779 | } |
9780 | |
9781 | // Whenever a top-level browsing context is navigated, the user agent MUST |
9782 | // lock the orientation of the document to the document's default |
9783 | // orientation. We don't explicitly check for a top-level browsing context |
9784 | // here because orientation is only set on top-level browsing contexts. |
9785 | if (mBrowsingContext->GetOrientationLock() != hal::ScreenOrientation::None) { |
9786 | MOZ_ASSERT(mBrowsingContext->IsTop())do { static_assert( mozilla::detail::AssertionConditionType< decltype(mBrowsingContext->IsTop())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mBrowsingContext->IsTop() ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "mBrowsingContext->IsTop()", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 9786); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mBrowsingContext->IsTop()" ")"); do { MOZ_CrashSequence(__null, 9786); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
9787 | MOZ_ALWAYS_SUCCEEDS(do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl (mBrowsingContext->SetOrientationLock(hal::ScreenOrientation ::None))), 1)))), 1))) { } else { do { do { } while (false); MOZ_ReportCrash ("" "NS_SUCCEEDED(mBrowsingContext->SetOrientationLock(hal::ScreenOrientation::None))" , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 9788); AnnotateMozCrashReason ("MOZ_CRASH(" "NS_SUCCEEDED(mBrowsingContext->SetOrientationLock(hal::ScreenOrientation::None))" ")"); do { MOZ_CrashSequence(__null, 9788); __attribute__((nomerge )) ::abort(); } while (false); } while (false); } } while (false ) |
9788 | mBrowsingContext->SetOrientationLock(hal::ScreenOrientation::None))do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl (mBrowsingContext->SetOrientationLock(hal::ScreenOrientation ::None))), 1)))), 1))) { } else { do { do { } while (false); MOZ_ReportCrash ("" "NS_SUCCEEDED(mBrowsingContext->SetOrientationLock(hal::ScreenOrientation::None))" , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 9788); AnnotateMozCrashReason ("MOZ_CRASH(" "NS_SUCCEEDED(mBrowsingContext->SetOrientationLock(hal::ScreenOrientation::None))" ")"); do { MOZ_CrashSequence(__null, 9788); __attribute__((nomerge )) ::abort(); } while (false); } while (false); } } while (false ); |
9789 | if (mBrowsingContext->IsActive()) { |
9790 | ScreenOrientation::UpdateActiveOrientationLock( |
9791 | hal::ScreenOrientation::None); |
9792 | } |
9793 | } |
9794 | |
9795 | // Check for saving the presentation here, before calling Stop(). |
9796 | // This is necessary so that we can catch any pending requests. |
9797 | // Since the new request has not been created yet, we pass null for the |
9798 | // new request parameter. |
9799 | // Also pass nullptr for the document, since it doesn't affect the return |
9800 | // value for our purposes here. |
9801 | const bool savePresentation = |
9802 | CanSavePresentation(aLoadState->LoadType(), nullptr, nullptr, |
9803 | /* aReportBFCacheComboTelemetry */ true); |
9804 | |
9805 | // nsDocShell::CanSavePresentation is for non-SHIP version only. Do a |
9806 | // separate check for SHIP so that we know if there are ongoing requests |
9807 | // before calling Stop() below. |
9808 | if (mozilla::SessionHistoryInParent()) { |
9809 | Document* document = GetDocument(); |
9810 | uint32_t flags = 0; |
9811 | if (document && !document->CanSavePresentation(nullptr, flags, true)) { |
9812 | // This forces some flags into the WindowGlobalParent's mBFCacheStatus, |
9813 | // which we'll then use in CanonicalBrowsingContext::AllowedInBFCache, |
9814 | // and in particular we'll store BFCacheStatus::REQUEST if needed. |
9815 | // Also, we want to report all the flags to the parent process here (and |
9816 | // not just BFCacheStatus::NOT_ALLOWED), so that it can update the |
9817 | // telemetry data correctly. |
9818 | document->DisallowBFCaching(flags); |
9819 | } |
9820 | } |
9821 | |
9822 | // Don't stop current network activity for javascript: URL's since they might |
9823 | // not result in any data, and thus nothing should be stopped in those cases. |
9824 | // In the case where they do result in data, the javascript: URL channel takes |
9825 | // care of stopping current network activity. Similarly, downloads don't |
9826 | // unload this document... |
9827 | if (!isJavaScript && !isDownload && !isExternalProtocol) { |
9828 | // Stop any current network activity. |
9829 | // Also stop content if this is a zombie doc. otherwise |
9830 | // the onload will be delayed by other loads initiated in the |
9831 | // background by the first document that |
9832 | // didn't fully load before the next load was initiated. |
9833 | // If not a zombie, don't stop content until data |
9834 | // starts arriving from the new URI... |
9835 | if ((mDocumentViewer && mDocumentViewer->GetPreviousViewer()) || |
9836 | LOAD_TYPE_HAS_FLAGS(aLoadState->LoadType(), LOAD_FLAGS_STOP_CONTENT)((aLoadState->LoadType()) & ((LOAD_FLAGS_STOP_CONTENT) << 16))) { |
9837 | rv = Stop(nsIWebNavigation::STOP_ALL); |
9838 | } else { |
9839 | rv = Stop(nsIWebNavigation::STOP_NETWORK); |
9840 | } |
9841 | |
9842 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
9843 | return rv; |
9844 | } |
9845 | } |
9846 | |
9847 | mLoadType = aLoadState->LoadType(); |
9848 | |
9849 | // aLoadState->SHEntry() should be assigned to mLSHE, only after Stop() has |
9850 | // been called. But when loading an error page, do not clear the |
9851 | // mLSHE for the real page. |
9852 | if (mLoadType != LOAD_ERROR_PAGE) { |
9853 | SetHistoryEntryAndUpdateBC(Some<nsISHEntry*>(aLoadState->SHEntry()), |
9854 | Nothing()); |
9855 | if (aLoadState->LoadIsFromSessionHistory() && |
9856 | !mozilla::SessionHistoryInParent()) { |
9857 | // We're making history navigation or a reload. Make sure our history ID |
9858 | // points to the same ID as SHEntry's docshell ID. |
9859 | nsID historyID = {}; |
9860 | aLoadState->SHEntry()->GetDocshellID(historyID); |
9861 | |
9862 | Unused << mBrowsingContext->SetHistoryID(historyID); |
9863 | } |
9864 | } |
9865 | |
9866 | mSavingOldViewer = savePresentation; |
9867 | |
9868 | // If we have a saved content viewer in history, restore and show it now. |
9869 | if (aLoadState->LoadIsFromSessionHistory() && |
9870 | (mLoadType & LOAD_CMD_HISTORY)) { |
9871 | // https://html.spec.whatwg.org/#history-traversal: |
9872 | // To traverse the history |
9873 | // "If entry has a different Document object than the current entry, then |
9874 | // run the following substeps: Remove any tasks queued by the history |
9875 | // traversal task source..." |
9876 | // Same document object case was handled already above with |
9877 | // HandleSameDocumentNavigation call. |
9878 | RefPtr<ChildSHistory> shistory = GetRootSessionHistory(); |
9879 | if (shistory) { |
9880 | shistory->RemovePendingHistoryNavigations(); |
9881 | } |
9882 | if (!mozilla::SessionHistoryInParent()) { |
9883 | // It's possible that the previous viewer of mDocumentViewer is the |
9884 | // viewer that will end up in aLoadState->SHEntry() when it gets closed. |
9885 | // If that's the case, we need to go ahead and force it into its shentry |
9886 | // so we can restore it. |
9887 | if (mDocumentViewer) { |
9888 | nsCOMPtr<nsIDocumentViewer> prevViewer = |
9889 | mDocumentViewer->GetPreviousViewer(); |
9890 | if (prevViewer) { |
9891 | #ifdef DEBUG1 |
9892 | nsCOMPtr<nsIDocumentViewer> prevPrevViewer = |
9893 | prevViewer->GetPreviousViewer(); |
9894 | NS_ASSERTION(!prevPrevViewer, "Should never have viewer chain here")do { if (!(!prevPrevViewer)) { NS_DebugBreak(NS_DEBUG_ASSERTION , "Should never have viewer chain here", "!prevPrevViewer", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 9894); MOZ_PretendNoReturn(); } } while (0); |
9895 | #endif |
9896 | nsCOMPtr<nsISHEntry> viewerEntry; |
9897 | prevViewer->GetHistoryEntry(getter_AddRefs(viewerEntry)); |
9898 | if (viewerEntry == aLoadState->SHEntry()) { |
9899 | // Make sure this viewer ends up in the right place |
9900 | mDocumentViewer->SetPreviousViewer(nullptr); |
9901 | prevViewer->Destroy(); |
9902 | } |
9903 | } |
9904 | } |
9905 | nsCOMPtr<nsISHEntry> oldEntry = mOSHE; |
9906 | bool restoring; |
9907 | rv = RestorePresentation(aLoadState->SHEntry(), &restoring); |
9908 | if (restoring) { |
9909 | glean::bfcache::page_restored |
9910 | .EnumGet(glean::bfcache::PageRestoredLabel::eTrue) |
9911 | .Add(); |
9912 | return rv; |
9913 | } |
9914 | glean::bfcache::page_restored |
9915 | .EnumGet(glean::bfcache::PageRestoredLabel::eFalse) |
9916 | .Add(); |
9917 | |
9918 | // We failed to restore the presentation, so clean up. |
9919 | // Both the old and new history entries could potentially be in |
9920 | // an inconsistent state. |
9921 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
9922 | if (oldEntry) { |
9923 | oldEntry->SyncPresentationState(); |
9924 | } |
9925 | |
9926 | aLoadState->SHEntry()->SyncPresentationState(); |
9927 | } |
9928 | } |
9929 | } |
9930 | |
9931 | bool isTopLevelDoc = mBrowsingContext->IsTopContent(); |
9932 | |
9933 | OriginAttributes attrs = GetOriginAttributes(); |
9934 | attrs.SetFirstPartyDomain(isTopLevelDoc, aLoadState->URI()); |
9935 | |
9936 | PredictorLearn(aLoadState->URI(), nullptr, |
9937 | nsINetworkPredictor::LEARN_LOAD_TOPLEVEL, attrs); |
9938 | PredictorPredict(aLoadState->URI(), nullptr, |
9939 | nsINetworkPredictor::PREDICT_LOAD, attrs, nullptr); |
9940 | |
9941 | nsCOMPtr<nsIRequest> req; |
9942 | rv = DoURILoad(aLoadState, aCacheKey, getter_AddRefs(req)); |
9943 | |
9944 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) { |
9945 | if (shouldTakeFocus) { |
9946 | mBrowsingContext->Focus(CallerType::System, IgnoreErrors()); |
9947 | } |
9948 | } |
9949 | |
9950 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
9951 | nsCOMPtr<nsIChannel> chan(do_QueryInterface(req)); |
9952 | UnblockEmbedderLoadEventForFailure(); |
9953 | nsCOMPtr<nsIURI> uri = aLoadState->URI(); |
9954 | if (DisplayLoadError(rv, uri, nullptr, chan) && |
9955 | // FIXME: At this point code was using internal load flags, but checking |
9956 | // non-internal load flags? |
9957 | aLoadState->HasLoadFlags(LOAD_FLAGS_ERROR_LOAD_CHANGES_RV)) { |
9958 | return NS_ERROR_LOAD_SHOWED_ERRORPAGE; |
9959 | } |
9960 | |
9961 | // We won't report any error if this is an unknown protocol error. The |
9962 | // reason behind this is that it will allow enumeration of external |
9963 | // protocols if we report an error for each unknown protocol. |
9964 | if (NS_ERROR_UNKNOWN_PROTOCOL == rv) { |
9965 | return NS_OK; |
9966 | } |
9967 | } |
9968 | |
9969 | return rv; |
9970 | } |
9971 | |
9972 | /* static */ |
9973 | bool nsDocShell::CanLoadInParentProcess(nsIURI* aURI) { |
9974 | nsCOMPtr<nsIURI> uri = aURI; |
9975 | // In e10s, in the parent process, we refuse to load anything other than |
9976 | // "safe" resources that we ship or trust enough to give "special" URLs. |
9977 | bool canLoadInParent = false; |
9978 | if (NS_SUCCEEDED(NS_URIChainHasFlags(((bool)(__builtin_expect(!!(!NS_FAILED_impl(NS_URIChainHasFlags ( uri, nsIProtocolHandler::URI_IS_UI_RESOURCE, &canLoadInParent ))), 1))) |
9979 | uri, nsIProtocolHandler::URI_IS_UI_RESOURCE, &canLoadInParent))((bool)(__builtin_expect(!!(!NS_FAILED_impl(NS_URIChainHasFlags ( uri, nsIProtocolHandler::URI_IS_UI_RESOURCE, &canLoadInParent ))), 1))) && |
9980 | canLoadInParent) { |
9981 | // We allow UI resources. |
9982 | return true; |
9983 | } |
9984 | // For about: and extension-based URIs, which don't get |
9985 | // URI_IS_UI_RESOURCE, first remove layers of view-source:, if present. |
9986 | while (uri && uri->SchemeIs("view-source")) { |
9987 | nsCOMPtr<nsINestedURI> nested = do_QueryInterface(uri); |
9988 | if (nested) { |
9989 | nested->GetInnerURI(getter_AddRefs(uri)); |
9990 | } else { |
9991 | break; |
9992 | } |
9993 | } |
9994 | // Allow about: URIs, and allow moz-extension ones if we're running |
9995 | // extension content in the parent process. |
9996 | if (!uri || uri->SchemeIs("about") || |
9997 | (!StaticPrefs::extensions_webextensions_remote() && |
9998 | uri->SchemeIs("moz-extension"))) { |
9999 | return true; |
10000 | } |
10001 | #ifdef MOZ_THUNDERBIRD |
10002 | if (uri->SchemeIs("imap") || uri->SchemeIs("mailbox") || |
10003 | uri->SchemeIs("news") || uri->SchemeIs("nntp") || |
10004 | uri->SchemeIs("snews") || uri->SchemeIs("x-moz-ews")) { |
10005 | return true; |
10006 | } |
10007 | #endif |
10008 | nsAutoCString scheme; |
10009 | uri->GetScheme(scheme); |
10010 | // Allow ext+foo URIs (extension-registered custom protocols). See |
10011 | // https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/protocol_handlers |
10012 | if (StringBeginsWith(scheme, "ext+"_ns) && |
10013 | !StaticPrefs::extensions_webextensions_remote()) { |
10014 | return true; |
10015 | } |
10016 | // Final exception for some legacy automated tests: |
10017 | if (xpc::IsInAutomation() && |
10018 | StaticPrefs::security_allow_unsafe_parent_loads()) { |
10019 | return true; |
10020 | } |
10021 | return false; |
10022 | } |
10023 | |
10024 | nsIPrincipal* nsDocShell::GetInheritedPrincipal( |
10025 | bool aConsiderCurrentDocument, bool aConsiderPartitionedPrincipal) { |
10026 | RefPtr<Document> document; |
10027 | bool inheritedFromCurrent = false; |
10028 | |
10029 | if (aConsiderCurrentDocument && mDocumentViewer) { |
10030 | document = mDocumentViewer->GetDocument(); |
10031 | inheritedFromCurrent = true; |
10032 | } |
10033 | |
10034 | if (!document) { |
10035 | nsCOMPtr<nsIDocShellTreeItem> parentItem; |
10036 | GetInProcessSameTypeParent(getter_AddRefs(parentItem)); |
10037 | if (parentItem) { |
10038 | document = parentItem->GetDocument(); |
10039 | } |
10040 | } |
10041 | |
10042 | if (!document) { |
10043 | if (!aConsiderCurrentDocument) { |
10044 | return nullptr; |
10045 | } |
10046 | |
10047 | // Make sure we end up with _something_ as the principal no matter |
10048 | // what.If this fails, we'll just get a null docViewer and bail. |
10049 | EnsureDocumentViewer(); |
10050 | if (!mDocumentViewer) { |
10051 | return nullptr; |
10052 | } |
10053 | document = mDocumentViewer->GetDocument(); |
10054 | } |
10055 | |
10056 | //-- Get the document's principal |
10057 | if (document) { |
10058 | nsIPrincipal* docPrincipal = aConsiderPartitionedPrincipal |
10059 | ? document->PartitionedPrincipal() |
10060 | : document->NodePrincipal(); |
10061 | |
10062 | // Don't allow loads in typeContent docShells to inherit the system |
10063 | // principal from existing documents. |
10064 | if (inheritedFromCurrent && mItemType == typeContent && |
10065 | docPrincipal->IsSystemPrincipal()) { |
10066 | return nullptr; |
10067 | } |
10068 | |
10069 | return docPrincipal; |
10070 | } |
10071 | |
10072 | return nullptr; |
10073 | } |
10074 | |
10075 | /* static */ nsresult nsDocShell::CreateRealChannelForDocument( |
10076 | nsIChannel** aChannel, nsIURI* aURI, nsILoadInfo* aLoadInfo, |
10077 | nsIInterfaceRequestor* aCallbacks, nsLoadFlags aLoadFlags, |
10078 | const nsAString& aSrcdoc, nsIURI* aBaseURI) { |
10079 | nsCOMPtr<nsIChannel> channel; |
10080 | if (aSrcdoc.IsVoid()) { |
10081 | MOZ_TRY(NS_NewChannelInternal(getter_AddRefs(channel), aURI, aLoadInfo,__extension__({ auto mozTryVarTempResult = ::mozilla::ToResult (NS_NewChannelInternal(getter_AddRefs(channel), aURI, aLoadInfo , nullptr, nullptr, aCallbacks, aLoadFlags)); if ((__builtin_expect (!!(mozTryVarTempResult.isErr()), 0))) { return mozTryVarTempResult .propagateErr(); } mozTryVarTempResult.unwrap(); }) |
10082 | nullptr, // PerformanceStorage__extension__({ auto mozTryVarTempResult = ::mozilla::ToResult (NS_NewChannelInternal(getter_AddRefs(channel), aURI, aLoadInfo , nullptr, nullptr, aCallbacks, aLoadFlags)); if ((__builtin_expect (!!(mozTryVarTempResult.isErr()), 0))) { return mozTryVarTempResult .propagateErr(); } mozTryVarTempResult.unwrap(); }) |
10083 | nullptr, // loadGroup__extension__({ auto mozTryVarTempResult = ::mozilla::ToResult (NS_NewChannelInternal(getter_AddRefs(channel), aURI, aLoadInfo , nullptr, nullptr, aCallbacks, aLoadFlags)); if ((__builtin_expect (!!(mozTryVarTempResult.isErr()), 0))) { return mozTryVarTempResult .propagateErr(); } mozTryVarTempResult.unwrap(); }) |
10084 | aCallbacks, aLoadFlags))__extension__({ auto mozTryVarTempResult = ::mozilla::ToResult (NS_NewChannelInternal(getter_AddRefs(channel), aURI, aLoadInfo , nullptr, nullptr, aCallbacks, aLoadFlags)); if ((__builtin_expect (!!(mozTryVarTempResult.isErr()), 0))) { return mozTryVarTempResult .propagateErr(); } mozTryVarTempResult.unwrap(); }); |
10085 | |
10086 | if (aBaseURI) { |
10087 | nsCOMPtr<nsIViewSourceChannel> vsc = do_QueryInterface(channel); |
10088 | if (vsc) { |
10089 | MOZ_ALWAYS_SUCCEEDS(vsc->SetBaseURI(aBaseURI))do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl (vsc->SetBaseURI(aBaseURI))), 1)))), 1))) { } else { do { do { } while (false); MOZ_ReportCrash("" "NS_SUCCEEDED(vsc->SetBaseURI(aBaseURI))" , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 10089); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(vsc->SetBaseURI(aBaseURI))" ")"); do { MOZ_CrashSequence(__null, 10089); __attribute__(( nomerge)) ::abort(); } while (false); } while (false); } } while (false); |
10090 | } |
10091 | } |
10092 | } else if (aURI->SchemeIs("view-source")) { |
10093 | // Instantiate view source handler protocol, if it doesn't exist already. |
10094 | nsCOMPtr<nsIIOService> io(do_GetIOService()); |
10095 | MOZ_ASSERT(io)do { static_assert( mozilla::detail::AssertionConditionType< decltype(io)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(io))), 0))) { do { } while (false ); MOZ_ReportAssertionFailure("io", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 10095); AnnotateMozCrashReason("MOZ_ASSERT" "(" "io" ")"); do { MOZ_CrashSequence(__null, 10095); __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
10096 | nsCOMPtr<nsIProtocolHandler> handler; |
10097 | nsresult rv = |
10098 | io->GetProtocolHandler("view-source", getter_AddRefs(handler)); |
10099 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
10100 | return rv; |
10101 | } |
10102 | |
10103 | nsViewSourceHandler* vsh = nsViewSourceHandler::GetInstance(); |
10104 | if (!vsh) { |
10105 | return NS_ERROR_FAILURE; |
10106 | } |
10107 | |
10108 | MOZ_TRY(vsh->NewSrcdocChannel(aURI, aBaseURI, aSrcdoc, aLoadInfo,__extension__({ auto mozTryVarTempResult = ::mozilla::ToResult (vsh->NewSrcdocChannel(aURI, aBaseURI, aSrcdoc, aLoadInfo, getter_AddRefs(channel))); if ((__builtin_expect(!!(mozTryVarTempResult .isErr()), 0))) { return mozTryVarTempResult.propagateErr(); } mozTryVarTempResult.unwrap(); }) |
10109 | getter_AddRefs(channel)))__extension__({ auto mozTryVarTempResult = ::mozilla::ToResult (vsh->NewSrcdocChannel(aURI, aBaseURI, aSrcdoc, aLoadInfo, getter_AddRefs(channel))); if ((__builtin_expect(!!(mozTryVarTempResult .isErr()), 0))) { return mozTryVarTempResult.propagateErr(); } mozTryVarTempResult.unwrap(); }); |
10110 | } else { |
10111 | MOZ_TRY(NS_NewInputStreamChannelInternal(getter_AddRefs(channel), aURI,__extension__({ auto mozTryVarTempResult = ::mozilla::ToResult (NS_NewInputStreamChannelInternal(getter_AddRefs(channel), aURI , aSrcdoc, "text/html"_ns, aLoadInfo, true)); if ((__builtin_expect (!!(mozTryVarTempResult.isErr()), 0))) { return mozTryVarTempResult .propagateErr(); } mozTryVarTempResult.unwrap(); }) |
10112 | aSrcdoc, "text/html"_ns, aLoadInfo,__extension__({ auto mozTryVarTempResult = ::mozilla::ToResult (NS_NewInputStreamChannelInternal(getter_AddRefs(channel), aURI , aSrcdoc, "text/html"_ns, aLoadInfo, true)); if ((__builtin_expect (!!(mozTryVarTempResult.isErr()), 0))) { return mozTryVarTempResult .propagateErr(); } mozTryVarTempResult.unwrap(); }) |
10113 | true))__extension__({ auto mozTryVarTempResult = ::mozilla::ToResult (NS_NewInputStreamChannelInternal(getter_AddRefs(channel), aURI , aSrcdoc, "text/html"_ns, aLoadInfo, true)); if ((__builtin_expect (!!(mozTryVarTempResult.isErr()), 0))) { return mozTryVarTempResult .propagateErr(); } mozTryVarTempResult.unwrap(); }); |
10114 | nsCOMPtr<nsIInputStreamChannel> isc = do_QueryInterface(channel); |
10115 | MOZ_ASSERT(isc)do { static_assert( mozilla::detail::AssertionConditionType< decltype(isc)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(isc))), 0))) { do { } while (false ); MOZ_ReportAssertionFailure("isc", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 10115); AnnotateMozCrashReason("MOZ_ASSERT" "(" "isc" ")"); do { MOZ_CrashSequence(__null, 10115); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
10116 | isc->SetBaseURI(aBaseURI); |
10117 | } |
10118 | |
10119 | if (aLoadFlags != nsIRequest::LOAD_NORMAL) { |
10120 | nsresult rv = channel->SetLoadFlags(aLoadFlags); |
10121 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 10121); return rv; } } while (false); |
10122 | } |
10123 | |
10124 | channel.forget(aChannel); |
10125 | return NS_OK; |
10126 | } |
10127 | |
10128 | /* static */ bool nsDocShell::CreateAndConfigureRealChannelForLoadState( |
10129 | BrowsingContext* aBrowsingContext, nsDocShellLoadState* aLoadState, |
10130 | LoadInfo* aLoadInfo, nsIInterfaceRequestor* aCallbacks, |
10131 | nsDocShell* aDocShell, const OriginAttributes& aOriginAttributes, |
10132 | nsLoadFlags aLoadFlags, uint32_t aCacheKey, nsresult& aRv, |
10133 | nsIChannel** aChannel) { |
10134 | MOZ_ASSERT(aLoadInfo)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aLoadInfo)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aLoadInfo))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aLoadInfo", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 10134); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadInfo" ")"); do { MOZ_CrashSequence(__null, 10134); __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
10135 | |
10136 | nsString srcdoc = VoidString(); |
10137 | bool isSrcdoc = |
10138 | aLoadState->HasInternalLoadFlags(INTERNAL_LOAD_FLAGS_IS_SRCDOC); |
10139 | if (isSrcdoc) { |
10140 | srcdoc = aLoadState->SrcdocData(); |
10141 | } |
10142 | |
10143 | aLoadInfo->SetTriggeringRemoteType( |
10144 | aLoadState->GetEffectiveTriggeringRemoteType()); |
10145 | |
10146 | if (aLoadState->PrincipalToInherit()) { |
10147 | aLoadInfo->SetPrincipalToInherit(aLoadState->PrincipalToInherit()); |
10148 | } |
10149 | aLoadInfo->SetLoadTriggeredFromExternal( |
10150 | aLoadState->HasLoadFlags(LOAD_FLAGS_FROM_EXTERNAL)); |
10151 | aLoadInfo->SetForceAllowDataURI(aLoadState->HasInternalLoadFlags( |
10152 | INTERNAL_LOAD_FLAGS_FORCE_ALLOW_DATA_URI)); |
10153 | aLoadInfo->SetOriginalFrameSrcLoad( |
10154 | aLoadState->HasInternalLoadFlags(INTERNAL_LOAD_FLAGS_ORIGINAL_FRAME_SRC)); |
10155 | aLoadInfo->SetIsNewWindowTarget( |
10156 | aLoadState->HasInternalLoadFlags(INTERNAL_LOAD_FLAGS_FIRST_LOAD)); |
10157 | |
10158 | bool inheritAttrs = false; |
10159 | if (aLoadState->PrincipalToInherit()) { |
10160 | inheritAttrs = nsContentUtils::ChannelShouldInheritPrincipal( |
10161 | aLoadState->PrincipalToInherit(), aLoadState->URI(), |
10162 | true, // aInheritForAboutBlank |
10163 | isSrcdoc); |
10164 | } |
10165 | |
10166 | // Strip the target query parameters before creating the channel. |
10167 | aLoadState->MaybeStripTrackerQueryStrings(aBrowsingContext); |
10168 | |
10169 | OriginAttributes attrs; |
10170 | |
10171 | // Inherit origin attributes from PrincipalToInherit if inheritAttrs is |
10172 | // true. Otherwise we just use the origin attributes from docshell. |
10173 | if (inheritAttrs) { |
10174 | MOZ_ASSERT(aLoadState->PrincipalToInherit(),do { static_assert( mozilla::detail::AssertionConditionType< decltype(aLoadState->PrincipalToInherit())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aLoadState->PrincipalToInherit ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("aLoadState->PrincipalToInherit()" " (" "We should have PrincipalToInherit here." ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 10175 ); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->PrincipalToInherit()" ") (" "We should have PrincipalToInherit here." ")"); do { MOZ_CrashSequence (__null, 10175); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false) |
10175 | "We should have PrincipalToInherit here.")do { static_assert( mozilla::detail::AssertionConditionType< decltype(aLoadState->PrincipalToInherit())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aLoadState->PrincipalToInherit ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("aLoadState->PrincipalToInherit()" " (" "We should have PrincipalToInherit here." ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 10175 ); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->PrincipalToInherit()" ") (" "We should have PrincipalToInherit here." ")"); do { MOZ_CrashSequence (__null, 10175); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); |
10176 | attrs = aLoadState->PrincipalToInherit()->OriginAttributesRef(); |
10177 | // If firstPartyIsolation is not enabled, then PrincipalToInherit should |
10178 | // have the same origin attributes with docshell. |
10179 | MOZ_ASSERT_IF(!OriginAttributes::IsFirstPartyEnabled(),do { if (!OriginAttributes::IsFirstPartyEnabled()) { do { static_assert ( mozilla::detail::AssertionConditionType<decltype(attrs == aOriginAttributes)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(attrs == aOriginAttributes)) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("attrs == aOriginAttributes" , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 10180); AnnotateMozCrashReason("MOZ_ASSERT" "(" "attrs == aOriginAttributes" ")"); do { MOZ_CrashSequence(__null, 10180); __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); } } while (false) |
10180 | attrs == aOriginAttributes)do { if (!OriginAttributes::IsFirstPartyEnabled()) { do { static_assert ( mozilla::detail::AssertionConditionType<decltype(attrs == aOriginAttributes)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(attrs == aOriginAttributes)) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("attrs == aOriginAttributes" , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 10180); AnnotateMozCrashReason("MOZ_ASSERT" "(" "attrs == aOriginAttributes" ")"); do { MOZ_CrashSequence(__null, 10180); __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); } } while (false); |
10181 | } else { |
10182 | attrs = aOriginAttributes; |
10183 | attrs.SetFirstPartyDomain(IsTopLevelDoc(aBrowsingContext, aLoadInfo), |
10184 | aLoadState->URI()); |
10185 | } |
10186 | |
10187 | aRv = aLoadInfo->SetOriginAttributes(attrs); |
10188 | if (NS_WARN_IF(NS_FAILED(aRv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(aRv )), 0))), "NS_FAILED(aRv)", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 10188)) { |
10189 | return false; |
10190 | } |
10191 | |
10192 | if (aLoadState->GetIsFromProcessingFrameAttributes()) { |
10193 | aLoadInfo->SetIsFromProcessingFrameAttributes(); |
10194 | } |
10195 | |
10196 | // Propagate the IsFormSubmission flag to the loadInfo. |
10197 | if (aLoadState->IsFormSubmission()) { |
10198 | aLoadInfo->SetIsFormSubmission(true); |
10199 | } |
10200 | |
10201 | aLoadInfo->SetUnstrippedURI(aLoadState->GetUnstrippedURI()); |
10202 | |
10203 | nsCOMPtr<nsIChannel> channel; |
10204 | aRv = CreateRealChannelForDocument(getter_AddRefs(channel), aLoadState->URI(), |
10205 | aLoadInfo, aCallbacks, aLoadFlags, srcdoc, |
10206 | aLoadState->BaseURI()); |
10207 | NS_ENSURE_SUCCESS(aRv, false)do { nsresult __rv = aRv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "aRv", "false", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 10207); return false; } } while (false); |
10208 | |
10209 | if (!channel) { |
10210 | return false; |
10211 | } |
10212 | |
10213 | // If the HTTPS-Only mode is enabled, every insecure request gets upgraded to |
10214 | // HTTPS by default. This behavior can be disabled through the loadinfo flag |
10215 | // HTTPS_ONLY_EXEMPT. |
10216 | nsHTTPSOnlyUtils::TestSitePermissionAndPotentiallyAddExemption(channel); |
10217 | |
10218 | // hack |
10219 | nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(channel)); |
10220 | nsCOMPtr<nsIHttpChannelInternal> httpChannelInternal( |
10221 | do_QueryInterface(channel)); |
10222 | nsCOMPtr<nsIURI> referrer; |
10223 | nsIReferrerInfo* referrerInfo = aLoadState->GetReferrerInfo(); |
10224 | if (referrerInfo) { |
10225 | referrerInfo->GetOriginalReferrer(getter_AddRefs(referrer)); |
10226 | } |
10227 | if (httpChannelInternal) { |
10228 | if (aLoadState->HasInternalLoadFlags( |
10229 | INTERNAL_LOAD_FLAGS_FORCE_ALLOW_COOKIES)) { |
10230 | aRv = httpChannelInternal->SetThirdPartyFlags( |
10231 | nsIHttpChannelInternal::THIRD_PARTY_FORCE_ALLOW); |
10232 | MOZ_ASSERT(NS_SUCCEEDED(aRv))do { static_assert( mozilla::detail::AssertionConditionType< decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1 ))))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1 )))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1)))", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 10232); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1)))" ")"); do { MOZ_CrashSequence(__null, 10232); __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
10233 | } |
10234 | if (aLoadState->FirstParty()) { |
10235 | aRv = httpChannelInternal->SetDocumentURI(aLoadState->URI()); |
10236 | MOZ_ASSERT(NS_SUCCEEDED(aRv))do { static_assert( mozilla::detail::AssertionConditionType< decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1 ))))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1 )))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1)))", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 10236); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1)))" ")"); do { MOZ_CrashSequence(__null, 10236); __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
10237 | } else { |
10238 | aRv = httpChannelInternal->SetDocumentURI(referrer); |
10239 | MOZ_ASSERT(NS_SUCCEEDED(aRv))do { static_assert( mozilla::detail::AssertionConditionType< decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1 ))))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1 )))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1)))", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 10239); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1)))" ")"); do { MOZ_CrashSequence(__null, 10239); __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
10240 | } |
10241 | aRv = httpChannelInternal->SetRedirectMode( |
10242 | nsIHttpChannelInternal::REDIRECT_MODE_MANUAL); |
10243 | MOZ_ASSERT(NS_SUCCEEDED(aRv))do { static_assert( mozilla::detail::AssertionConditionType< decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1 ))))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1 )))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1)))", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 10243); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1)))" ")"); do { MOZ_CrashSequence(__null, 10243); __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
10244 | } |
10245 | |
10246 | if (httpChannel) { |
10247 | if (aLoadState->HeadersStream()) { |
10248 | aRv = AddHeadersToChannel(aLoadState->HeadersStream(), httpChannel); |
10249 | } |
10250 | // Set the referrer explicitly |
10251 | // Referrer is currenly only set for link clicks here. |
10252 | if (referrerInfo) { |
10253 | aRv = httpChannel->SetReferrerInfo(referrerInfo); |
10254 | MOZ_ASSERT(NS_SUCCEEDED(aRv))do { static_assert( mozilla::detail::AssertionConditionType< decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1 ))))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1 )))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1)))", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 10254); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1)))" ")"); do { MOZ_CrashSequence(__null, 10254); __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
10255 | } |
10256 | |
10257 | // Mark the http channel as UrgentStart for top level document loading in |
10258 | // active tab. |
10259 | if (IsUrgentStart(aBrowsingContext, aLoadInfo, aLoadState->LoadType())) { |
10260 | nsCOMPtr<nsIClassOfService> cos(do_QueryInterface(channel)); |
10261 | if (cos) { |
10262 | cos->AddClassFlags(nsIClassOfService::UrgentStart); |
10263 | if (StaticPrefs::dom_document_priority_incremental()) { |
10264 | cos->SetIncremental(true); |
10265 | } |
10266 | } |
10267 | } |
10268 | } |
10269 | |
10270 | channel->SetOriginalURI(aLoadState->OriginalURI() ? aLoadState->OriginalURI() |
10271 | : aLoadState->URI()); |
10272 | |
10273 | const nsACString& typeHint = aLoadState->TypeHint(); |
10274 | if (!typeHint.IsVoid()) { |
10275 | channel->SetContentType(typeHint); |
10276 | } |
10277 | |
10278 | const nsAString& fileName = aLoadState->FileName(); |
10279 | if (!fileName.IsVoid()) { |
10280 | aRv = channel->SetContentDisposition(nsIChannel::DISPOSITION_ATTACHMENT); |
10281 | NS_ENSURE_SUCCESS(aRv, false)do { nsresult __rv = aRv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "aRv", "false", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 10281); return false; } } while (false); |
10282 | if (!fileName.IsEmpty()) { |
10283 | aRv = channel->SetContentDispositionFilename(fileName); |
10284 | NS_ENSURE_SUCCESS(aRv, false)do { nsresult __rv = aRv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "aRv", "false", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 10284); return false; } } while (false); |
10285 | } |
10286 | } |
10287 | |
10288 | if (nsCOMPtr<nsIWritablePropertyBag2> props = do_QueryInterface(channel)) { |
10289 | nsCOMPtr<nsIURI> referrer; |
10290 | nsIReferrerInfo* referrerInfo = aLoadState->GetReferrerInfo(); |
10291 | if (referrerInfo) { |
10292 | referrerInfo->GetOriginalReferrer(getter_AddRefs(referrer)); |
10293 | } |
10294 | // save true referrer for those who need it (e.g. xpinstall whitelisting) |
10295 | // Currently only http and ftp channels support this. |
10296 | props->SetPropertyAsInterface(u"docshell.internalReferrer"_ns, referrer); |
10297 | } |
10298 | |
10299 | nsCOMPtr<nsICacheInfoChannel> cacheChannel(do_QueryInterface(channel)); |
10300 | auto loadType = aLoadState->LoadType(); |
10301 | |
10302 | if (loadType == LOAD_RELOAD_NORMAL && |
10303 | StaticPrefs:: |
10304 | browser_soft_reload_only_force_validate_top_level_document()) { |
10305 | nsCOMPtr<nsICacheInfoChannel> cachingChannel = do_QueryInterface(channel); |
10306 | if (cachingChannel) { |
10307 | cachingChannel->SetForceValidateCacheContent(true); |
10308 | } |
10309 | } |
10310 | |
10311 | // figure out if we need to set the post data stream on the channel... |
10312 | if (aLoadState->PostDataStream()) { |
10313 | if (nsCOMPtr<nsIFormPOSTActionChannel> postChannel = |
10314 | do_QueryInterface(channel)) { |
10315 | // XXX it's a bit of a hack to rewind the postdata stream here but |
10316 | // it has to be done in case the post data is being reused multiple |
10317 | // times. |
10318 | nsCOMPtr<nsISeekableStream> postDataSeekable = |
10319 | do_QueryInterface(aLoadState->PostDataStream()); |
10320 | if (postDataSeekable) { |
10321 | aRv = postDataSeekable->Seek(nsISeekableStream::NS_SEEK_SET, 0); |
10322 | NS_ENSURE_SUCCESS(aRv, false)do { nsresult __rv = aRv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "aRv", "false", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 10322); return false; } } while (false); |
10323 | } |
10324 | |
10325 | // we really need to have a content type associated with this stream!! |
10326 | postChannel->SetUploadStream(aLoadState->PostDataStream(), ""_ns, -1); |
10327 | |
10328 | // Ownership of the stream has transferred to the channel, clear our |
10329 | // reference. |
10330 | aLoadState->SetPostDataStream(nullptr); |
10331 | } |
10332 | |
10333 | /* If there is a valid postdata *and* it is a History Load, |
10334 | * set up the cache key on the channel, to retrieve the |
10335 | * data *only* from the cache. If it is a normal reload, the |
10336 | * cache is free to go to the server for updated postdata. |
10337 | */ |
10338 | if (cacheChannel && aCacheKey != 0) { |
10339 | if (loadType == LOAD_HISTORY || loadType == LOAD_RELOAD_CHARSET_CHANGE) { |
10340 | cacheChannel->SetCacheKey(aCacheKey); |
10341 | uint32_t loadFlags; |
10342 | if (NS_SUCCEEDED(channel->GetLoadFlags(&loadFlags))((bool)(__builtin_expect(!!(!NS_FAILED_impl(channel->GetLoadFlags (&loadFlags))), 1)))) { |
10343 | channel->SetLoadFlags(loadFlags | |
10344 | nsICachingChannel::LOAD_ONLY_FROM_CACHE); |
10345 | } |
10346 | } else if (loadType == LOAD_RELOAD_NORMAL) { |
10347 | cacheChannel->SetCacheKey(aCacheKey); |
10348 | } |
10349 | } |
10350 | } else { |
10351 | /* If there is no postdata, set the cache key on the channel, and |
10352 | * do not set the LOAD_ONLY_FROM_CACHE flag, so that the channel |
10353 | * will be free to get it from net if it is not found in cache. |
10354 | * New cache may use it creatively on CGI pages with GET |
10355 | * method and even on those that say "no-cache" |
10356 | */ |
10357 | if (loadType == LOAD_HISTORY || loadType == LOAD_RELOAD_NORMAL || |
10358 | loadType == LOAD_RELOAD_CHARSET_CHANGE || |
10359 | loadType == LOAD_RELOAD_CHARSET_CHANGE_BYPASS_CACHE || |
10360 | loadType == LOAD_RELOAD_CHARSET_CHANGE_BYPASS_PROXY_AND_CACHE) { |
10361 | if (cacheChannel && aCacheKey != 0) { |
10362 | cacheChannel->SetCacheKey(aCacheKey); |
10363 | } |
10364 | } |
10365 | } |
10366 | |
10367 | if (nsCOMPtr<nsIScriptChannel> scriptChannel = do_QueryInterface(channel)) { |
10368 | // Allow execution against our context if the principals match |
10369 | scriptChannel->SetExecutionPolicy(nsIScriptChannel::EXECUTE_NORMAL); |
10370 | } |
10371 | |
10372 | if (nsCOMPtr<nsITimedChannel> timedChannel = do_QueryInterface(channel)) { |
10373 | nsString initiatorType; |
10374 | switch (aLoadInfo->InternalContentPolicyType()) { |
10375 | case nsIContentPolicy::TYPE_INTERNAL_EMBED: |
10376 | initiatorType = u"embed"_ns; |
10377 | break; |
10378 | case nsIContentPolicy::TYPE_INTERNAL_OBJECT: |
10379 | initiatorType = u"object"_ns; |
10380 | break; |
10381 | default: { |
10382 | const auto& embedderElementType = |
10383 | aBrowsingContext->GetEmbedderElementType(); |
10384 | if (embedderElementType) { |
10385 | initiatorType = *embedderElementType; |
10386 | } |
10387 | break; |
10388 | } |
10389 | } |
10390 | |
10391 | if (!initiatorType.IsEmpty()) { |
10392 | timedChannel->SetInitiatorType(initiatorType); |
10393 | } |
10394 | } |
10395 | |
10396 | nsCOMPtr<nsIURI> rpURI; |
10397 | aLoadInfo->GetResultPrincipalURI(getter_AddRefs(rpURI)); |
10398 | Maybe<nsCOMPtr<nsIURI>> originalResultPrincipalURI; |
10399 | aLoadState->GetMaybeResultPrincipalURI(originalResultPrincipalURI); |
10400 | if (originalResultPrincipalURI && |
10401 | (!aLoadState->KeepResultPrincipalURIIfSet() || !rpURI)) { |
10402 | // Unconditionally override, we want the replay to be equal to what has |
10403 | // been captured. |
10404 | aLoadInfo->SetResultPrincipalURI(originalResultPrincipalURI.ref()); |
10405 | } |
10406 | |
10407 | if (aLoadState->OriginalURI() && aLoadState->LoadReplace()) { |
10408 | // The LOAD_REPLACE flag and its handling here will be removed as part |
10409 | // of bug 1319110. For now preserve its restoration here to not break |
10410 | // any code expecting it being set specially on redirected channels. |
10411 | // If the flag has originally been set to change result of |
10412 | // NS_GetFinalChannelURI it won't have any effect and also won't cause |
10413 | // any harm. |
10414 | uint32_t loadFlags; |
10415 | aRv = channel->GetLoadFlags(&loadFlags); |
10416 | NS_ENSURE_SUCCESS(aRv, false)do { nsresult __rv = aRv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "aRv", "false", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 10416); return false; } } while (false); |
10417 | channel->SetLoadFlags(loadFlags | nsIChannel::LOAD_REPLACE); |
10418 | } |
10419 | |
10420 | nsCOMPtr<nsIContentSecurityPolicy> csp = aLoadState->Csp(); |
10421 | if (csp) { |
10422 | // Navigational requests that are same origin need to be upgraded in case |
10423 | // upgrade-insecure-requests is present. Please note that for document |
10424 | // navigations that bit is re-computed in case we encounter a server |
10425 | // side redirect so the navigation is not same-origin anymore. |
10426 | bool upgradeInsecureRequests = false; |
10427 | csp->GetUpgradeInsecureRequests(&upgradeInsecureRequests); |
10428 | if (upgradeInsecureRequests) { |
10429 | // only upgrade if the navigation is same origin |
10430 | nsCOMPtr<nsIPrincipal> resultPrincipal; |
10431 | aRv = nsContentUtils::GetSecurityManager()->GetChannelResultPrincipal( |
10432 | channel, getter_AddRefs(resultPrincipal)); |
10433 | NS_ENSURE_SUCCESS(aRv, false)do { nsresult __rv = aRv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "aRv", "false", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 10433); return false; } } while (false); |
10434 | if (nsContentSecurityUtils::IsConsideredSameOriginForUIR( |
10435 | aLoadState->TriggeringPrincipal(), resultPrincipal)) { |
10436 | aLoadInfo->SetUpgradeInsecureRequests(true); |
10437 | } |
10438 | } |
10439 | |
10440 | // For document loads we store the CSP that potentially needs to |
10441 | // be inherited by the new document, e.g. in case we are loading |
10442 | // an opaque origin like a data: URI. The actual inheritance |
10443 | // check happens within Document::InitCSP(). |
10444 | // Please create an actual copy of the CSP (do not share the same |
10445 | // reference) otherwise a Meta CSP of an opaque origin will |
10446 | // incorrectly be propagated to the embedding document. |
10447 | RefPtr<nsCSPContext> cspToInherit = new nsCSPContext(); |
10448 | cspToInherit->InitFromOther(static_cast<nsCSPContext*>(csp.get())); |
10449 | aLoadInfo->SetCSPToInherit(cspToInherit); |
10450 | } |
10451 | |
10452 | channel.forget(aChannel); |
10453 | return true; |
10454 | } |
10455 | |
10456 | bool nsDocShell::IsAboutBlankLoadOntoInitialAboutBlank( |
10457 | nsIURI* aURI, bool aInheritPrincipal, nsIPrincipal* aPrincipalToInherit) { |
10458 | return NS_IsAboutBlankAllowQueryAndFragment(aURI) && aInheritPrincipal && |
10459 | (aPrincipalToInherit == GetInheritedPrincipal(false)) && |
10460 | (!mDocumentViewer || !mDocumentViewer->GetDocument() || |
10461 | mDocumentViewer->GetDocument()->IsInitialDocument()); |
10462 | } |
10463 | |
10464 | nsresult nsDocShell::DoURILoad(nsDocShellLoadState* aLoadState, |
10465 | Maybe<uint32_t> aCacheKey, |
10466 | nsIRequest** aRequest) { |
10467 | // Double-check that we're still around to load this URI. |
10468 | if (mIsBeingDestroyed) { |
10469 | // Return NS_OK despite not doing anything to avoid throwing exceptions |
10470 | // from nsLocation::SetHref if the unload handler of the existing page |
10471 | // tears us down. |
10472 | return NS_OK; |
10473 | } |
10474 | |
10475 | nsCOMPtr<nsIURILoader> uriLoader = components::URILoader::Service(); |
10476 | if (NS_WARN_IF(!uriLoader)NS_warn_if_impl(!uriLoader, "!uriLoader", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 10476)) { |
10477 | return NS_ERROR_UNEXPECTED; |
10478 | } |
10479 | |
10480 | // Persist and sync layout history state before we load a new uri, as this |
10481 | // might be our last chance to do so, in the content process. |
10482 | PersistLayoutHistoryState(); |
10483 | SynchronizeLayoutHistoryState(); |
10484 | |
10485 | nsresult rv; |
10486 | nsContentPolicyType contentPolicyType = DetermineContentType(); |
10487 | |
10488 | if (IsSubframe()) { |
10489 | MOZ_ASSERT(contentPolicyType == nsIContentPolicy::TYPE_INTERNAL_IFRAME ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(contentPolicyType == nsIContentPolicy::TYPE_INTERNAL_IFRAME || contentPolicyType == nsIContentPolicy::TYPE_INTERNAL_FRAME )>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(contentPolicyType == nsIContentPolicy::TYPE_INTERNAL_IFRAME || contentPolicyType == nsIContentPolicy::TYPE_INTERNAL_FRAME ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "contentPolicyType == nsIContentPolicy::TYPE_INTERNAL_IFRAME || contentPolicyType == nsIContentPolicy::TYPE_INTERNAL_FRAME" " (" "DoURILoad thinks this is a frame and InternalLoad does not" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 10491 ); AnnotateMozCrashReason("MOZ_ASSERT" "(" "contentPolicyType == nsIContentPolicy::TYPE_INTERNAL_IFRAME || contentPolicyType == nsIContentPolicy::TYPE_INTERNAL_FRAME" ") (" "DoURILoad thinks this is a frame and InternalLoad does not" ")"); do { MOZ_CrashSequence(__null, 10491); __attribute__(( nomerge)) ::abort(); } while (false); } } while (false) |
10490 | contentPolicyType == nsIContentPolicy::TYPE_INTERNAL_FRAME,do { static_assert( mozilla::detail::AssertionConditionType< decltype(contentPolicyType == nsIContentPolicy::TYPE_INTERNAL_IFRAME || contentPolicyType == nsIContentPolicy::TYPE_INTERNAL_FRAME )>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(contentPolicyType == nsIContentPolicy::TYPE_INTERNAL_IFRAME || contentPolicyType == nsIContentPolicy::TYPE_INTERNAL_FRAME ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "contentPolicyType == nsIContentPolicy::TYPE_INTERNAL_IFRAME || contentPolicyType == nsIContentPolicy::TYPE_INTERNAL_FRAME" " (" "DoURILoad thinks this is a frame and InternalLoad does not" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 10491 ); AnnotateMozCrashReason("MOZ_ASSERT" "(" "contentPolicyType == nsIContentPolicy::TYPE_INTERNAL_IFRAME || contentPolicyType == nsIContentPolicy::TYPE_INTERNAL_FRAME" ") (" "DoURILoad thinks this is a frame and InternalLoad does not" ")"); do { MOZ_CrashSequence(__null, 10491); __attribute__(( nomerge)) ::abort(); } while (false); } } while (false) |
10491 | "DoURILoad thinks this is a frame and InternalLoad does not")do { static_assert( mozilla::detail::AssertionConditionType< decltype(contentPolicyType == nsIContentPolicy::TYPE_INTERNAL_IFRAME || contentPolicyType == nsIContentPolicy::TYPE_INTERNAL_FRAME )>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(contentPolicyType == nsIContentPolicy::TYPE_INTERNAL_IFRAME || contentPolicyType == nsIContentPolicy::TYPE_INTERNAL_FRAME ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "contentPolicyType == nsIContentPolicy::TYPE_INTERNAL_IFRAME || contentPolicyType == nsIContentPolicy::TYPE_INTERNAL_FRAME" " (" "DoURILoad thinks this is a frame and InternalLoad does not" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 10491 ); AnnotateMozCrashReason("MOZ_ASSERT" "(" "contentPolicyType == nsIContentPolicy::TYPE_INTERNAL_IFRAME || contentPolicyType == nsIContentPolicy::TYPE_INTERNAL_FRAME" ") (" "DoURILoad thinks this is a frame and InternalLoad does not" ")"); do { MOZ_CrashSequence(__null, 10491); __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
10492 | if (StaticPrefs::dom_block_external_protocol_in_iframes()) { |
10493 | // Only allow URLs able to return data in iframes. |
10494 | if (nsContentUtils::IsExternalProtocol(aLoadState->URI())) { |
10495 | // The context to check user-interaction with for the purposes of |
10496 | // popup-blocking. |
10497 | // |
10498 | // We generally want to check the context that initiated the navigation. |
10499 | WindowContext* sourceWindowContext = [&] { |
10500 | const MaybeDiscardedBrowsingContext& sourceBC = |
10501 | aLoadState->SourceBrowsingContext(); |
10502 | if (!sourceBC.IsNullOrDiscarded()) { |
10503 | if (WindowContext* wc = sourceBC.get()->GetCurrentWindowContext()) { |
10504 | return wc; |
10505 | } |
10506 | } |
10507 | return mBrowsingContext->GetParentWindowContext(); |
10508 | }(); |
10509 | |
10510 | MOZ_ASSERT(sourceWindowContext)do { static_assert( mozilla::detail::AssertionConditionType< decltype(sourceWindowContext)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(sourceWindowContext))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("sourceWindowContext" , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 10510); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sourceWindowContext" ")"); do { MOZ_CrashSequence(__null, 10510); __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
10511 | // FIXME: We can't check user-interaction against an OOP window. This is |
10512 | // the next best thing we can really do. The load state keeps whether |
10513 | // the navigation had a user interaction in process |
10514 | // (aLoadState->HasValidUserGestureActivation()), but we can't really |
10515 | // consume it, which we want to prevent popup-spamming from the same |
10516 | // click event. |
10517 | WindowContext* context = |
10518 | sourceWindowContext->IsInProcess() |
10519 | ? sourceWindowContext |
10520 | : mBrowsingContext->GetCurrentWindowContext(); |
10521 | const bool popupBlocked = [&] { |
10522 | const bool active = mBrowsingContext->IsActive(); |
10523 | |
10524 | // For same-origin-with-top windows, we grant a single free popup |
10525 | // without user activation, see bug 1680721. |
10526 | // |
10527 | // We consume the flag now even if there's no user activation. |
10528 | const bool hasFreePass = [&] { |
10529 | if (!active || |
10530 | !(context->IsInProcess() && context->SameOriginWithTop())) { |
10531 | return false; |
10532 | } |
10533 | nsGlobalWindowInner* win = |
10534 | context->TopWindowContext()->GetInnerWindow(); |
10535 | return win && win->TryOpenExternalProtocolIframe(); |
10536 | }(); |
10537 | |
10538 | if (context->IsInProcess() && |
10539 | context->ConsumeTransientUserGestureActivation()) { |
10540 | // If the user has interacted with the page, consume it. |
10541 | return false; |
10542 | } |
10543 | |
10544 | // TODO(emilio): Can we remove this check? It seems like what prompted |
10545 | // this code (bug 1514547) should be covered by transient user |
10546 | // activation, see bug 1514547. |
10547 | if (active && |
10548 | PopupBlocker::ConsumeTimerTokenForExternalProtocolIframe()) { |
10549 | return false; |
10550 | } |
10551 | |
10552 | if (sourceWindowContext->CanShowPopup()) { |
10553 | return false; |
10554 | } |
10555 | |
10556 | if (hasFreePass) { |
10557 | return false; |
10558 | } |
10559 | |
10560 | return true; |
10561 | }(); |
10562 | |
10563 | // No error must be returned when iframes are blocked. |
10564 | if (popupBlocked) { |
10565 | nsAutoString message; |
10566 | nsresult rv = nsContentUtils::GetLocalizedString( |
10567 | nsContentUtils::eDOM_PROPERTIES, |
10568 | "ExternalProtocolFrameBlockedNoUserActivation", message); |
10569 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) { |
10570 | nsContentUtils::ReportToConsoleByWindowID( |
10571 | message, nsIScriptError::warningFlag, "DOM"_ns, |
10572 | context->InnerWindowId()); |
10573 | } |
10574 | return NS_OK; |
10575 | } |
10576 | } |
10577 | } |
10578 | |
10579 | // Only allow view-source scheme in top-level docshells. view-source is |
10580 | // the only scheme to which this applies at the moment due to potential |
10581 | // timing attacks to read data from cross-origin iframes. If this widens |
10582 | // we should add a protocol flag for whether the scheme is allowed in |
10583 | // frames and use something like nsNetUtil::NS_URIChainHasFlags. |
10584 | nsCOMPtr<nsIURI> tempURI = aLoadState->URI(); |
10585 | nsCOMPtr<nsINestedURI> nestedURI = do_QueryInterface(tempURI); |
10586 | while (nestedURI) { |
10587 | // view-source should always be an nsINestedURI, loop and check the |
10588 | // scheme on this and all inner URIs that are also nested URIs. |
10589 | if (tempURI->SchemeIs("view-source")) { |
10590 | return NS_ERROR_UNKNOWN_PROTOCOL; |
10591 | } |
10592 | nestedURI->GetInnerURI(getter_AddRefs(tempURI)); |
10593 | nestedURI = do_QueryInterface(tempURI); |
10594 | } |
10595 | } else { |
10596 | MOZ_ASSERT(contentPolicyType == nsIContentPolicy::TYPE_DOCUMENT,do { static_assert( mozilla::detail::AssertionConditionType< decltype(contentPolicyType == nsIContentPolicy::TYPE_DOCUMENT )>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(contentPolicyType == nsIContentPolicy::TYPE_DOCUMENT ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "contentPolicyType == nsIContentPolicy::TYPE_DOCUMENT" " (" "DoURILoad thinks this is a document and InternalLoad does not" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 10597 ); AnnotateMozCrashReason("MOZ_ASSERT" "(" "contentPolicyType == nsIContentPolicy::TYPE_DOCUMENT" ") (" "DoURILoad thinks this is a document and InternalLoad does not" ")"); do { MOZ_CrashSequence(__null, 10597); __attribute__(( nomerge)) ::abort(); } while (false); } } while (false) |
10597 | "DoURILoad thinks this is a document and InternalLoad does not")do { static_assert( mozilla::detail::AssertionConditionType< decltype(contentPolicyType == nsIContentPolicy::TYPE_DOCUMENT )>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(contentPolicyType == nsIContentPolicy::TYPE_DOCUMENT ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "contentPolicyType == nsIContentPolicy::TYPE_DOCUMENT" " (" "DoURILoad thinks this is a document and InternalLoad does not" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 10597 ); AnnotateMozCrashReason("MOZ_ASSERT" "(" "contentPolicyType == nsIContentPolicy::TYPE_DOCUMENT" ") (" "DoURILoad thinks this is a document and InternalLoad does not" ")"); do { MOZ_CrashSequence(__null, 10597); __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
10598 | } |
10599 | |
10600 | // We want to inherit aLoadState->PrincipalToInherit() when: |
10601 | // 1. ChannelShouldInheritPrincipal returns true. |
10602 | // 2. aLoadState->URI() is not data: URI, or data: URI is not |
10603 | // configured as unique opaque origin. |
10604 | bool inheritPrincipal = false; |
10605 | |
10606 | nsCOMPtr<nsIURI> uri = aLoadState->URI(); |
10607 | if (aLoadState->PrincipalToInherit()) { |
10608 | bool isSrcdoc = |
10609 | aLoadState->HasInternalLoadFlags(INTERNAL_LOAD_FLAGS_IS_SRCDOC); |
10610 | bool inheritAttrs = nsContentUtils::ChannelShouldInheritPrincipal( |
10611 | aLoadState->PrincipalToInherit(), uri, |
10612 | true, // aInheritForAboutBlank |
10613 | isSrcdoc); |
10614 | |
10615 | inheritPrincipal = inheritAttrs && !uri->SchemeIs("data"); |
10616 | } |
10617 | |
10618 | // See https://bugzilla.mozilla.org/show_bug.cgi?id=1736570 |
10619 | const bool isAboutBlankLoadOntoInitialAboutBlank = |
10620 | IsAboutBlankLoadOntoInitialAboutBlank(uri, inheritPrincipal, |
10621 | aLoadState->PrincipalToInherit()); |
10622 | |
10623 | // FIXME We still have a ton of codepaths that don't pass through |
10624 | // DocumentLoadListener, so probably need to create session history info |
10625 | // in more places. |
10626 | if (aLoadState->GetLoadingSessionHistoryInfo()) { |
10627 | SetLoadingSessionHistoryInfo(*aLoadState->GetLoadingSessionHistoryInfo()); |
10628 | } else if (isAboutBlankLoadOntoInitialAboutBlank && |
10629 | mozilla::SessionHistoryInParent()) { |
10630 | // Materialize LoadingSessionHistoryInfo here, because DocumentChannel |
10631 | // loads have it, and later history behavior depends on it existing. |
10632 | UniquePtr<SessionHistoryInfo> entry = MakeUnique<SessionHistoryInfo>( |
10633 | uri, aLoadState->TriggeringPrincipal(), |
10634 | aLoadState->PrincipalToInherit(), |
10635 | aLoadState->PartitionedPrincipalToInherit(), aLoadState->Csp(), |
10636 | mContentTypeHint); |
10637 | mozilla::dom::LoadingSessionHistoryInfo info(*entry); |
10638 | SetLoadingSessionHistoryInfo(info, true); |
10639 | } |
10640 | |
10641 | // open a channel for the url |
10642 | |
10643 | // If we have a pending channel, use the channel we've already created here. |
10644 | // We don't need to set up load flags for our channel, as it has already been |
10645 | // created. |
10646 | |
10647 | if (nsCOMPtr<nsIChannel> channel = |
10648 | aLoadState->GetPendingRedirectedChannel()) { |
10649 | // If we have a request outparameter, shove our channel into it. |
10650 | if (aRequest) { |
10651 | nsCOMPtr<nsIRequest> outRequest = channel; |
10652 | outRequest.forget(aRequest); |
10653 | } |
10654 | |
10655 | return OpenRedirectedChannel(aLoadState); |
10656 | } |
10657 | |
10658 | // There are two cases we care about: |
10659 | // * Top-level load: In this case, loadingNode is null, but loadingWindow |
10660 | // is our mScriptGlobal. We pass null for loadingPrincipal in this case. |
10661 | // * Subframe load: loadingWindow is null, but loadingNode is the frame |
10662 | // element for the load. loadingPrincipal is the NodePrincipal of the |
10663 | // frame element. |
10664 | nsCOMPtr<nsINode> loadingNode; |
10665 | nsCOMPtr<nsPIDOMWindowOuter> loadingWindow; |
10666 | nsCOMPtr<nsIPrincipal> loadingPrincipal; |
10667 | nsCOMPtr<nsISupports> topLevelLoadingContext; |
10668 | |
10669 | if (contentPolicyType == nsIContentPolicy::TYPE_DOCUMENT) { |
10670 | loadingNode = nullptr; |
10671 | loadingPrincipal = nullptr; |
10672 | loadingWindow = mScriptGlobal; |
10673 | if (XRE_IsContentProcess()) { |
10674 | // In e10s the child process doesn't have access to the element that |
10675 | // contains the browsing context (because that element is in the chrome |
10676 | // process). |
10677 | nsCOMPtr<nsIBrowserChild> browserChild = GetBrowserChild(); |
10678 | topLevelLoadingContext = ToSupports(browserChild); |
10679 | } else { |
10680 | // This is for loading non-e10s tabs and toplevel windows of various |
10681 | // sorts. |
10682 | // For the toplevel window cases, requestingElement will be null. |
10683 | nsCOMPtr<Element> requestingElement = |
10684 | loadingWindow->GetFrameElementInternal(); |
10685 | topLevelLoadingContext = requestingElement; |
10686 | } |
10687 | } else { |
10688 | loadingWindow = nullptr; |
10689 | loadingNode = mScriptGlobal->GetFrameElementInternal(); |
10690 | if (loadingNode) { |
10691 | // If we have a loading node, then use that as our loadingPrincipal. |
10692 | loadingPrincipal = loadingNode->NodePrincipal(); |
10693 | #ifdef DEBUG1 |
10694 | // Get the docshell type for requestingElement. |
10695 | RefPtr<Document> requestingDoc = loadingNode->OwnerDoc(); |
10696 | nsCOMPtr<nsIDocShell> elementDocShell = requestingDoc->GetDocShell(); |
10697 | // requestingElement docshell type = current docshell type. |
10698 | MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType< decltype(mItemType == elementDocShell->ItemType())>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(mItemType == elementDocShell->ItemType()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mItemType == elementDocShell->ItemType()" " (" "subframes should have the same docshell type as their parent" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 10700 ); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mItemType == elementDocShell->ItemType()" ") (" "subframes should have the same docshell type as their parent" ")"); do { MOZ_CrashSequence(__null, 10700); __attribute__(( nomerge)) ::abort(); } while (false); } } while (false) |
10699 | mItemType == elementDocShell->ItemType(),do { static_assert( mozilla::detail::AssertionConditionType< decltype(mItemType == elementDocShell->ItemType())>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(mItemType == elementDocShell->ItemType()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mItemType == elementDocShell->ItemType()" " (" "subframes should have the same docshell type as their parent" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 10700 ); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mItemType == elementDocShell->ItemType()" ") (" "subframes should have the same docshell type as their parent" ")"); do { MOZ_CrashSequence(__null, 10700); __attribute__(( nomerge)) ::abort(); } while (false); } } while (false) |
10700 | "subframes should have the same docshell type as their parent")do { static_assert( mozilla::detail::AssertionConditionType< decltype(mItemType == elementDocShell->ItemType())>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(mItemType == elementDocShell->ItemType()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mItemType == elementDocShell->ItemType()" " (" "subframes should have the same docshell type as their parent" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 10700 ); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mItemType == elementDocShell->ItemType()" ") (" "subframes should have the same docshell type as their parent" ")"); do { MOZ_CrashSequence(__null, 10700); __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
10701 | #endif |
10702 | } else { |
10703 | if (mIsBeingDestroyed) { |
10704 | // If this isn't a top-level load and mScriptGlobal's frame element is |
10705 | // null, then the element got removed from the DOM while we were trying |
10706 | // to load this resource. This docshell is scheduled for destruction |
10707 | // already, so bail out here. |
10708 | return NS_OK; |
10709 | } |
10710 | // If we are not being destroyed and we do not have access to the loading |
10711 | // node, then we are a remote subframe. Set the loading principal |
10712 | // to be a null principal and then set it correctly in the parent. |
10713 | loadingPrincipal = NullPrincipal::Create(GetOriginAttributes(), nullptr); |
10714 | } |
10715 | } |
10716 | |
10717 | if (!aLoadState->TriggeringPrincipal()) { |
10718 | MOZ_ASSERT(false, "DoURILoad needs a valid triggeringPrincipal")do { static_assert( mozilla::detail::AssertionConditionType< decltype(false)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("false" " (" "DoURILoad needs a valid triggeringPrincipal" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 10718 ); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "DoURILoad needs a valid triggeringPrincipal" ")"); do { MOZ_CrashSequence(__null, 10718); __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
10719 | return NS_ERROR_FAILURE; |
10720 | } |
10721 | |
10722 | uint32_t sandboxFlags = mBrowsingContext->GetSandboxFlags(); |
10723 | nsSecurityFlags securityFlags = |
10724 | nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL; |
10725 | |
10726 | if (mLoadType == LOAD_ERROR_PAGE) { |
10727 | securityFlags |= nsILoadInfo::SEC_LOAD_ERROR_PAGE; |
10728 | } |
10729 | |
10730 | if (inheritPrincipal) { |
10731 | securityFlags |= nsILoadInfo::SEC_FORCE_INHERIT_PRINCIPAL; |
10732 | } |
10733 | |
10734 | // Must never have a parent for TYPE_DOCUMENT loads |
10735 | MOZ_ASSERT_IF(contentPolicyType == nsIContentPolicy::TYPE_DOCUMENT,do { if (contentPolicyType == nsIContentPolicy::TYPE_DOCUMENT ) { do { static_assert( mozilla::detail::AssertionConditionType <decltype(!mBrowsingContext->GetParent())>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(! !(!mBrowsingContext->GetParent()))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("!mBrowsingContext->GetParent()" , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 10736); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mBrowsingContext->GetParent()" ")"); do { MOZ_CrashSequence(__null, 10736); __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); } } while (false) |
10736 | !mBrowsingContext->GetParent())do { if (contentPolicyType == nsIContentPolicy::TYPE_DOCUMENT ) { do { static_assert( mozilla::detail::AssertionConditionType <decltype(!mBrowsingContext->GetParent())>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(! !(!mBrowsingContext->GetParent()))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("!mBrowsingContext->GetParent()" , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 10736); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mBrowsingContext->GetParent()" ")"); do { MOZ_CrashSequence(__null, 10736); __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); } } while (false); |
10737 | // Subdocuments must have a parent |
10738 | MOZ_ASSERT_IF(contentPolicyType == nsIContentPolicy::TYPE_SUBDOCUMENT,do { if (contentPolicyType == nsIContentPolicy::TYPE_SUBDOCUMENT ) { do { static_assert( mozilla::detail::AssertionConditionType <decltype(mBrowsingContext->GetParent())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mBrowsingContext->GetParent ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("mBrowsingContext->GetParent()", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 10739); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mBrowsingContext->GetParent()" ")"); do { MOZ_CrashSequence(__null, 10739); __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); } } while (false) |
10739 | mBrowsingContext->GetParent())do { if (contentPolicyType == nsIContentPolicy::TYPE_SUBDOCUMENT ) { do { static_assert( mozilla::detail::AssertionConditionType <decltype(mBrowsingContext->GetParent())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mBrowsingContext->GetParent ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("mBrowsingContext->GetParent()", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 10739); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mBrowsingContext->GetParent()" ")"); do { MOZ_CrashSequence(__null, 10739); __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); } } while (false); |
10740 | mBrowsingContext->SetTriggeringAndInheritPrincipals( |
10741 | aLoadState->TriggeringPrincipal(), aLoadState->PrincipalToInherit(), |
10742 | aLoadState->GetLoadIdentifier()); |
10743 | RefPtr<LoadInfo> loadInfo; |
10744 | if (contentPolicyType == nsIContentPolicy::TYPE_DOCUMENT) { |
10745 | loadInfo = |
10746 | new LoadInfo(loadingWindow, uri, aLoadState->TriggeringPrincipal(), |
10747 | topLevelLoadingContext, securityFlags, sandboxFlags); |
10748 | } else { |
10749 | loadInfo = MOZ_TRY(LoadInfo::Create(__extension__({ auto mozTryVarTempResult = ::mozilla::ToResult (LoadInfo::Create( loadingPrincipal, aLoadState->TriggeringPrincipal (), loadingNode, securityFlags, contentPolicyType, Maybe<mozilla ::dom::ClientInfo>(), Maybe<mozilla::dom::ServiceWorkerDescriptor >(), sandboxFlags)); if ((__builtin_expect(!!(mozTryVarTempResult .isErr()), 0))) { return mozTryVarTempResult.propagateErr(); } mozTryVarTempResult.unwrap(); }) |
10750 | loadingPrincipal, aLoadState->TriggeringPrincipal(), loadingNode,__extension__({ auto mozTryVarTempResult = ::mozilla::ToResult (LoadInfo::Create( loadingPrincipal, aLoadState->TriggeringPrincipal (), loadingNode, securityFlags, contentPolicyType, Maybe<mozilla ::dom::ClientInfo>(), Maybe<mozilla::dom::ServiceWorkerDescriptor >(), sandboxFlags)); if ((__builtin_expect(!!(mozTryVarTempResult .isErr()), 0))) { return mozTryVarTempResult.propagateErr(); } mozTryVarTempResult.unwrap(); }) |
10751 | securityFlags, contentPolicyType, Maybe<mozilla::dom::ClientInfo>(),__extension__({ auto mozTryVarTempResult = ::mozilla::ToResult (LoadInfo::Create( loadingPrincipal, aLoadState->TriggeringPrincipal (), loadingNode, securityFlags, contentPolicyType, Maybe<mozilla ::dom::ClientInfo>(), Maybe<mozilla::dom::ServiceWorkerDescriptor >(), sandboxFlags)); if ((__builtin_expect(!!(mozTryVarTempResult .isErr()), 0))) { return mozTryVarTempResult.propagateErr(); } mozTryVarTempResult.unwrap(); }) |
10752 | Maybe<mozilla::dom::ServiceWorkerDescriptor>(), sandboxFlags))__extension__({ auto mozTryVarTempResult = ::mozilla::ToResult (LoadInfo::Create( loadingPrincipal, aLoadState->TriggeringPrincipal (), loadingNode, securityFlags, contentPolicyType, Maybe<mozilla ::dom::ClientInfo>(), Maybe<mozilla::dom::ServiceWorkerDescriptor >(), sandboxFlags)); if ((__builtin_expect(!!(mozTryVarTempResult .isErr()), 0))) { return mozTryVarTempResult.propagateErr(); } mozTryVarTempResult.unwrap(); }); |
10753 | } |
10754 | RefPtr<WindowContext> context = mBrowsingContext->GetCurrentWindowContext(); |
10755 | |
10756 | if (isAboutBlankLoadOntoInitialAboutBlank) { |
10757 | // Match the DocumentChannel case where the default for third-partiness |
10758 | // differs from the default in LoadInfo construction here. |
10759 | // toolkit/components/antitracking/test/browser/browser_aboutblank.js |
10760 | // fails without this. |
10761 | BrowsingContext* top = mBrowsingContext->Top(); |
10762 | if (top == mBrowsingContext) { |
10763 | // If we're at the top, this must be a window.open()ed |
10764 | // window, and we can't be third-party relative to ourselves. |
10765 | loadInfo->SetIsThirdPartyContextToTopWindow(false); |
10766 | } else { |
10767 | if (Document* topDoc = top->GetDocument()) { |
10768 | bool thirdParty = false; |
10769 | mozilla::Unused << topDoc->GetPrincipal()->IsThirdPartyPrincipal( |
10770 | aLoadState->PrincipalToInherit(), &thirdParty); |
10771 | loadInfo->SetIsThirdPartyContextToTopWindow(thirdParty); |
10772 | } else { |
10773 | // If top is in a different process, we have to be third-party relative |
10774 | // to it. |
10775 | loadInfo->SetIsThirdPartyContextToTopWindow(true); |
10776 | } |
10777 | } |
10778 | } |
10779 | |
10780 | if (mLoadType != LOAD_ERROR_PAGE && context && context->IsInProcess()) { |
10781 | if (context->HasValidTransientUserGestureActivation()) { |
10782 | aLoadState->SetHasValidUserGestureActivation(true); |
10783 | aLoadState->SetTextDirectiveUserActivation(true); |
10784 | } |
10785 | if (!aLoadState->TriggeringWindowId()) { |
10786 | aLoadState->SetTriggeringWindowId(context->Id()); |
10787 | } |
10788 | if (!aLoadState->TriggeringStorageAccess()) { |
10789 | Document* contextDoc = context->GetExtantDoc(); |
10790 | if (contextDoc) { |
10791 | aLoadState->SetTriggeringStorageAccess( |
10792 | contextDoc->UsingStorageAccess()); |
10793 | } |
10794 | } |
10795 | } |
10796 | |
10797 | // in case this docshell load was triggered by a valid transient user gesture, |
10798 | // or also the load originates from external, then we pass that information on |
10799 | // to the loadinfo, which allows e.g. setting Sec-Fetch-User request headers. |
10800 | if (aLoadState->HasValidUserGestureActivation() || |
10801 | aLoadState->HasLoadFlags(LOAD_FLAGS_FROM_EXTERNAL)) { |
10802 | loadInfo->SetHasValidUserGestureActivation(true); |
10803 | aLoadState->SetTextDirectiveUserActivation(true); |
10804 | } |
10805 | |
10806 | loadInfo->SetTextDirectiveUserActivation( |
10807 | aLoadState->GetTextDirectiveUserActivation()); |
10808 | |
10809 | loadInfo->SetTriggeringWindowId(aLoadState->TriggeringWindowId()); |
10810 | loadInfo->SetTriggeringStorageAccess(aLoadState->TriggeringStorageAccess()); |
10811 | loadInfo->SetTriggeringSandboxFlags(aLoadState->TriggeringSandboxFlags()); |
10812 | net::ClassificationFlags flags = aLoadState->TriggeringClassificationFlags(); |
10813 | loadInfo->SetTriggeringFirstPartyClassificationFlags(flags.firstPartyFlags); |
10814 | loadInfo->SetTriggeringThirdPartyClassificationFlags(flags.thirdPartyFlags); |
10815 | loadInfo->SetIsMetaRefresh(aLoadState->IsMetaRefresh()); |
10816 | |
10817 | uint32_t cacheKey = 0; |
10818 | if (aCacheKey) { |
10819 | cacheKey = *aCacheKey; |
10820 | } else if (mozilla::SessionHistoryInParent()) { |
10821 | if (mLoadingEntry) { |
10822 | cacheKey = mLoadingEntry->mInfo.GetCacheKey(); |
10823 | } else if (mActiveEntry) { // for reload cases |
10824 | cacheKey = mActiveEntry->GetCacheKey(); |
10825 | } |
10826 | } else { |
10827 | if (mLSHE) { |
10828 | cacheKey = mLSHE->GetCacheKey(); |
10829 | } else if (mOSHE) { // for reload cases |
10830 | cacheKey = mOSHE->GetCacheKey(); |
10831 | } |
10832 | } |
10833 | |
10834 | bool uriModified; |
10835 | if (mLSHE || mLoadingEntry) { |
10836 | if (mLoadingEntry) { |
10837 | uriModified = mLoadingEntry->mInfo.GetURIWasModified(); |
10838 | } else { |
10839 | uriModified = mLSHE->GetURIWasModified(); |
10840 | } |
10841 | } else { |
10842 | uriModified = false; |
10843 | } |
10844 | |
10845 | bool isEmbeddingBlockedError = false; |
10846 | if (mFailedChannel) { |
10847 | nsresult status; |
10848 | mFailedChannel->GetStatus(&status); |
10849 | isEmbeddingBlockedError = status == NS_ERROR_XFO_VIOLATION || |
10850 | status == NS_ERROR_CSP_FRAME_ANCESTOR_VIOLATION; |
10851 | } |
10852 | |
10853 | nsLoadFlags loadFlags = aLoadState->CalculateChannelLoadFlags( |
10854 | mBrowsingContext, uriModified, Some(isEmbeddingBlockedError)); |
10855 | |
10856 | nsCOMPtr<nsIChannel> channel; |
10857 | if (DocumentChannel::CanUseDocumentChannel(uri) && |
10858 | !isAboutBlankLoadOntoInitialAboutBlank) { |
10859 | channel = DocumentChannel::CreateForDocument( |
10860 | aLoadState, loadInfo, loadFlags, this, cacheKey, uriModified, |
10861 | isEmbeddingBlockedError); |
10862 | MOZ_ASSERT(channel)do { static_assert( mozilla::detail::AssertionConditionType< decltype(channel)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(channel))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("channel", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 10862); AnnotateMozCrashReason("MOZ_ASSERT" "(" "channel" ")" ); do { MOZ_CrashSequence(__null, 10862); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
10863 | |
10864 | // Disable keyword fixup when using DocumentChannel, since |
10865 | // DocumentLoadListener will handle this for us (in the parent process). |
10866 | mAllowKeywordFixup = false; |
10867 | } else if (!CreateAndConfigureRealChannelForLoadState( |
10868 | mBrowsingContext, aLoadState, loadInfo, this, this, |
10869 | GetOriginAttributes(), loadFlags, cacheKey, rv, |
10870 | getter_AddRefs(channel))) { |
10871 | return rv; |
10872 | } |
10873 | |
10874 | // Make sure to give the caller a channel if we managed to create one |
10875 | // This is important for correct error page/session history interaction |
10876 | if (aRequest) { |
10877 | NS_ADDREF(*aRequest = channel)(*aRequest = channel)->AddRef(); |
10878 | } |
10879 | |
10880 | const nsACString& typeHint = aLoadState->TypeHint(); |
10881 | if (!typeHint.IsVoid()) { |
10882 | mContentTypeHint = typeHint; |
10883 | } else { |
10884 | mContentTypeHint.Truncate(); |
10885 | } |
10886 | |
10887 | // Load attributes depend on load type... |
10888 | if (mLoadType == LOAD_RELOAD_CHARSET_CHANGE) { |
10889 | // Use SetAllowStaleCacheContent (not LOAD_FROM_CACHE flag) since we |
10890 | // only want to force cache load for this channel, not the whole |
10891 | // loadGroup. |
10892 | nsCOMPtr<nsICacheInfoChannel> cachingChannel = do_QueryInterface(channel); |
10893 | if (cachingChannel) { |
10894 | cachingChannel->SetAllowStaleCacheContent(true); |
10895 | } |
10896 | } |
10897 | |
10898 | uint32_t openFlags = |
10899 | nsDocShell::ComputeURILoaderFlags(mBrowsingContext, mLoadType); |
10900 | return OpenInitializedChannel(channel, uriLoader, openFlags); |
10901 | } |
10902 | |
10903 | static nsresult AppendSegmentToString(nsIInputStream* aIn, void* aClosure, |
10904 | const char* aFromRawSegment, |
10905 | uint32_t aToOffset, uint32_t aCount, |
10906 | uint32_t* aWriteCount) { |
10907 | // aFromSegment now contains aCount bytes of data. |
10908 | |
10909 | nsAutoCString* buf = static_cast<nsAutoCString*>(aClosure); |
10910 | buf->Append(aFromRawSegment, aCount); |
10911 | |
10912 | // Indicate that we have consumed all of aFromSegment |
10913 | *aWriteCount = aCount; |
10914 | return NS_OK; |
10915 | } |
10916 | |
10917 | /* static */ nsresult nsDocShell::AddHeadersToChannel( |
10918 | nsIInputStream* aHeadersData, nsIChannel* aGenericChannel) { |
10919 | nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aGenericChannel); |
10920 | NS_ENSURE_STATE(httpChannel)do { if ((__builtin_expect(!!(!(httpChannel)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "httpChannel" ") failed" , nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 10920); return NS_ERROR_UNEXPECTED; } } while (false); |
10921 | |
10922 | uint32_t numRead; |
10923 | nsAutoCString headersString; |
10924 | nsresult rv = aHeadersData->ReadSegments( |
10925 | AppendSegmentToString, &headersString, UINT32_MAX(4294967295U), &numRead); |
10926 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 10926); return rv; } } while (false); |
10927 | |
10928 | // used during the manipulation of the String from the InputStream |
10929 | nsAutoCString headerName; |
10930 | nsAutoCString headerValue; |
10931 | int32_t crlf; |
10932 | int32_t colon; |
10933 | |
10934 | // |
10935 | // Iterate over the headersString: for each "\r\n" delimited chunk, |
10936 | // add the value as a header to the nsIHttpChannel |
10937 | // |
10938 | |
10939 | static const char kWhitespace[] = "\b\t\r\n "; |
10940 | while (true) { |
10941 | crlf = headersString.Find("\r\n"); |
10942 | if (crlf == kNotFound) { |
10943 | return NS_OK; |
10944 | } |
10945 | |
10946 | const nsACString& oneHeader = StringHead(headersString, crlf); |
10947 | |
10948 | colon = oneHeader.FindChar(':'); |
10949 | if (colon == kNotFound) { |
10950 | return NS_ERROR_UNEXPECTED; |
10951 | } |
10952 | |
10953 | headerName = StringHead(oneHeader, colon); |
10954 | headerValue = Substring(oneHeader, colon + 1); |
10955 | |
10956 | headerName.Trim(kWhitespace); |
10957 | headerValue.Trim(kWhitespace); |
10958 | |
10959 | headersString.Cut(0, crlf + 2); |
10960 | |
10961 | // |
10962 | // FINALLY: we can set the header! |
10963 | // |
10964 | |
10965 | rv = httpChannel->SetRequestHeader(headerName, headerValue, true); |
10966 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 10966); return rv; } } while (false); |
10967 | } |
10968 | |
10969 | MOZ_ASSERT_UNREACHABLE("oops")do { static_assert( mozilla::detail::AssertionConditionType< decltype(false)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: " "oops" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 10969); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: " "oops" ")"); do { MOZ_CrashSequence (__null, 10969); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); |
10970 | return NS_ERROR_UNEXPECTED; |
10971 | } |
10972 | |
10973 | /* static */ uint32_t nsDocShell::ComputeURILoaderFlags( |
10974 | BrowsingContext* aBrowsingContext, uint32_t aLoadType, |
10975 | bool aIsDocumentLoad) { |
10976 | MOZ_ASSERT(aBrowsingContext)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aBrowsingContext)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aBrowsingContext))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aBrowsingContext" , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 10976); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aBrowsingContext" ")" ); do { MOZ_CrashSequence(__null, 10976); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
10977 | |
10978 | uint32_t openFlags = 0; |
10979 | if (aLoadType == LOAD_LINK) { |
10980 | openFlags |= nsIURILoader::IS_CONTENT_PREFERRED; |
10981 | } |
10982 | if (!aBrowsingContext->GetAllowContentRetargeting()) { |
10983 | openFlags |= nsIURILoader::DONT_RETARGET; |
10984 | } |
10985 | |
10986 | if (!aIsDocumentLoad) { |
10987 | openFlags |= nsIURILoader::IS_OBJECT_EMBED; |
10988 | |
10989 | // Unless the pref is set, object/embed loads always specify DONT_RETARGET. |
10990 | // See bug 1868001 for details. |
10991 | if (!StaticPrefs::dom_navigation_object_embed_allow_retargeting()) { |
10992 | openFlags |= nsIURILoader::DONT_RETARGET; |
10993 | } |
10994 | } |
10995 | |
10996 | return openFlags; |
10997 | } |
10998 | |
10999 | nsresult nsDocShell::OpenInitializedChannel(nsIChannel* aChannel, |
11000 | nsIURILoader* aURILoader, |
11001 | uint32_t aOpenFlags) { |
11002 | nsresult rv = NS_OK; |
11003 | |
11004 | // If anything fails here, make sure to clear our initial ClientSource. |
11005 | auto cleanupInitialClient = |
11006 | MakeScopeExit([&] { mInitialClientSource.reset(); }); |
11007 | |
11008 | nsCOMPtr<nsPIDOMWindowOuter> win = GetWindow(); |
11009 | NS_ENSURE_TRUE(win, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(win)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING , "NS_ENSURE_TRUE(" "win" ") failed", nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 11009); return NS_ERROR_FAILURE; } } while (false); |
11010 | |
11011 | MaybeCreateInitialClientSource(); |
11012 | |
11013 | // Let the client channel helper know if we are using DocumentChannel, |
11014 | // since redirects get handled in the parent process in that case. |
11015 | RefPtr<net::DocumentChannel> docChannel = do_QueryObject(aChannel); |
11016 | if (docChannel && XRE_IsContentProcess()) { |
11017 | // Tell the content process nsDocumentOpenInfo to not try to do |
11018 | // any sort of targeting. |
11019 | aOpenFlags |= nsIURILoader::DONT_RETARGET; |
11020 | } |
11021 | |
11022 | // Since we are loading a document we need to make sure the proper reserved |
11023 | // and initial client data is stored on the nsILoadInfo. The |
11024 | // ClientChannelHelper does this and ensures that it is propagated properly |
11025 | // on redirects. We pass no reserved client here so that the helper will |
11026 | // create the reserved ClientSource if necessary. |
11027 | Maybe<ClientInfo> noReservedClient; |
11028 | if (docChannel) { |
11029 | // When using DocumentChannel, all redirect handling is done in the parent, |
11030 | // so we just need the child variant to watch for the internal redirect |
11031 | // to the final channel. |
11032 | rv = AddClientChannelHelperInChild(aChannel, |
11033 | GetMainThreadSerialEventTarget()); |
11034 | docChannel->SetInitialClientInfo(GetInitialClientInfo()); |
11035 | } else { |
11036 | rv = AddClientChannelHelper(aChannel, std::move(noReservedClient), |
11037 | GetInitialClientInfo(), |
11038 | GetMainThreadSerialEventTarget()); |
11039 | } |
11040 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 11040); return rv; } } while (false); |
11041 | |
11042 | rv = aURILoader->OpenURI(aChannel, aOpenFlags, this); |
11043 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 11043); return rv; } } while (false); |
11044 | |
11045 | // We're about to load a new page and it may take time before necko |
11046 | // gives back any data, so main thread might have a chance to process a |
11047 | // collector slice |
11048 | nsJSContext::MaybeRunNextCollectorSlice(this, JS::GCReason::DOCSHELL); |
11049 | |
11050 | // Success. Keep the initial ClientSource if it exists. |
11051 | cleanupInitialClient.release(); |
11052 | |
11053 | return NS_OK; |
11054 | } |
11055 | |
11056 | nsresult nsDocShell::OpenRedirectedChannel(nsDocShellLoadState* aLoadState) { |
11057 | nsCOMPtr<nsIChannel> channel = aLoadState->GetPendingRedirectedChannel(); |
11058 | MOZ_ASSERT(channel)do { static_assert( mozilla::detail::AssertionConditionType< decltype(channel)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(channel))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("channel", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 11058); AnnotateMozCrashReason("MOZ_ASSERT" "(" "channel" ")" ); do { MOZ_CrashSequence(__null, 11058); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
11059 | |
11060 | // If anything fails here, make sure to clear our initial ClientSource. |
11061 | auto cleanupInitialClient = |
11062 | MakeScopeExit([&] { mInitialClientSource.reset(); }); |
11063 | |
11064 | nsCOMPtr<nsPIDOMWindowOuter> win = GetWindow(); |
11065 | NS_ENSURE_TRUE(win, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(win)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING , "NS_ENSURE_TRUE(" "win" ") failed", nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 11065); return NS_ERROR_FAILURE; } } while (false); |
11066 | |
11067 | MaybeCreateInitialClientSource(); |
11068 | |
11069 | nsCOMPtr<nsILoadInfo> loadInfo = channel->LoadInfo(); |
11070 | |
11071 | LoadInfo* li = static_cast<LoadInfo*>(loadInfo.get()); |
11072 | if (loadInfo->GetExternalContentPolicyType() == |
11073 | ExtContentPolicy::TYPE_DOCUMENT) { |
11074 | li->UpdateBrowsingContextID(mBrowsingContext->Id()); |
11075 | } else if (loadInfo->GetExternalContentPolicyType() == |
11076 | ExtContentPolicy::TYPE_SUBDOCUMENT) { |
11077 | li->UpdateFrameBrowsingContextID(mBrowsingContext->Id()); |
11078 | } |
11079 | |
11080 | // If we did a process switch, then we should have an existing allocated |
11081 | // ClientInfo, so we just need to allocate a corresponding ClientSource. |
11082 | CreateReservedSourceIfNeeded(channel, GetMainThreadSerialEventTarget()); |
11083 | |
11084 | uint32_t documentOpenInfoFlags = nsIURILoader::DONT_RETARGET; |
11085 | if (loadInfo->GetExternalContentPolicyType() == |
11086 | ExtContentPolicy::TYPE_OBJECT) { |
11087 | documentOpenInfoFlags |= nsIURILoader::IS_OBJECT_EMBED; |
11088 | } |
11089 | |
11090 | RefPtr<nsDocumentOpenInfo> loader = |
11091 | new nsDocumentOpenInfo(this, documentOpenInfoFlags, nullptr); |
11092 | channel->SetLoadGroup(mLoadGroup); |
11093 | |
11094 | MOZ_ALWAYS_SUCCEEDS(loader->Prepare())do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl (loader->Prepare())), 1)))), 1))) { } else { do { do { } while (false); MOZ_ReportCrash("" "NS_SUCCEEDED(loader->Prepare())" , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 11094); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(loader->Prepare())" ")"); do { MOZ_CrashSequence(__null, 11094); __attribute__(( nomerge)) ::abort(); } while (false); } while (false); } } while (false); |
11095 | |
11096 | nsresult rv = NS_OK; |
11097 | if (XRE_IsParentProcess()) { |
11098 | // If we're in the parent, the we don't have an nsIChildChannel, just |
11099 | // the original channel, which is already open in this process. |
11100 | |
11101 | // DocumentLoadListener expects to get an nsIParentChannel, so |
11102 | // we create a wrapper around the channel and nsIStreamListener |
11103 | // that forwards functionality as needed, and then we register |
11104 | // it under the provided identifier. |
11105 | RefPtr<ParentChannelWrapper> wrapper = |
11106 | new ParentChannelWrapper(channel, loader); |
11107 | wrapper->Register(aLoadState->GetPendingRedirectChannelRegistrarId()); |
11108 | |
11109 | mLoadGroup->AddRequest(channel, nullptr); |
11110 | } else if (nsCOMPtr<nsIChildChannel> childChannel = |
11111 | do_QueryInterface(channel)) { |
11112 | // Our channel was redirected from another process, so doesn't need to |
11113 | // be opened again. However, it does need its listener hooked up |
11114 | // correctly. |
11115 | rv = childChannel->CompleteRedirectSetup(loader); |
11116 | } else { |
11117 | // It's possible for the redirected channel to not implement |
11118 | // nsIChildChannel and be entirely local (like srcdoc). In that case we |
11119 | // can just open the local instance and it will work. |
11120 | rv = channel->AsyncOpen(loader); |
11121 | } |
11122 | if (rv == NS_ERROR_NO_CONTENT) { |
11123 | return NS_OK; |
11124 | } |
11125 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 11125); return rv; } } while (false); |
11126 | |
11127 | // Success. Keep the initial ClientSource if it exists. |
11128 | cleanupInitialClient.release(); |
11129 | return NS_OK; |
11130 | } |
11131 | |
11132 | // https://html.spec.whatwg.org/#scrolling-to-a-fragment |
11133 | nsresult nsDocShell::ScrollToAnchor(bool aCurHasRef, bool aNewHasRef, |
11134 | nsACString& aNewHash, uint32_t aLoadType) { |
11135 | if (!mCurrentURI) { |
11136 | return NS_OK; |
11137 | } |
11138 | |
11139 | RefPtr<PresShell> presShell = GetPresShell(); |
11140 | if (!presShell) { |
11141 | // If we failed to get the shell, or if there is no shell, |
11142 | // nothing left to do here. |
11143 | return NS_OK; |
11144 | } |
11145 | |
11146 | ScrollContainerFrame* rootScroll = presShell->GetRootScrollContainerFrame(); |
11147 | if (rootScroll) { |
11148 | rootScroll->ClearDidHistoryRestore(); |
11149 | } |
11150 | |
11151 | // If it's a load from history, we don't have any anchor jumping to do. |
11152 | // Scrollbar position will be restored by the caller based on positions stored |
11153 | // in session history. |
11154 | bool scroll = aLoadType != LOAD_HISTORY && aLoadType != LOAD_RELOAD_NORMAL; |
11155 | // If the load contains text directives, try to apply them. This may fail if |
11156 | // the load is a same-document load that was initiated before the document was |
11157 | // fully loaded and the target is not yet included in the DOM tree. |
11158 | // For this case, the `uninvokedTextDirectives` are not cleared, so that |
11159 | // `Document::ScrollToRef()` can re-apply the text directive. |
11160 | // `Document::ScrollToRef()` is (presumably) the second "async" call mentioned |
11161 | // in sec. 7.4.2.3.3 in the HTML spec, "Fragment navigations": |
11162 | // https://html.spec.whatwg.org/#scroll-to-fragid:~:text=This%20algorithm%20will%20be%20called%20twice |
11163 | |
11164 | const RefPtr fragmentDirective = GetDocument()->FragmentDirective(); |
11165 | const nsTArray<RefPtr<nsRange>> textDirectiveRanges = |
11166 | fragmentDirective->FindTextFragmentsInDocument(); |
11167 | fragmentDirective->HighlightTextDirectives(textDirectiveRanges); |
11168 | const bool scrollToTextDirective = |
11169 | !textDirectiveRanges.IsEmpty() && |
11170 | fragmentDirective->IsTextDirectiveAllowedToBeScrolledTo(); |
11171 | const RefPtr<nsRange> textDirectiveToScroll = |
11172 | scrollToTextDirective ? textDirectiveRanges[0] : nullptr; |
11173 | |
11174 | // If we have no new anchor, we do not want to scroll, unless there is a |
11175 | // current anchor and we are doing a history load. So return if we have no |
11176 | // new anchor, and there is no current anchor or the load is not a history |
11177 | // load. |
11178 | if ((!aCurHasRef || aLoadType != LOAD_HISTORY) && !aNewHasRef && |
11179 | !scrollToTextDirective) { |
11180 | return NS_OK; |
11181 | } |
11182 | |
11183 | // Both the new and current URIs refer to the same page. We can now |
11184 | // browse to the hash stored in the new URI. |
11185 | |
11186 | if (aNewHash.IsEmpty() && !scrollToTextDirective) { |
11187 | // 2. If fragment is the empty string, then return the special value top of |
11188 | // the document. |
11189 | // |
11190 | // Tell the shell it's at an anchor without scrolling. |
11191 | presShell->GoToAnchor(u""_ns, nullptr, false); |
11192 | |
11193 | if (scroll) { |
11194 | // Scroll to the top of the page. Ignore the return value; failure to |
11195 | // scroll here (e.g. if there is no root scrollframe) is not grounds for |
11196 | // canceling the load! |
11197 | SetCurScrollPosEx(0, 0); |
11198 | } |
11199 | |
11200 | return NS_OK; |
11201 | } |
11202 | |
11203 | // 3. Let potentialIndicatedElement be the result of finding a potential |
11204 | // indicated element given document and fragment. |
11205 | NS_ConvertUTF8toUTF16 uStr(aNewHash); |
11206 | |
11207 | MOZ_ASSERT(!uStr.IsEmpty() || scrollToTextDirective)do { static_assert( mozilla::detail::AssertionConditionType< decltype(!uStr.IsEmpty() || scrollToTextDirective)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(!uStr.IsEmpty() || scrollToTextDirective))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!uStr.IsEmpty() || scrollToTextDirective" , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 11207); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!uStr.IsEmpty() || scrollToTextDirective" ")"); do { MOZ_CrashSequence(__null, 11207); __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
11208 | |
11209 | auto rv = presShell->GoToAnchor(uStr, textDirectiveToScroll, scroll, |
11210 | ScrollFlags::ScrollSmoothAuto); |
11211 | |
11212 | // 4. If potentialIndicatedElement is not null, then return |
11213 | // potentialIndicatedElement. |
11214 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) { |
11215 | return NS_OK; |
11216 | } |
11217 | |
11218 | // 5. Let fragmentBytes be the result of percent-decoding fragment. |
11219 | nsAutoCString fragmentBytes; |
11220 | const bool unescaped = NS_UnescapeURL(aNewHash.Data(), aNewHash.Length(), |
11221 | /* aFlags = */ 0, fragmentBytes); |
11222 | |
11223 | if (!unescaped) { |
11224 | // Another attempt is only necessary if characters were unescaped. |
11225 | return NS_OK; |
11226 | } |
11227 | |
11228 | if (fragmentBytes.IsEmpty()) { |
11229 | // When aNewHash contains "%00", the unescaped string may be empty, and |
11230 | // GoToAnchor asserts if we ask it to scroll to an empty ref. |
11231 | presShell->GoToAnchor(u""_ns, nullptr, false); |
11232 | return NS_OK; |
11233 | } |
11234 | |
11235 | // 6. Let decodedFragment be the result of running UTF-8 decode without BOM on |
11236 | // fragmentBytes. |
11237 | nsAutoString decodedFragment; |
11238 | rv = UTF_8_ENCODING->DecodeWithoutBOMHandling(fragmentBytes, decodedFragment); |
11239 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 11239); return rv; } } while (false); |
11240 | |
11241 | // 7. Set potentialIndicatedElement to the result of finding a potential |
11242 | // indicated element given document and decodedFragment. |
11243 | // |
11244 | // Ignore the return value of GoToAnchor, since it will return an error if |
11245 | // there is no such anchor in the document, which is actually a success |
11246 | // condition for us (we want to update the session history with the new URI no |
11247 | // matter whether we actually scrolled somewhere). |
11248 | presShell->GoToAnchor(decodedFragment, nullptr, scroll, |
11249 | ScrollFlags::ScrollSmoothAuto); |
11250 | |
11251 | return NS_OK; |
11252 | } |
11253 | |
11254 | bool nsDocShell::OnNewURI(nsIURI* aURI, nsIChannel* aChannel, |
11255 | nsIPrincipal* aTriggeringPrincipal, |
11256 | nsIPrincipal* aPrincipalToInherit, |
11257 | nsIPrincipal* aPartitionedPrincipalToInherit, |
11258 | nsIContentSecurityPolicy* aCsp, |
11259 | bool aAddToGlobalHistory, bool aCloneSHChildren) { |
11260 | MOZ_ASSERT(aURI, "uri is null")do { static_assert( mozilla::detail::AssertionConditionType< decltype(aURI)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(aURI))), 0))) { do { } while (false ); MOZ_ReportAssertionFailure("aURI" " (" "uri is null" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 11260); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aURI" ") (" "uri is null" ")"); do { MOZ_CrashSequence(__null, 11260); __attribute__ ((nomerge)) ::abort(); } while (false); } } while (false); |
11261 | MOZ_ASSERT(!aChannel || !aTriggeringPrincipal, "Shouldn't have both set")do { static_assert( mozilla::detail::AssertionConditionType< decltype(!aChannel || !aTriggeringPrincipal)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!aChannel || !aTriggeringPrincipal ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "!aChannel || !aTriggeringPrincipal" " (" "Shouldn't have both set" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 11261 ); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aChannel || !aTriggeringPrincipal" ") (" "Shouldn't have both set" ")"); do { MOZ_CrashSequence (__null, 11261); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); |
11262 | |
11263 | MOZ_ASSERT(!aPrincipalToInherit ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(!aPrincipalToInherit || (aPrincipalToInherit && aTriggeringPrincipal))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!aPrincipalToInherit || (aPrincipalToInherit && aTriggeringPrincipal)))), 0))) { do { } while (false ); MOZ_ReportAssertionFailure("!aPrincipalToInherit || (aPrincipalToInherit && aTriggeringPrincipal)" , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 11264); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aPrincipalToInherit || (aPrincipalToInherit && aTriggeringPrincipal)" ")"); do { MOZ_CrashSequence(__null, 11264); __attribute__(( nomerge)) ::abort(); } while (false); } } while (false) |
11264 | (aPrincipalToInherit && aTriggeringPrincipal))do { static_assert( mozilla::detail::AssertionConditionType< decltype(!aPrincipalToInherit || (aPrincipalToInherit && aTriggeringPrincipal))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!aPrincipalToInherit || (aPrincipalToInherit && aTriggeringPrincipal)))), 0))) { do { } while (false ); MOZ_ReportAssertionFailure("!aPrincipalToInherit || (aPrincipalToInherit && aTriggeringPrincipal)" , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 11264); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aPrincipalToInherit || (aPrincipalToInherit && aTriggeringPrincipal)" ")"); do { MOZ_CrashSequence(__null, 11264); __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
11265 | |
11266 | #if defined(DEBUG1) |
11267 | if (MOZ_LOG_TEST(gDocShellLog, LogLevel::Debug)(__builtin_expect(!!(mozilla::detail::log_test(gDocShellLog, LogLevel ::Debug)), 0))) { |
11268 | nsAutoCString chanName; |
11269 | if (aChannel) { |
11270 | aChannel->GetName(chanName); |
11271 | } else { |
11272 | chanName.AssignLiteral("<no channel>"); |
11273 | } |
11274 | |
11275 | MOZ_LOG(gDocShellLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gDocShellLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "nsDocShell[%p]::OnNewURI(\"%s\", [%s], 0x%x)\n" , this, aURI->GetSpecOrDefault().get(), chanName.get(), mLoadType ); } } while (0) |
11276 | ("nsDocShell[%p]::OnNewURI(\"%s\", [%s], 0x%x)\n", this,do { const ::mozilla::LogModule* moz_real_module = gDocShellLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "nsDocShell[%p]::OnNewURI(\"%s\", [%s], 0x%x)\n" , this, aURI->GetSpecOrDefault().get(), chanName.get(), mLoadType ); } } while (0) |
11277 | aURI->GetSpecOrDefault().get(), chanName.get(), mLoadType))do { const ::mozilla::LogModule* moz_real_module = gDocShellLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "nsDocShell[%p]::OnNewURI(\"%s\", [%s], 0x%x)\n" , this, aURI->GetSpecOrDefault().get(), chanName.get(), mLoadType ); } } while (0); |
11278 | } |
11279 | #endif |
11280 | |
11281 | bool equalUri = false; |
11282 | |
11283 | // Get the post data and the HTTP response code from the channel. |
11284 | uint32_t responseStatus = 0; |
11285 | nsCOMPtr<nsIInputStream> inputStream; |
11286 | if (aChannel) { |
11287 | nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(aChannel)); |
11288 | |
11289 | // Check if the HTTPChannel is hiding under a multiPartChannel |
11290 | if (!httpChannel) { |
11291 | GetHttpChannel(aChannel, getter_AddRefs(httpChannel)); |
11292 | } |
11293 | |
11294 | if (httpChannel) { |
11295 | nsCOMPtr<nsIUploadChannel> uploadChannel(do_QueryInterface(httpChannel)); |
11296 | if (uploadChannel) { |
11297 | uploadChannel->GetUploadStream(getter_AddRefs(inputStream)); |
11298 | } |
11299 | |
11300 | // If the response status indicates an error, unlink this session |
11301 | // history entry from any entries sharing its document. |
11302 | nsresult rv = httpChannel->GetResponseStatus(&responseStatus); |
11303 | if (mLSHE && NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && responseStatus >= 400) { |
11304 | mLSHE->AbandonBFCacheEntry(); |
11305 | // FIXME Do the same for mLoadingEntry |
11306 | } |
11307 | } |
11308 | } |
11309 | |
11310 | // Determine if this type of load should update history. |
11311 | bool updateGHistory = ShouldUpdateGlobalHistory(mLoadType); |
11312 | |
11313 | // We don't update session history on reload unless we're loading |
11314 | // an iframe in shift-reload case. |
11315 | bool updateSHistory = mBrowsingContext->ShouldUpdateSessionHistory(mLoadType); |
11316 | |
11317 | // Create SH Entry (mLSHE) only if there is a SessionHistory object in the |
11318 | // root browsing context. |
11319 | // FIXME If session history in the parent is enabled then we only do this if |
11320 | // the session history object is in process, otherwise we can't really |
11321 | // use the mLSHE anyway. Once session history is only stored in the |
11322 | // parent then this code will probably be removed anyway. |
11323 | RefPtr<ChildSHistory> rootSH = GetRootSessionHistory(); |
11324 | if (!rootSH) { |
11325 | updateSHistory = false; |
11326 | updateGHistory = false; // XXX Why global history too? |
11327 | } |
11328 | |
11329 | // Check if the url to be loaded is the same as the one already loaded. |
11330 | if (mCurrentURI) { |
11331 | aURI->Equals(mCurrentURI, &equalUri); |
11332 | } |
11333 | |
11334 | #ifdef DEBUG1 |
11335 | bool shAvailable = (rootSH != nullptr); |
11336 | |
11337 | // XXX This log message is almost useless because |updateSHistory| |
11338 | // and |updateGHistory| are not correct at this point. |
11339 | |
11340 | MOZ_LOG(gDocShellLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gDocShellLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, " shAvailable=%i updateSHistory=%i updateGHistory=%i" " equalURI=%i\n", shAvailable, updateSHistory, updateGHistory , equalUri); } } while (0) |
11341 | (" shAvailable=%i updateSHistory=%i updateGHistory=%i"do { const ::mozilla::LogModule* moz_real_module = gDocShellLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, " shAvailable=%i updateSHistory=%i updateGHistory=%i" " equalURI=%i\n", shAvailable, updateSHistory, updateGHistory , equalUri); } } while (0) |
11342 | " equalURI=%i\n",do { const ::mozilla::LogModule* moz_real_module = gDocShellLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, " shAvailable=%i updateSHistory=%i updateGHistory=%i" " equalURI=%i\n", shAvailable, updateSHistory, updateGHistory , equalUri); } } while (0) |
11343 | shAvailable, updateSHistory, updateGHistory, equalUri))do { const ::mozilla::LogModule* moz_real_module = gDocShellLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, " shAvailable=%i updateSHistory=%i updateGHistory=%i" " equalURI=%i\n", shAvailable, updateSHistory, updateGHistory , equalUri); } } while (0); |
11344 | #endif |
11345 | |
11346 | /* If the url to be loaded is the same as the one already there, |
11347 | * and the original loadType is LOAD_NORMAL, LOAD_LINK, or |
11348 | * LOAD_STOP_CONTENT, set loadType to LOAD_NORMAL_REPLACE so that |
11349 | * AddToSessionHistory() won't mess with the current SHEntry and |
11350 | * if this page has any frame children, it also will be handled |
11351 | * properly. see bug 83684 |
11352 | * |
11353 | * NB: If mOSHE is null but we have a current URI, then it probably |
11354 | * means that we must be at the transient about:blank content viewer; |
11355 | * we should let the normal load continue, since there's nothing to |
11356 | * replace. Sometimes this happens after a session restore (eg process |
11357 | * switch) and mCurrentURI is not about:blank; we assume we can let the load |
11358 | * continue (Bug 1301399). |
11359 | * |
11360 | * XXX Hopefully changing the loadType at this time will not hurt |
11361 | * anywhere. The other way to take care of sequentially repeating |
11362 | * frameset pages is to add new methods to nsIDocShellTreeItem. |
11363 | * Hopefully I don't have to do that. |
11364 | */ |
11365 | if (equalUri && |
11366 | (mozilla::SessionHistoryInParent() ? !!mActiveEntry : !!mOSHE) && |
11367 | (mLoadType == LOAD_NORMAL || mLoadType == LOAD_LINK || |
11368 | mLoadType == LOAD_STOP_CONTENT) && |
11369 | !inputStream) { |
11370 | mLoadType = LOAD_NORMAL_REPLACE; |
11371 | } |
11372 | |
11373 | // If this is a refresh to the currently loaded url, we don't |
11374 | // have to update session or global history. |
11375 | if (mLoadType == LOAD_REFRESH && !inputStream && equalUri) { |
11376 | SetHistoryEntryAndUpdateBC(Some<nsISHEntry*>(mOSHE), Nothing()); |
11377 | } |
11378 | |
11379 | /* If the user pressed shift-reload, cache will create a new cache key |
11380 | * for the page. Save the new cacheKey in Session History. |
11381 | * see bug 90098 |
11382 | */ |
11383 | if (aChannel && IsForceReloadType(mLoadType)) { |
11384 | MOZ_ASSERT(!updateSHistory || IsSubframe(),do { static_assert( mozilla::detail::AssertionConditionType< decltype(!updateSHistory || IsSubframe())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!updateSHistory || IsSubframe ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("!updateSHistory || IsSubframe()" " (" "We shouldn't be updating session history for forced" " reloads unless we're in a newly created iframe!" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 11386); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!updateSHistory || IsSubframe()" ") (" "We shouldn't be updating session history for forced" " reloads unless we're in a newly created iframe!" ")"); do { MOZ_CrashSequence(__null, 11386); __attribute__(( nomerge)) ::abort(); } while (false); } } while (false) |
11385 | "We shouldn't be updating session history for forced"do { static_assert( mozilla::detail::AssertionConditionType< decltype(!updateSHistory || IsSubframe())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!updateSHistory || IsSubframe ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("!updateSHistory || IsSubframe()" " (" "We shouldn't be updating session history for forced" " reloads unless we're in a newly created iframe!" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 11386); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!updateSHistory || IsSubframe()" ") (" "We shouldn't be updating session history for forced" " reloads unless we're in a newly created iframe!" ")"); do { MOZ_CrashSequence(__null, 11386); __attribute__(( nomerge)) ::abort(); } while (false); } } while (false) |
11386 | " reloads unless we're in a newly created iframe!")do { static_assert( mozilla::detail::AssertionConditionType< decltype(!updateSHistory || IsSubframe())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!updateSHistory || IsSubframe ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("!updateSHistory || IsSubframe()" " (" "We shouldn't be updating session history for forced" " reloads unless we're in a newly created iframe!" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 11386); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!updateSHistory || IsSubframe()" ") (" "We shouldn't be updating session history for forced" " reloads unless we're in a newly created iframe!" ")"); do { MOZ_CrashSequence(__null, 11386); __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
11387 | |
11388 | nsCOMPtr<nsICacheInfoChannel> cacheChannel(do_QueryInterface(aChannel)); |
11389 | uint32_t cacheKey = 0; |
11390 | // Get the Cache Key and store it in SH. |
11391 | if (cacheChannel) { |
11392 | cacheChannel->GetCacheKey(&cacheKey); |
11393 | } |
11394 | // If we already have a loading history entry, store the new cache key |
11395 | // in it. Otherwise, since we're doing a reload and won't be updating |
11396 | // our history entry, store the cache key in our current history entry. |
11397 | SetCacheKeyOnHistoryEntry(mLSHE ? mLSHE : mOSHE, cacheKey); |
11398 | |
11399 | if (!mozilla::SessionHistoryInParent()) { |
11400 | // Since we're force-reloading, clear all the sub frame history. |
11401 | ClearFrameHistory(mLSHE); |
11402 | ClearFrameHistory(mOSHE); |
11403 | } |
11404 | } |
11405 | |
11406 | if (!mozilla::SessionHistoryInParent()) { |
11407 | // Clear subframe history on refresh. |
11408 | // XXX: history.go(0) won't go this path as mLoadType is LOAD_HISTORY in |
11409 | // this case. One should re-validate after bug 1331865 fixed. |
11410 | if (mLoadType == LOAD_REFRESH) { |
11411 | ClearFrameHistory(mLSHE); |
11412 | ClearFrameHistory(mOSHE); |
11413 | } |
11414 | |
11415 | if (updateSHistory) { |
11416 | // Update session history if necessary... |
11417 | if (!mLSHE && (mItemType == typeContent) && mURIResultedInDocument) { |
11418 | /* This is a fresh page getting loaded for the first time |
11419 | *.Create a Entry for it and add it to SH, if this is the |
11420 | * rootDocShell |
11421 | */ |
11422 | (void)AddToSessionHistory(aURI, aChannel, aTriggeringPrincipal, |
11423 | aPrincipalToInherit, |
11424 | aPartitionedPrincipalToInherit, aCsp, |
11425 | aCloneSHChildren, getter_AddRefs(mLSHE)); |
11426 | } |
11427 | } else if (GetSessionHistory() && mLSHE && mURIResultedInDocument) { |
11428 | // Even if we don't add anything to SHistory, ensure the current index |
11429 | // points to the same SHEntry as our mLSHE. |
11430 | |
11431 | GetSessionHistory()->LegacySHistory()->EnsureCorrectEntryAtCurrIndex( |
11432 | mLSHE); |
11433 | } |
11434 | } |
11435 | |
11436 | // If this is a POST request, we do not want to include this in global |
11437 | // history. |
11438 | if (ShouldAddURIVisit(aChannel) && updateGHistory && aAddToGlobalHistory && |
11439 | !net::ChannelIsPost(aChannel)) { |
11440 | nsCOMPtr<nsIURI> previousURI; |
11441 | uint32_t previousFlags = 0; |
11442 | |
11443 | if (mLoadType & LOAD_CMD_RELOAD) { |
11444 | // On a reload request, we don't set redirecting flags. |
11445 | previousURI = aURI; |
11446 | } else { |
11447 | ExtractLastVisit(aChannel, getter_AddRefs(previousURI), &previousFlags); |
11448 | } |
11449 | |
11450 | AddURIVisit(aURI, previousURI, previousFlags, responseStatus); |
11451 | } |
11452 | |
11453 | // If this was a history load or a refresh, or it was a history load but |
11454 | // later changed to LOAD_NORMAL_REPLACE due to redirection, update the index |
11455 | // in session history. |
11456 | if (!mozilla::SessionHistoryInParent() && rootSH && |
11457 | ((mLoadType & (LOAD_CMD_HISTORY | LOAD_CMD_RELOAD)) || |
11458 | mLoadType == LOAD_NORMAL_REPLACE || mLoadType == LOAD_REFRESH_REPLACE)) { |
11459 | mPreviousEntryIndex = rootSH->Index(); |
11460 | if (!mozilla::SessionHistoryInParent()) { |
11461 | rootSH->LegacySHistory()->UpdateIndex(); |
11462 | } |
11463 | mLoadedEntryIndex = rootSH->Index(); |
11464 | MOZ_LOG(gPageCacheLog, LogLevel::Verbose,do { const ::mozilla::LogModule* moz_real_module = gPageCacheLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Verbose)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Verbose, "Previous index: %d, Loaded index: %d", mPreviousEntryIndex , mLoadedEntryIndex); } } while (0) |
11465 | ("Previous index: %d, Loaded index: %d", mPreviousEntryIndex,do { const ::mozilla::LogModule* moz_real_module = gPageCacheLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Verbose)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Verbose, "Previous index: %d, Loaded index: %d", mPreviousEntryIndex , mLoadedEntryIndex); } } while (0) |
11466 | mLoadedEntryIndex))do { const ::mozilla::LogModule* moz_real_module = gPageCacheLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Verbose)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Verbose, "Previous index: %d, Loaded index: %d", mPreviousEntryIndex , mLoadedEntryIndex); } } while (0); |
11467 | } |
11468 | |
11469 | // aCloneSHChildren exactly means "we are not loading a new document". |
11470 | uint32_t locationFlags = |
11471 | aCloneSHChildren ? uint32_t(LOCATION_CHANGE_SAME_DOCUMENT) : 0; |
11472 | |
11473 | bool onLocationChangeNeeded = |
11474 | SetCurrentURI(aURI, aChannel, false, |
11475 | /* aIsInitialAboutBlank */ false, locationFlags); |
11476 | // Make sure to store the referrer from the channel, if any |
11477 | nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(aChannel)); |
11478 | if (httpChannel) { |
11479 | mReferrerInfo = httpChannel->GetReferrerInfo(); |
11480 | } |
11481 | return onLocationChangeNeeded; |
11482 | } |
11483 | |
11484 | Maybe<Wireframe> nsDocShell::GetWireframe() { |
11485 | const bool collectWireFrame = |
11486 | mozilla::SessionHistoryInParent() && |
11487 | StaticPrefs::browser_history_collectWireframes() && |
11488 | mBrowsingContext->IsTopContent() && mActiveEntry; |
11489 | |
11490 | if (!collectWireFrame) { |
11491 | return Nothing(); |
11492 | } |
11493 | |
11494 | RefPtr<Document> doc = mDocumentViewer->GetDocument(); |
11495 | Nullable<Wireframe> wireframe; |
11496 | doc->GetWireframeWithoutFlushing(false, wireframe); |
11497 | if (wireframe.IsNull()) { |
11498 | return Nothing(); |
11499 | } |
11500 | return Some(wireframe.Value()); |
11501 | } |
11502 | |
11503 | bool nsDocShell::CollectWireframe() { |
11504 | Maybe<Wireframe> wireframe = GetWireframe(); |
11505 | if (wireframe.isNothing()) { |
11506 | return false; |
11507 | } |
11508 | |
11509 | if (XRE_IsParentProcess()) { |
11510 | SessionHistoryEntry* entry = |
11511 | mBrowsingContext->Canonical()->GetActiveSessionHistoryEntry(); |
11512 | if (entry) { |
11513 | entry->SetWireframe(wireframe); |
11514 | } |
11515 | } else { |
11516 | mozilla::Unused |
11517 | << ContentChild::GetSingleton()->SendSessionHistoryEntryWireframe( |
11518 | mBrowsingContext, wireframe.ref()); |
11519 | } |
11520 | |
11521 | return true; |
11522 | } |
11523 | |
11524 | //***************************************************************************** |
11525 | // nsDocShell: Session History |
11526 | //***************************************************************************** |
11527 | |
11528 | NS_IMETHODIMPnsresult |
11529 | nsDocShell::AddState(JS::Handle<JS::Value> aData, const nsAString& aTitle, |
11530 | const nsAString& aURL, bool aReplace, JSContext* aCx) { |
11531 | MOZ_LOG(gSHLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gSHLog; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "nsDocShell[%p]: AddState(..., %s, %s, %d)" , this, NS_ConvertUTF16toUTF8(aTitle).get(), NS_ConvertUTF16toUTF8 (aURL).get(), aReplace); } } while (0) |
11532 | ("nsDocShell[%p]: AddState(..., %s, %s, %d)", this,do { const ::mozilla::LogModule* moz_real_module = gSHLog; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "nsDocShell[%p]: AddState(..., %s, %s, %d)" , this, NS_ConvertUTF16toUTF8(aTitle).get(), NS_ConvertUTF16toUTF8 (aURL).get(), aReplace); } } while (0) |
11533 | NS_ConvertUTF16toUTF8(aTitle).get(),do { const ::mozilla::LogModule* moz_real_module = gSHLog; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "nsDocShell[%p]: AddState(..., %s, %s, %d)" , this, NS_ConvertUTF16toUTF8(aTitle).get(), NS_ConvertUTF16toUTF8 (aURL).get(), aReplace); } } while (0) |
11534 | NS_ConvertUTF16toUTF8(aURL).get(), aReplace))do { const ::mozilla::LogModule* moz_real_module = gSHLog; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "nsDocShell[%p]: AddState(..., %s, %s, %d)" , this, NS_ConvertUTF16toUTF8(aTitle).get(), NS_ConvertUTF16toUTF8 (aURL).get(), aReplace); } } while (0); |
11535 | // Implements History.pushState and History.replaceState |
11536 | |
11537 | // Here's what we do, roughly in the order specified by HTML5. The specific |
11538 | // steps we are executing are at |
11539 | // <https://html.spec.whatwg.org/multipage/history.html#dom-history-pushstate>, |
11540 | // <https://html.spec.whatwg.org/#shared-history-push/replace-state-steps>, |
11541 | // and |
11542 | // <https://html.spec.whatwg.org/multipage/history.html#url-and-history-update-steps>. |
11543 | // This function basically implements #dom-history-pushstate and |
11544 | // UpdateURLAndHistory implements #url-and-history-update-steps. |
11545 | // |
11546 | // A. Serialize aData using structured clone. This is #dom-history-pushstate |
11547 | // step 5. |
11548 | // B. If the third argument is present, #dom-history-pushstate step 7. |
11549 | // 7.1. Resolve the url, relative to our document. |
11550 | // 7.2. If (a) fails, raise a SECURITY_ERR |
11551 | // 7.4. Compare the resulting absolute URL to the document's address. If |
11552 | // any part of the URLs difer other than the <path>, <query>, and |
11553 | // <fragment> components, raise a SECURITY_ERR and abort. |
11554 | // C. If !aReplace, #url-and-history-update-steps steps 2.1-2.3: |
11555 | // Remove from the session history all entries after the current entry, |
11556 | // as we would after a regular navigation, and save the current |
11557 | // entry's scroll position (bug 590573). |
11558 | // D. #url-and-history-update-steps step 2.4 or step 3. As apropriate, |
11559 | // either add a state object entry to the session history after the |
11560 | // current entry with the following properties, or modify the current |
11561 | // session history entry to set |
11562 | // a. cloned data as the state object, |
11563 | // b. if the third argument was present, the absolute URL found in |
11564 | // step 2 |
11565 | // Also clear the new history entry's POST data (see bug 580069). |
11566 | // E. If aReplace is false (i.e. we're doing a pushState instead of a |
11567 | // replaceState), notify bfcache that we've navigated to a new page. |
11568 | // F. If the third argument is present, set the document's current address |
11569 | // to the absolute URL found in step B. This is |
11570 | // #url-and-history-update-steps step 4. |
11571 | // |
11572 | // It's important that this function not run arbitrary scripts after step A |
11573 | // and before completing step E. For example, if a script called |
11574 | // history.back() before we completed step E, bfcache might destroy an |
11575 | // active content viewer. Since EvictOutOfRangeDocumentViewers at the end of |
11576 | // step E might run script, we can't just put a script blocker around the |
11577 | // critical section. |
11578 | // |
11579 | // Note that we completely ignore the aTitle parameter. |
11580 | |
11581 | nsresult rv; |
11582 | |
11583 | RefPtr<Document> document = GetDocument(); |
11584 | NS_ENSURE_TRUE(document, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(document)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "document" ") failed", nullptr , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 11584); return NS_ERROR_FAILURE; } } while (false); |
11585 | |
11586 | // Don't clobber the load type of an existing network load. |
11587 | Maybe<AutoRestore<uint32_t>> loadTypeResetter; |
11588 | if (StaticPrefs:: |
11589 | docshell_shistory_sameDocumentNavigationOverridesLoadType() && |
11590 | !document->NodePrincipal()->IsURIInPrefList( |
11591 | "docshell.shistory.sameDocumentNavigationOverridesLoadType." |
11592 | "forceDisable")) { |
11593 | loadTypeResetter.emplace(mLoadType); |
11594 | } |
11595 | |
11596 | // pushState effectively becomes replaceState when we've started a network |
11597 | // load but haven't adopted its document yet. This mirrors what we do with |
11598 | // changes to the hash at this stage of the game. |
11599 | if (JustStartedNetworkLoad()) { |
11600 | if (!loadTypeResetter.isSome()) { |
11601 | loadTypeResetter.emplace(mLoadType); |
11602 | } |
11603 | aReplace = true; |
11604 | } |
11605 | |
11606 | // Step A: Serialize aData using structured clone. |
11607 | // https://html.spec.whatwg.org/multipage/history.html#dom-history-pushstate |
11608 | // step 5. |
11609 | nsCOMPtr<nsIStructuredCloneContainer> scContainer; |
11610 | |
11611 | // scContainer->Init might cause arbitrary JS to run, and this code might |
11612 | // navigate the page we're on, potentially to a different origin! (bug |
11613 | // 634834) To protect against this, we abort if our principal changes due |
11614 | // to the InitFromJSVal() call. |
11615 | { |
11616 | RefPtr<Document> origDocument = GetDocument(); |
11617 | if (!origDocument) { |
11618 | return NS_ERROR_DOM_SECURITY_ERR; |
11619 | } |
11620 | nsCOMPtr<nsIPrincipal> origPrincipal = origDocument->NodePrincipal(); |
11621 | |
11622 | scContainer = new nsStructuredCloneContainer(); |
11623 | rv = scContainer->InitFromJSVal(aData, aCx); |
11624 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 11624); return rv; } } while (false); |
11625 | |
11626 | RefPtr<Document> newDocument = GetDocument(); |
11627 | if (!newDocument) { |
11628 | return NS_ERROR_DOM_SECURITY_ERR; |
11629 | } |
11630 | nsCOMPtr<nsIPrincipal> newPrincipal = newDocument->NodePrincipal(); |
11631 | |
11632 | bool principalsEqual = false; |
11633 | origPrincipal->Equals(newPrincipal, &principalsEqual); |
11634 | NS_ENSURE_TRUE(principalsEqual, NS_ERROR_DOM_SECURITY_ERR)do { if ((__builtin_expect(!!(!(principalsEqual)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "principalsEqual" ") failed" , nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 11634); return NS_ERROR_DOM_SECURITY_ERR; } } while (false); |
11635 | } |
11636 | |
11637 | // Check that the state object isn't too long. |
11638 | int32_t maxStateObjSize = StaticPrefs::browser_history_maxStateObjectSize(); |
11639 | if (maxStateObjSize < 0) { |
11640 | maxStateObjSize = 0; |
11641 | } |
11642 | |
11643 | uint64_t scSize; |
11644 | rv = scContainer->GetSerializedNBytes(&scSize); |
11645 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 11645); return rv; } } while (false); |
11646 | |
11647 | NS_ENSURE_TRUE(scSize <= (uint32_t)maxStateObjSize, NS_ERROR_ILLEGAL_VALUE)do { if ((__builtin_expect(!!(!(scSize <= (uint32_t)maxStateObjSize )), 0))) { NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "scSize <= (uint32_t)maxStateObjSize" ") failed", nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 11647); return NS_ERROR_ILLEGAL_VALUE; } } while (false); |
11648 | |
11649 | // Step B: Resolve aURL. |
11650 | // https://html.spec.whatwg.org/multipage/history.html#dom-history-pushstate |
11651 | // step 7. |
11652 | bool equalURIs = true; |
11653 | nsCOMPtr<nsIURI> currentURI; |
11654 | if (mCurrentURI) { |
11655 | currentURI = nsIOService::CreateExposableURI(mCurrentURI); |
11656 | } else { |
11657 | currentURI = mCurrentURI; |
11658 | } |
11659 | nsCOMPtr<nsIURI> newURI; |
11660 | if (aURL.Length() == 0) { |
11661 | newURI = currentURI; |
11662 | } else { |
11663 | // 7.1: Resolve aURL relative to mURI |
11664 | |
11665 | nsIURI* docBaseURI = document->GetDocBaseURI(); |
11666 | if (!docBaseURI) { |
11667 | return NS_ERROR_FAILURE; |
11668 | } |
11669 | |
11670 | nsAutoCString spec; |
11671 | docBaseURI->GetSpec(spec); |
11672 | |
11673 | rv = NS_NewURI(getter_AddRefs(newURI), aURL, |
11674 | document->GetDocumentCharacterSet(), docBaseURI); |
11675 | |
11676 | // 7.2: If 2a fails, raise a SECURITY_ERR |
11677 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
11678 | return NS_ERROR_DOM_SECURITY_ERR; |
11679 | } |
11680 | |
11681 | if (!document->CanRewriteURL(newURI)) { |
11682 | return NS_ERROR_DOM_SECURITY_ERR; |
11683 | } |
11684 | |
11685 | if (currentURI) { |
11686 | currentURI->Equals(newURI, &equalURIs); |
11687 | } else { |
11688 | equalURIs = false; |
11689 | } |
11690 | |
11691 | } // end of same-origin check |
11692 | |
11693 | // https://html.spec.whatwg.org/#shared-history-push/replace-state-steps |
11694 | // Step 8 |
11695 | if (nsCOMPtr<nsPIDOMWindowInner> window = document->GetInnerWindow()) { |
11696 | if (RefPtr<Navigation> navigation = window->Navigation()) { |
11697 | bool shouldContinue = navigation->FirePushReplaceReloadNavigateEvent( |
11698 | aCx, aReplace ? NavigationType::Replace : NavigationType::Push, |
11699 | newURI, |
11700 | /* aIsSameDocument */ true, /* aIsSync */ true, |
11701 | /* aUserInvolvement */ Nothing(), |
11702 | /* aSourceElement */ nullptr, /* aFormDataEntryList */ nullptr, |
11703 | /* aNavigationAPIState */ nullptr, scContainer); |
11704 | |
11705 | // Step 9 |
11706 | if (!shouldContinue) { |
11707 | return NS_OK; |
11708 | } |
11709 | } |
11710 | } |
11711 | |
11712 | // Step 10 |
11713 | // Run #url-and-history-update-steps |
11714 | rv = UpdateURLAndHistory(document, newURI, scContainer, |
11715 | aReplace ? NavigationHistoryBehavior::Replace |
11716 | : NavigationHistoryBehavior::Push, |
11717 | currentURI, equalURIs); |
11718 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 11718); return rv; } } while (false); |
11719 | |
11720 | return NS_OK; |
11721 | } |
11722 | |
11723 | nsresult nsDocShell::UpdateURLAndHistory( |
11724 | Document* aDocument, nsIURI* aNewURI, nsIStructuredCloneContainer* aData, |
11725 | NavigationHistoryBehavior aHistoryHandling, nsIURI* aCurrentURI, |
11726 | bool aEqualURIs) { |
11727 | // Implements |
11728 | // https://html.spec.whatwg.org/multipage/history.html#url-and-history-update-steps |
11729 | MOZ_ASSERT(aHistoryHandling != NavigationHistoryBehavior::Auto)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aHistoryHandling != NavigationHistoryBehavior::Auto) >::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(aHistoryHandling != NavigationHistoryBehavior::Auto) )), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aHistoryHandling != NavigationHistoryBehavior::Auto" , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 11729); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aHistoryHandling != NavigationHistoryBehavior::Auto" ")"); do { MOZ_CrashSequence(__null, 11729); __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
11730 | bool isReplace = aHistoryHandling == NavigationHistoryBehavior::Replace; |
11731 | |
11732 | // If we have a pending title change, handle it before creating a new entry. |
11733 | aDocument->DoNotifyPossibleTitleChange(); |
11734 | |
11735 | // Step 2, if aReplace is false: Create a new entry in the session |
11736 | // history. This will erase all SHEntries after the new entry and make this |
11737 | // entry the current one. This operation may modify mOSHE, which we need |
11738 | // later, so we keep a reference here. |
11739 | NS_ENSURE_TRUE(mOSHE || mActiveEntry || isReplace, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(mOSHE || mActiveEntry || isReplace )), 0))) { NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "mOSHE || mActiveEntry || isReplace" ") failed", nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 11739); return NS_ERROR_FAILURE; } } while (false); |
11740 | nsCOMPtr<nsISHEntry> oldOSHE = mOSHE; |
11741 | |
11742 | // If this push/replaceState changed the document's current URI and the new |
11743 | // URI differs from the old URI in more than the hash, or if the old |
11744 | // SHEntry's URI was modified in this way by a push/replaceState call |
11745 | // set URIWasModified to true for the current SHEntry (bug 669671). |
11746 | bool sameExceptHashes = true; |
11747 | aNewURI->EqualsExceptRef(aCurrentURI, &sameExceptHashes); |
11748 | bool uriWasModified; |
11749 | if (sameExceptHashes) { |
11750 | if (mozilla::SessionHistoryInParent()) { |
11751 | uriWasModified = mActiveEntry && mActiveEntry->GetURIWasModified(); |
11752 | } else { |
11753 | uriWasModified = oldOSHE && oldOSHE->GetURIWasModified(); |
11754 | } |
11755 | } else { |
11756 | uriWasModified = true; |
11757 | } |
11758 | |
11759 | mLoadType = LOAD_PUSHSTATE; |
11760 | |
11761 | nsCOMPtr<nsISHEntry> newSHEntry; |
11762 | if (!isReplace) { |
11763 | // Step 2. |
11764 | |
11765 | // Step 2.2, "Remove any tasks queued by the history traversal task |
11766 | // source that are associated with any Document objects in the |
11767 | // top-level browsing context's document family." This is very hard in |
11768 | // SessionHistoryInParent since we can't synchronously access the |
11769 | // pending navigations that are already sent to the parent. We can |
11770 | // abort any AsyncGo navigations that are waiting to be sent. If we |
11771 | // send a message to the parent, it would be processed after any |
11772 | // navigations previously sent. So long as we consider the "history |
11773 | // traversal task source" to be the list in this process we match the |
11774 | // spec. If we move the entire list to the parent, we can handle the |
11775 | // aborting of loads there, but we don't have a way to synchronously |
11776 | // remove entries as we do here for non-SHIP. |
11777 | RefPtr<ChildSHistory> shistory = GetRootSessionHistory(); |
11778 | if (shistory) { |
11779 | shistory->RemovePendingHistoryNavigations(); |
11780 | } |
11781 | |
11782 | nsPoint scrollPos = GetCurScrollPos(); |
11783 | |
11784 | bool scrollRestorationIsManual; |
11785 | if (mozilla::SessionHistoryInParent()) { |
11786 | // FIXME Need to save the current scroll position on mActiveEntry. |
11787 | scrollRestorationIsManual = mActiveEntry->GetScrollRestorationIsManual(); |
11788 | } else { |
11789 | // Save the current scroll position (bug 590573). Step 2.3. |
11790 | mOSHE->SetScrollPosition(scrollPos.x, scrollPos.y); |
11791 | |
11792 | scrollRestorationIsManual = mOSHE->GetScrollRestorationIsManual(); |
11793 | } |
11794 | |
11795 | nsCOMPtr<nsIContentSecurityPolicy> csp = aDocument->GetCsp(); |
11796 | |
11797 | if (mozilla::SessionHistoryInParent()) { |
11798 | MOZ_LOG(gSHLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gSHLog; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "nsDocShell %p UpdateActiveEntry (not replacing)" , this); } } while (0) |
11799 | ("nsDocShell %p UpdateActiveEntry (not replacing)", this))do { const ::mozilla::LogModule* moz_real_module = gSHLog; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "nsDocShell %p UpdateActiveEntry (not replacing)" , this); } } while (0); |
11800 | |
11801 | nsString title(mActiveEntry->GetTitle()); |
11802 | nsCOMPtr<nsIReferrerInfo> referrerInfo = mActiveEntry->GetReferrerInfo(); |
11803 | |
11804 | UpdateActiveEntry(false, |
11805 | /* aPreviousScrollPos = */ Some(scrollPos), aNewURI, |
11806 | /* aOriginalURI = */ nullptr, |
11807 | /* aReferrerInfo = */ referrerInfo, |
11808 | /* aTriggeringPrincipal = */ aDocument->NodePrincipal(), |
11809 | csp, title, scrollRestorationIsManual, aData, |
11810 | uriWasModified, aDocument->PartitionedPrincipal()); |
11811 | } else { |
11812 | // Since we're not changing which page we have loaded, pass |
11813 | // true for aCloneChildren. |
11814 | nsresult rv = AddToSessionHistory( |
11815 | aNewURI, nullptr, |
11816 | aDocument->NodePrincipal(), // triggeringPrincipal |
11817 | nullptr, nullptr, csp, true, getter_AddRefs(newSHEntry)); |
11818 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 11818); return rv; } } while (false); |
11819 | |
11820 | NS_ENSURE_TRUE(newSHEntry, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(newSHEntry)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "newSHEntry" ") failed", nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 11820); return NS_ERROR_FAILURE; } } while (false); |
11821 | |
11822 | // Session history entries created by pushState inherit scroll restoration |
11823 | // mode from the current entry. |
11824 | newSHEntry->SetScrollRestorationIsManual(scrollRestorationIsManual); |
11825 | |
11826 | // Set the new SHEntry's title (bug 655273). |
11827 | nsString title; |
11828 | mOSHE->GetTitle(title); |
11829 | newSHEntry->SetTitle(title); |
11830 | |
11831 | nsCOMPtr<nsIReferrerInfo> referrerInfo = mOSHE->GetReferrerInfo(); |
11832 | newSHEntry->SetReferrerInfo(referrerInfo); |
11833 | |
11834 | // Link the new SHEntry to the old SHEntry's BFCache entry, since the |
11835 | // two entries correspond to the same document. |
11836 | NS_ENSURE_SUCCESS(newSHEntry->AdoptBFCacheEntry(oldOSHE),do { nsresult __rv = newSHEntry->AdoptBFCacheEntry(oldOSHE ); if (((bool)(__builtin_expect(!!(NS_FAILED_impl(__rv)), 0)) )) { const char* name = mozilla::GetStaticErrorName(__rv); mozilla ::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "newSHEntry->AdoptBFCacheEntry(oldOSHE)" , "NS_ERROR_FAILURE", static_cast<uint32_t>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""); NS_DebugBreak (NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 11837); return NS_ERROR_FAILURE; } } while (false) |
11837 | NS_ERROR_FAILURE)do { nsresult __rv = newSHEntry->AdoptBFCacheEntry(oldOSHE ); if (((bool)(__builtin_expect(!!(NS_FAILED_impl(__rv)), 0)) )) { const char* name = mozilla::GetStaticErrorName(__rv); mozilla ::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "newSHEntry->AdoptBFCacheEntry(oldOSHE)" , "NS_ERROR_FAILURE", static_cast<uint32_t>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""); NS_DebugBreak (NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 11837); return NS_ERROR_FAILURE; } } while (false); |
11838 | |
11839 | // AddToSessionHistory may not modify mOSHE. In case it doesn't, |
11840 | // we'll just set mOSHE here. |
11841 | mOSHE = newSHEntry; |
11842 | } |
11843 | } else if (mozilla::SessionHistoryInParent()) { |
11844 | MOZ_LOG(gSHLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gSHLog; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "nsDocShell %p UpdateActiveEntry (replacing) mActiveEntry %p" , this, mActiveEntry.get()); } } while (0) |
11845 | ("nsDocShell %p UpdateActiveEntry (replacing) mActiveEntry %p",do { const ::mozilla::LogModule* moz_real_module = gSHLog; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "nsDocShell %p UpdateActiveEntry (replacing) mActiveEntry %p" , this, mActiveEntry.get()); } } while (0) |
11846 | this, mActiveEntry.get()))do { const ::mozilla::LogModule* moz_real_module = gSHLog; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "nsDocShell %p UpdateActiveEntry (replacing) mActiveEntry %p" , this, mActiveEntry.get()); } } while (0); |
11847 | // Setting the resultPrincipalURI to nullptr is fine here: it will cause |
11848 | // NS_GetFinalChannelURI to use the originalURI as the URI, which is aNewURI |
11849 | // in our case. We could also set it to aNewURI, with the same result. |
11850 | // We don't use aTitle here, see bug 544535. |
11851 | nsString title; |
11852 | nsCOMPtr<nsIReferrerInfo> referrerInfo; |
11853 | if (mActiveEntry) { |
11854 | title = mActiveEntry->GetTitle(); |
11855 | referrerInfo = mActiveEntry->GetReferrerInfo(); |
11856 | } else { |
11857 | referrerInfo = nullptr; |
11858 | } |
11859 | UpdateActiveEntry( |
11860 | true, /* aPreviousScrollPos = */ Nothing(), aNewURI, aNewURI, |
11861 | /* aReferrerInfo = */ referrerInfo, aDocument->NodePrincipal(), |
11862 | aDocument->GetCsp(), title, |
11863 | mActiveEntry && mActiveEntry->GetScrollRestorationIsManual(), aData, |
11864 | uriWasModified, aDocument->PartitionedPrincipal()); |
11865 | } else { |
11866 | // Step 3. |
11867 | newSHEntry = mOSHE; |
11868 | |
11869 | MOZ_LOG(gSHLog, LogLevel::Debug, ("nsDocShell %p step 3", this))do { const ::mozilla::LogModule* moz_real_module = gSHLog; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "nsDocShell %p step 3", this); } } while ( 0); |
11870 | // Since we're not changing which page we have loaded, pass |
11871 | // true for aCloneChildren. |
11872 | if (!newSHEntry) { |
11873 | nsresult rv = AddToSessionHistory( |
11874 | aNewURI, nullptr, |
11875 | aDocument->NodePrincipal(), // triggeringPrincipal |
11876 | nullptr, nullptr, aDocument->GetCsp(), true, |
11877 | getter_AddRefs(newSHEntry)); |
11878 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 11878); return rv; } } while (false); |
11879 | mOSHE = newSHEntry; |
11880 | } |
11881 | |
11882 | nsCOMPtr<nsIReferrerInfo> referrerInfo = mOSHE->GetReferrerInfo(); |
11883 | |
11884 | newSHEntry->SetURI(aNewURI); |
11885 | newSHEntry->SetOriginalURI(aNewURI); |
11886 | // We replaced the URI of the entry, clear the unstripped URI as it |
11887 | // shouldn't be used for reloads anymore. |
11888 | newSHEntry->SetUnstrippedURI(nullptr); |
11889 | // Setting the resultPrincipalURI to nullptr is fine here: it will cause |
11890 | // NS_GetFinalChannelURI to use the originalURI as the URI, which is aNewURI |
11891 | // in our case. We could also set it to aNewURI, with the same result. |
11892 | newSHEntry->SetResultPrincipalURI(nullptr); |
11893 | newSHEntry->SetLoadReplace(false); |
11894 | newSHEntry->SetReferrerInfo(referrerInfo); |
11895 | } |
11896 | |
11897 | if (!mozilla::SessionHistoryInParent()) { |
11898 | // Step 2.4 and 3: Modify new/original session history entry and clear its |
11899 | // POST data, if there is any. |
11900 | newSHEntry->SetStateData(aData); |
11901 | newSHEntry->SetPostData(nullptr); |
11902 | |
11903 | newSHEntry->SetURIWasModified(uriWasModified); |
11904 | |
11905 | // Step E as described at the top of AddState: If aReplace is false, |
11906 | // indicating that we're doing a pushState rather than a replaceState, |
11907 | // notify bfcache that we've added a page to the history so it can evict |
11908 | // content viewers if appropriate. Otherwise call ReplaceEntry so that we |
11909 | // notify nsIHistoryListeners that an entry was replaced. We may not have a |
11910 | // root session history if this call is coming from a document.open() in a |
11911 | // docshell subtree that disables session history. |
11912 | RefPtr<ChildSHistory> rootSH = GetRootSessionHistory(); |
11913 | if (rootSH) { |
11914 | rootSH->LegacySHistory()->EvictDocumentViewersOrReplaceEntry(newSHEntry, |
11915 | isReplace); |
11916 | } |
11917 | } |
11918 | |
11919 | // Step 4: If the document's URI changed, update document's URI and update |
11920 | // global history. |
11921 | // |
11922 | // We need to call FireOnLocationChange so that the browser's address bar |
11923 | // gets updated and the back button is enabled, but we only need to |
11924 | // explicitly call FireOnLocationChange if we're not calling SetCurrentURI, |
11925 | // since SetCurrentURI will call FireOnLocationChange for us. |
11926 | // |
11927 | // Both SetCurrentURI(...) and FireDummyOnLocationChange() pass |
11928 | // nullptr for aRequest param to FireOnLocationChange(...). Such an update |
11929 | // notification is allowed only when we know docshell is not loading a new |
11930 | // document and it requires LOCATION_CHANGE_SAME_DOCUMENT flag. Otherwise, |
11931 | // FireOnLocationChange(...) breaks security UI. |
11932 | // |
11933 | // If the docshell is shutting down, don't update the document URI, as we |
11934 | // can't load into a docshell that is being destroyed. |
11935 | if (!aEqualURIs && !mIsBeingDestroyed) { |
11936 | aDocument->SetDocumentURI(aNewURI); |
11937 | SetCurrentURI(aNewURI, nullptr, /* aFireLocationChange */ true, |
11938 | /* aIsInitialAboutBlank */ false, |
11939 | GetSameDocumentNavigationFlags(aNewURI)); |
11940 | |
11941 | AddURIVisit(aNewURI, aCurrentURI, 0); |
11942 | |
11943 | // AddURIVisit doesn't set the title for the new URI in global history, |
11944 | // so do that here. |
11945 | UpdateGlobalHistoryTitle(aNewURI); |
11946 | |
11947 | // Inform the favicon service that our old favicon applies to this new |
11948 | // URI. |
11949 | CopyFavicon(aCurrentURI, aNewURI, UsePrivateBrowsing()); |
11950 | } else { |
11951 | FireDummyOnLocationChange(); |
11952 | } |
11953 | aDocument->SetStateObject(aData); |
11954 | |
11955 | if (RefPtr navigation = aDocument->GetInnerWindow()->Navigation()) { |
11956 | MOZ_LOG(gNavigationLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gNavigationLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "nsDocShell %p triggering a navigation event for a same-document " "navigation from UpdateURLAndHistory -> isReplace: %s", this , isReplace ? "true" : "false"); } } while (0) |
11957 | ("nsDocShell %p triggering a navigation event for a same-document "do { const ::mozilla::LogModule* moz_real_module = gNavigationLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "nsDocShell %p triggering a navigation event for a same-document " "navigation from UpdateURLAndHistory -> isReplace: %s", this , isReplace ? "true" : "false"); } } while (0) |
11958 | "navigation from UpdateURLAndHistory -> isReplace: %s",do { const ::mozilla::LogModule* moz_real_module = gNavigationLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "nsDocShell %p triggering a navigation event for a same-document " "navigation from UpdateURLAndHistory -> isReplace: %s", this , isReplace ? "true" : "false"); } } while (0) |
11959 | this, isReplace ? "true" : "false"))do { const ::mozilla::LogModule* moz_real_module = gNavigationLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "nsDocShell %p triggering a navigation event for a same-document " "navigation from UpdateURLAndHistory -> isReplace: %s", this , isReplace ? "true" : "false"); } } while (0); |
11960 | // Step 11: Update the navigation API entries for a same-document |
11961 | // navigation given document's relevant global object's navigation API, |
11962 | // newEntry, and historyHandling. |
11963 | navigation->UpdateEntriesForSameDocumentNavigation( |
11964 | mActiveEntry.get(), |
11965 | isReplace ? NavigationType::Replace : NavigationType::Push); |
11966 | } |
11967 | |
11968 | return NS_OK; |
11969 | } |
11970 | |
11971 | NS_IMETHODIMPnsresult |
11972 | nsDocShell::GetCurrentScrollRestorationIsManual(bool* aIsManual) { |
11973 | if (mozilla::SessionHistoryInParent()) { |
11974 | *aIsManual = mActiveEntry && mActiveEntry->GetScrollRestorationIsManual(); |
11975 | return NS_OK; |
11976 | } |
11977 | |
11978 | *aIsManual = false; |
11979 | if (mOSHE) { |
11980 | return mOSHE->GetScrollRestorationIsManual(aIsManual); |
11981 | } |
11982 | |
11983 | return NS_OK; |
11984 | } |
11985 | |
11986 | NS_IMETHODIMPnsresult |
11987 | nsDocShell::SetCurrentScrollRestorationIsManual(bool aIsManual) { |
11988 | SetScrollRestorationIsManualOnHistoryEntry(mOSHE, aIsManual); |
11989 | |
11990 | return NS_OK; |
11991 | } |
11992 | |
11993 | void nsDocShell::SetScrollRestorationIsManualOnHistoryEntry( |
11994 | nsISHEntry* aSHEntry, bool aIsManual) { |
11995 | if (aSHEntry) { |
11996 | aSHEntry->SetScrollRestorationIsManual(aIsManual); |
11997 | } |
11998 | |
11999 | if (mActiveEntry && mBrowsingContext) { |
12000 | mActiveEntry->SetScrollRestorationIsManual(aIsManual); |
12001 | if (XRE_IsParentProcess()) { |
12002 | SessionHistoryEntry* entry = |
12003 | mBrowsingContext->Canonical()->GetActiveSessionHistoryEntry(); |
12004 | if (entry) { |
12005 | entry->SetScrollRestorationIsManual(aIsManual); |
12006 | } |
12007 | } else { |
12008 | mozilla::Unused << ContentChild::GetSingleton() |
12009 | ->SendSessionHistoryEntryScrollRestorationIsManual( |
12010 | mBrowsingContext, aIsManual); |
12011 | } |
12012 | } |
12013 | } |
12014 | |
12015 | void nsDocShell::SetCacheKeyOnHistoryEntry(nsISHEntry* aSHEntry, |
12016 | uint32_t aCacheKey) { |
12017 | if (aSHEntry) { |
12018 | aSHEntry->SetCacheKey(aCacheKey); |
12019 | } |
12020 | |
12021 | if (mActiveEntry && mBrowsingContext) { |
12022 | mActiveEntry->SetCacheKey(aCacheKey); |
12023 | if (XRE_IsParentProcess()) { |
12024 | SessionHistoryEntry* entry = |
12025 | mBrowsingContext->Canonical()->GetActiveSessionHistoryEntry(); |
12026 | if (entry) { |
12027 | entry->SetCacheKey(aCacheKey); |
12028 | } |
12029 | } else { |
12030 | mozilla::Unused |
12031 | << ContentChild::GetSingleton()->SendSessionHistoryEntryCacheKey( |
12032 | mBrowsingContext, aCacheKey); |
12033 | } |
12034 | } |
12035 | } |
12036 | |
12037 | /* static */ |
12038 | bool nsDocShell::ShouldAddToSessionHistory(nsIURI* aURI, nsIChannel* aChannel) { |
12039 | // I believe none of the about: urls should go in the history. But then |
12040 | // that could just be me... If the intent is only deny about:blank then we |
12041 | // should just do a spec compare, rather than two gets of the scheme and |
12042 | // then the path. -Gagan |
12043 | nsresult rv; |
12044 | nsAutoCString buf; |
12045 | |
12046 | rv = aURI->GetScheme(buf); |
12047 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
12048 | return false; |
12049 | } |
12050 | |
12051 | if (buf.EqualsLiteral("about")) { |
12052 | rv = aURI->GetPathQueryRef(buf); |
12053 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
12054 | return false; |
12055 | } |
12056 | |
12057 | if (buf.EqualsLiteral("blank")) { |
12058 | return false; |
12059 | } |
12060 | // We only want to add about:newtab if it's not privileged, and |
12061 | // if it is not configured to show the blank page. |
12062 | if (buf.EqualsLiteral("newtab")) { |
12063 | if (!StaticPrefs::browser_newtabpage_enabled()) { |
12064 | return false; |
12065 | } |
12066 | |
12067 | NS_ENSURE_TRUE(aChannel, false)do { if ((__builtin_expect(!!(!(aChannel)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aChannel" ") failed", nullptr , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 12067); return false; } } while (false); |
12068 | nsCOMPtr<nsIPrincipal> resultPrincipal; |
12069 | rv = nsContentUtils::GetSecurityManager()->GetChannelResultPrincipal( |
12070 | aChannel, getter_AddRefs(resultPrincipal)); |
12071 | NS_ENSURE_SUCCESS(rv, false)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "false", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 12071); return false; } } while (false); |
12072 | return !resultPrincipal->IsSystemPrincipal(); |
12073 | } |
12074 | } |
12075 | |
12076 | return true; |
12077 | } |
12078 | |
12079 | nsresult nsDocShell::AddToSessionHistory( |
12080 | nsIURI* aURI, nsIChannel* aChannel, nsIPrincipal* aTriggeringPrincipal, |
12081 | nsIPrincipal* aPrincipalToInherit, |
12082 | nsIPrincipal* aPartitionedPrincipalToInherit, |
12083 | nsIContentSecurityPolicy* aCsp, bool aCloneChildren, |
12084 | nsISHEntry** aNewEntry) { |
12085 | MOZ_ASSERT(aURI, "uri is null")do { static_assert( mozilla::detail::AssertionConditionType< decltype(aURI)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(aURI))), 0))) { do { } while (false ); MOZ_ReportAssertionFailure("aURI" " (" "uri is null" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 12085); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aURI" ") (" "uri is null" ")"); do { MOZ_CrashSequence(__null, 12085); __attribute__ ((nomerge)) ::abort(); } while (false); } } while (false); |
12086 | MOZ_ASSERT(!aChannel || !aTriggeringPrincipal, "Shouldn't have both set")do { static_assert( mozilla::detail::AssertionConditionType< decltype(!aChannel || !aTriggeringPrincipal)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!aChannel || !aTriggeringPrincipal ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "!aChannel || !aTriggeringPrincipal" " (" "Shouldn't have both set" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 12086 ); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aChannel || !aTriggeringPrincipal" ") (" "Shouldn't have both set" ")"); do { MOZ_CrashSequence (__null, 12086); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); |
12087 | MOZ_DIAGNOSTIC_ASSERT(!mozilla::SessionHistoryInParent())do { static_assert( mozilla::detail::AssertionConditionType< decltype(!mozilla::SessionHistoryInParent())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!mozilla::SessionHistoryInParent ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("!mozilla::SessionHistoryInParent()", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 12087); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "!mozilla::SessionHistoryInParent()" ")"); do { MOZ_CrashSequence(__null, 12087); __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
12088 | |
12089 | #if defined(DEBUG1) |
12090 | if (MOZ_LOG_TEST(gDocShellLog, LogLevel::Debug)(__builtin_expect(!!(mozilla::detail::log_test(gDocShellLog, LogLevel ::Debug)), 0))) { |
12091 | nsAutoCString chanName; |
12092 | if (aChannel) { |
12093 | aChannel->GetName(chanName); |
12094 | } else { |
12095 | chanName.AssignLiteral("<no channel>"); |
12096 | } |
12097 | |
12098 | MOZ_LOG(gDocShellLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gDocShellLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "nsDocShell[%p]::AddToSessionHistory(\"%s\", [%s])\n" , this, aURI->GetSpecOrDefault().get(), chanName.get()); } } while (0) |
12099 | ("nsDocShell[%p]::AddToSessionHistory(\"%s\", [%s])\n", this,do { const ::mozilla::LogModule* moz_real_module = gDocShellLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "nsDocShell[%p]::AddToSessionHistory(\"%s\", [%s])\n" , this, aURI->GetSpecOrDefault().get(), chanName.get()); } } while (0) |
12100 | aURI->GetSpecOrDefault().get(), chanName.get()))do { const ::mozilla::LogModule* moz_real_module = gDocShellLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "nsDocShell[%p]::AddToSessionHistory(\"%s\", [%s])\n" , this, aURI->GetSpecOrDefault().get(), chanName.get()); } } while (0); |
12101 | } |
12102 | #endif |
12103 | |
12104 | nsresult rv = NS_OK; |
12105 | nsCOMPtr<nsISHEntry> entry; |
12106 | |
12107 | /* |
12108 | * If this is a LOAD_FLAGS_REPLACE_HISTORY in a subframe, we use |
12109 | * the existing SH entry in the page and replace the url and |
12110 | * other vitalities. |
12111 | */ |
12112 | if (LOAD_TYPE_HAS_FLAGS(mLoadType, LOAD_FLAGS_REPLACE_HISTORY)((mLoadType) & ((LOAD_FLAGS_REPLACE_HISTORY) << 16) ) && |
12113 | !mBrowsingContext->IsTop()) { |
12114 | // This is a subframe |
12115 | entry = mOSHE; |
12116 | if (entry) { |
12117 | entry->ClearEntry(); |
12118 | } |
12119 | } |
12120 | |
12121 | // Create a new entry if necessary. |
12122 | if (!entry) { |
12123 | entry = new nsSHEntry(); |
12124 | } |
12125 | |
12126 | // Get the post data & referrer |
12127 | nsCOMPtr<nsIInputStream> inputStream; |
12128 | nsCOMPtr<nsIURI> originalURI; |
12129 | nsCOMPtr<nsIURI> resultPrincipalURI; |
12130 | nsCOMPtr<nsIURI> unstrippedURI; |
12131 | bool loadReplace = false; |
12132 | nsCOMPtr<nsIReferrerInfo> referrerInfo; |
12133 | uint32_t cacheKey = 0; |
12134 | nsCOMPtr<nsIPrincipal> triggeringPrincipal = aTriggeringPrincipal; |
12135 | nsCOMPtr<nsIPrincipal> principalToInherit = aPrincipalToInherit; |
12136 | nsCOMPtr<nsIPrincipal> partitionedPrincipalToInherit = |
12137 | aPartitionedPrincipalToInherit; |
12138 | nsCOMPtr<nsIContentSecurityPolicy> csp = aCsp; |
12139 | bool expired = false; // by default the page is not expired |
12140 | bool discardLayoutState = false; |
12141 | nsCOMPtr<nsICacheInfoChannel> cacheChannel; |
12142 | bool userActivation = false; |
12143 | |
12144 | if (aChannel) { |
12145 | cacheChannel = do_QueryInterface(aChannel); |
12146 | |
12147 | /* If there is a caching channel, get the Cache Key and store it |
12148 | * in SH. |
12149 | */ |
12150 | if (cacheChannel) { |
12151 | cacheChannel->GetCacheKey(&cacheKey); |
12152 | } |
12153 | nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(aChannel)); |
12154 | |
12155 | // Check if the httpChannel is hiding under a multipartChannel |
12156 | if (!httpChannel) { |
12157 | GetHttpChannel(aChannel, getter_AddRefs(httpChannel)); |
12158 | } |
12159 | if (httpChannel) { |
12160 | nsCOMPtr<nsIUploadChannel> uploadChannel(do_QueryInterface(httpChannel)); |
12161 | if (uploadChannel) { |
12162 | uploadChannel->GetUploadStream(getter_AddRefs(inputStream)); |
12163 | } |
12164 | httpChannel->GetOriginalURI(getter_AddRefs(originalURI)); |
12165 | uint32_t loadFlags; |
12166 | aChannel->GetLoadFlags(&loadFlags); |
12167 | loadReplace = loadFlags & nsIChannel::LOAD_REPLACE; |
12168 | rv = httpChannel->GetReferrerInfo(getter_AddRefs(referrerInfo)); |
12169 | MOZ_ASSERT(NS_SUCCEEDED(rv))do { static_assert( mozilla::detail::AssertionConditionType< decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1) )))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1) ))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 12169); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))" ")"); do { MOZ_CrashSequence(__null, 12169); __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
12170 | |
12171 | discardLayoutState = ShouldDiscardLayoutState(httpChannel); |
12172 | } |
12173 | |
12174 | nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo(); |
12175 | if (!triggeringPrincipal) { |
12176 | triggeringPrincipal = loadInfo->TriggeringPrincipal(); |
12177 | } |
12178 | if (!csp) { |
12179 | csp = loadInfo->GetCspToInherit(); |
12180 | } |
12181 | |
12182 | loadInfo->GetResultPrincipalURI(getter_AddRefs(resultPrincipalURI)); |
12183 | |
12184 | loadInfo->GetUnstrippedURI(getter_AddRefs(unstrippedURI)); |
12185 | |
12186 | userActivation = loadInfo->GetHasValidUserGestureActivation(); |
12187 | |
12188 | // For now keep storing just the principal in the SHEntry. |
12189 | if (!principalToInherit) { |
12190 | if (loadInfo->GetLoadingSandboxed()) { |
12191 | if (loadInfo->GetLoadingPrincipal()) { |
12192 | principalToInherit = NullPrincipal::CreateWithInheritedAttributes( |
12193 | loadInfo->GetLoadingPrincipal()); |
12194 | } else { |
12195 | // get the OriginAttributes |
12196 | OriginAttributes attrs; |
12197 | loadInfo->GetOriginAttributes(&attrs); |
12198 | principalToInherit = NullPrincipal::Create(attrs); |
12199 | } |
12200 | } else { |
12201 | principalToInherit = loadInfo->PrincipalToInherit(); |
12202 | } |
12203 | } |
12204 | |
12205 | if (!partitionedPrincipalToInherit) { |
12206 | // XXXehsan is it correct to fall back to the principal to inherit in all |
12207 | // cases? For example, what about the cases where we are using the load |
12208 | // info's principal to inherit? Do we need to add a similar concept to |
12209 | // load info for partitioned principal? |
12210 | partitionedPrincipalToInherit = principalToInherit; |
12211 | } |
12212 | } |
12213 | |
12214 | nsAutoString srcdoc; |
12215 | bool srcdocEntry = false; |
12216 | nsCOMPtr<nsIURI> baseURI; |
12217 | |
12218 | nsCOMPtr<nsIInputStreamChannel> inStrmChan = do_QueryInterface(aChannel); |
12219 | if (inStrmChan) { |
12220 | bool isSrcdocChannel; |
12221 | inStrmChan->GetIsSrcdocChannel(&isSrcdocChannel); |
12222 | if (isSrcdocChannel) { |
12223 | inStrmChan->GetSrcdocData(srcdoc); |
12224 | srcdocEntry = true; |
12225 | inStrmChan->GetBaseURI(getter_AddRefs(baseURI)); |
12226 | } else { |
12227 | srcdoc.SetIsVoid(true); |
12228 | } |
12229 | } |
12230 | /* If cache got a 'no-store', ask SH not to store |
12231 | * HistoryLayoutState. By default, SH will set this |
12232 | * flag to true and save HistoryLayoutState. |
12233 | */ |
12234 | bool saveLayoutState = !discardLayoutState; |
12235 | |
12236 | if (cacheChannel) { |
12237 | // Check if the page has expired from cache |
12238 | uint32_t expTime = 0; |
12239 | cacheChannel->GetCacheTokenExpirationTime(&expTime); |
12240 | uint32_t now = PRTimeToSeconds(PR_Now()); |
12241 | if (expTime <= now) { |
12242 | expired = true; |
12243 | } |
12244 | } |
12245 | |
12246 | // Title is set in nsDocShell::SetTitle() |
12247 | entry->Create(aURI, // uri |
12248 | u""_ns, // Title |
12249 | inputStream, // Post data stream |
12250 | cacheKey, // CacheKey |
12251 | mContentTypeHint, // Content-type |
12252 | triggeringPrincipal, // Channel or provided principal |
12253 | principalToInherit, partitionedPrincipalToInherit, csp, |
12254 | HistoryID(), GetCreatedDynamically(), originalURI, |
12255 | resultPrincipalURI, unstrippedURI, loadReplace, referrerInfo, |
12256 | srcdoc, srcdocEntry, baseURI, saveLayoutState, expired, |
12257 | userActivation); |
12258 | |
12259 | if (mBrowsingContext->IsTop() && GetSessionHistory()) { |
12260 | Maybe<int32_t> previousEntryIndex; |
12261 | Maybe<int32_t> loadedEntryIndex; |
12262 | |
12263 | if (mBrowsingContext->IsTop() && |
12264 | !ShouldAddToSessionHistory(aURI, aChannel)) { |
12265 | entry->SetTransient(); |
12266 | } |
12267 | rv = GetSessionHistory()->LegacySHistory()->AddToRootSessionHistory( |
12268 | aCloneChildren, mOSHE, mBrowsingContext, entry, mLoadType, |
12269 | &previousEntryIndex, &loadedEntryIndex); |
12270 | |
12271 | MOZ_ASSERT(NS_SUCCEEDED(rv), "Could not add entry to root session history")do { static_assert( mozilla::detail::AssertionConditionType< decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1) )))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1) ))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))" " (" "Could not add entry to root session history" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 12271); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))" ") (" "Could not add entry to root session history" ")"); do { MOZ_CrashSequence(__null, 12271); __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
12272 | if (previousEntryIndex.isSome()) { |
12273 | mPreviousEntryIndex = previousEntryIndex.value(); |
12274 | } |
12275 | if (loadedEntryIndex.isSome()) { |
12276 | mLoadedEntryIndex = loadedEntryIndex.value(); |
12277 | } |
12278 | |
12279 | // aCloneChildren implies that we are retaining the same document, thus we |
12280 | // need to signal to the top WC that the new SHEntry may receive a fresh |
12281 | // user interaction flag. |
12282 | if (aCloneChildren) { |
12283 | WindowContext* topWc = mBrowsingContext->GetTopWindowContext(); |
12284 | if (topWc && !topWc->IsDiscarded()) { |
12285 | MOZ_ALWAYS_SUCCEEDS(topWc->SetSHEntryHasUserInteraction(false))do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl (topWc->SetSHEntryHasUserInteraction(false))), 1)))), 1))) { } else { do { do { } while (false); MOZ_ReportCrash("" "NS_SUCCEEDED(topWc->SetSHEntryHasUserInteraction(false))" , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 12285); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(topWc->SetSHEntryHasUserInteraction(false))" ")"); do { MOZ_CrashSequence(__null, 12285); __attribute__(( nomerge)) ::abort(); } while (false); } while (false); } } while (false); |
12286 | } |
12287 | } |
12288 | } else { |
12289 | // This is a subframe, make sure that this new SHEntry will be |
12290 | // marked with user interaction. |
12291 | WindowContext* topWc = mBrowsingContext->GetTopWindowContext(); |
12292 | if (topWc && !topWc->IsDiscarded()) { |
12293 | MOZ_ALWAYS_SUCCEEDS(topWc->SetSHEntryHasUserInteraction(false))do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl (topWc->SetSHEntryHasUserInteraction(false))), 1)))), 1))) { } else { do { do { } while (false); MOZ_ReportCrash("" "NS_SUCCEEDED(topWc->SetSHEntryHasUserInteraction(false))" , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 12293); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(topWc->SetSHEntryHasUserInteraction(false))" ")"); do { MOZ_CrashSequence(__null, 12293); __attribute__(( nomerge)) ::abort(); } while (false); } while (false); } } while (false); |
12294 | } |
12295 | if (!mOSHE || !LOAD_TYPE_HAS_FLAGS(mLoadType, LOAD_FLAGS_REPLACE_HISTORY)((mLoadType) & ((LOAD_FLAGS_REPLACE_HISTORY) << 16) )) { |
12296 | rv = AddChildSHEntryToParent(entry, mBrowsingContext->ChildOffset(), |
12297 | aCloneChildren); |
12298 | } |
12299 | } |
12300 | |
12301 | // Return the new SH entry... |
12302 | if (aNewEntry) { |
12303 | *aNewEntry = nullptr; |
12304 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) { |
12305 | entry.forget(aNewEntry); |
12306 | } |
12307 | } |
12308 | |
12309 | return rv; |
12310 | } |
12311 | |
12312 | void nsDocShell::UpdateActiveEntry( |
12313 | bool aReplace, const Maybe<nsPoint>& aPreviousScrollPos, nsIURI* aURI, |
12314 | nsIURI* aOriginalURI, nsIReferrerInfo* aReferrerInfo, |
12315 | nsIPrincipal* aTriggeringPrincipal, nsIContentSecurityPolicy* aCsp, |
12316 | const nsAString& aTitle, bool aScrollRestorationIsManual, |
12317 | nsIStructuredCloneContainer* aData, bool aURIWasModified, |
12318 | nsIPrincipal* aPartitionedPrincipal) { |
12319 | MOZ_ASSERT(mozilla::SessionHistoryInParent())do { static_assert( mozilla::detail::AssertionConditionType< decltype(mozilla::SessionHistoryInParent())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mozilla::SessionHistoryInParent ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("mozilla::SessionHistoryInParent()", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 12319); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mozilla::SessionHistoryInParent()" ")"); do { MOZ_CrashSequence(__null, 12319); __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
12320 | MOZ_ASSERT(aURI, "uri is null")do { static_assert( mozilla::detail::AssertionConditionType< decltype(aURI)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(aURI))), 0))) { do { } while (false ); MOZ_ReportAssertionFailure("aURI" " (" "uri is null" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 12320); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aURI" ") (" "uri is null" ")"); do { MOZ_CrashSequence(__null, 12320); __attribute__ ((nomerge)) ::abort(); } while (false); } } while (false); |
12321 | MOZ_ASSERT(mLoadType == LOAD_PUSHSTATE,do { static_assert( mozilla::detail::AssertionConditionType< decltype(mLoadType == LOAD_PUSHSTATE)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mLoadType == LOAD_PUSHSTATE) )), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mLoadType == LOAD_PUSHSTATE" " (" "This code only deals with pushState" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 12322); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLoadType == LOAD_PUSHSTATE" ") (" "This code only deals with pushState" ")"); do { MOZ_CrashSequence (__null, 12322); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false) |
12322 | "This code only deals with pushState")do { static_assert( mozilla::detail::AssertionConditionType< decltype(mLoadType == LOAD_PUSHSTATE)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mLoadType == LOAD_PUSHSTATE) )), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mLoadType == LOAD_PUSHSTATE" " (" "This code only deals with pushState" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 12322); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLoadType == LOAD_PUSHSTATE" ") (" "This code only deals with pushState" ")"); do { MOZ_CrashSequence (__null, 12322); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); |
12323 | MOZ_ASSERT_IF(aPreviousScrollPos.isSome(), !aReplace)do { if (aPreviousScrollPos.isSome()) { do { static_assert( mozilla ::detail::AssertionConditionType<decltype(!aReplace)>:: isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(!aReplace))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("!aReplace", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 12323); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aReplace" ")"); do { MOZ_CrashSequence(__null, 12323); __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); } } while (false); |
12324 | |
12325 | MOZ_LOG(gSHLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gSHLog; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "Creating an active entry on nsDocShell %p to %s" , this, aURI->GetSpecOrDefault().get()); } } while (0) |
12326 | ("Creating an active entry on nsDocShell %p to %s", this,do { const ::mozilla::LogModule* moz_real_module = gSHLog; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "Creating an active entry on nsDocShell %p to %s" , this, aURI->GetSpecOrDefault().get()); } } while (0) |
12327 | aURI->GetSpecOrDefault().get()))do { const ::mozilla::LogModule* moz_real_module = gSHLog; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "Creating an active entry on nsDocShell %p to %s" , this, aURI->GetSpecOrDefault().get()); } } while (0); |
12328 | |
12329 | // Even if we're replacing an existing entry we create new a |
12330 | // SessionHistoryInfo. In the parent process we'll keep the existing |
12331 | // SessionHistoryEntry, but just replace its SessionHistoryInfo, that way the |
12332 | // entry keeps identity but its data is replaced. |
12333 | bool replace = aReplace && mActiveEntry; |
12334 | |
12335 | if (!replace) { |
12336 | CollectWireframe(); |
12337 | } |
12338 | |
12339 | UniquePtr<SessionHistoryInfo> previousActiveEntry(mActiveEntry.release()); |
12340 | if (previousActiveEntry) { |
12341 | // Link this entry to the previous active entry. |
12342 | mActiveEntry = MakeUnique<SessionHistoryInfo>(*previousActiveEntry, aURI); |
12343 | } else { |
12344 | mActiveEntry = MakeUnique<SessionHistoryInfo>( |
12345 | aURI, aTriggeringPrincipal, nullptr, nullptr, aCsp, mContentTypeHint); |
12346 | } |
12347 | mActiveEntry->SetOriginalURI(aOriginalURI); |
12348 | mActiveEntry->SetUnstrippedURI(nullptr); |
12349 | mActiveEntry->SetReferrerInfo(aReferrerInfo); |
12350 | mActiveEntry->SetTitle(aTitle); |
12351 | mActiveEntry->SetStateData(static_cast<nsStructuredCloneContainer*>(aData)); |
12352 | mActiveEntry->SetURIWasModified(aURIWasModified); |
12353 | mActiveEntry->SetScrollRestorationIsManual(aScrollRestorationIsManual); |
12354 | mActiveEntry->SetPartitionedPrincipalToInherit(aPartitionedPrincipal); |
12355 | |
12356 | if (replace) { |
12357 | mBrowsingContext->ReplaceActiveSessionHistoryEntry(mActiveEntry.get()); |
12358 | } else { |
12359 | mBrowsingContext->IncrementHistoryEntryCountForBrowsingContext(); |
12360 | // FIXME We should probably just compute mChildOffset in the parent |
12361 | // instead of passing it over IPC here. |
12362 | mBrowsingContext->SetActiveSessionHistoryEntry( |
12363 | aPreviousScrollPos, mActiveEntry.get(), previousActiveEntry.get(), |
12364 | mLoadType, |
12365 | /* aCacheKey = */ 0); |
12366 | // FIXME Do we need to update mPreviousEntryIndex and mLoadedEntryIndex? |
12367 | } |
12368 | } |
12369 | |
12370 | nsresult nsDocShell::LoadHistoryEntry(nsISHEntry* aEntry, uint32_t aLoadType, |
12371 | bool aUserActivation) { |
12372 | NS_ENSURE_TRUE(aEntry, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(aEntry)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aEntry" ") failed", nullptr , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 12372); return NS_ERROR_FAILURE; } } while (false); |
12373 | |
12374 | nsresult rv; |
12375 | RefPtr<nsDocShellLoadState> loadState; |
12376 | rv = aEntry->CreateLoadInfo(getter_AddRefs(loadState)); |
12377 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 12377); return rv; } } while (false); |
12378 | |
12379 | // Calling CreateAboutBlankDocumentViewer can set mOSHE to null, and if |
12380 | // that's the only thing holding a ref to aEntry that will cause aEntry to |
12381 | // die while we're loading it. So hold a strong ref to aEntry here, just |
12382 | // in case. |
12383 | nsCOMPtr<nsISHEntry> kungFuDeathGrip(aEntry); |
12384 | |
12385 | loadState->SetHasValidUserGestureActivation( |
12386 | loadState->HasValidUserGestureActivation() || aUserActivation); |
12387 | |
12388 | loadState->SetTextDirectiveUserActivation( |
12389 | loadState->GetTextDirectiveUserActivation() || aUserActivation); |
12390 | |
12391 | return LoadHistoryEntry(loadState, aLoadType, aEntry == mOSHE); |
12392 | } |
12393 | |
12394 | nsresult nsDocShell::LoadHistoryEntry(const LoadingSessionHistoryInfo& aEntry, |
12395 | uint32_t aLoadType, |
12396 | bool aUserActivation) { |
12397 | RefPtr<nsDocShellLoadState> loadState = aEntry.CreateLoadInfo(); |
12398 | loadState->SetHasValidUserGestureActivation( |
12399 | loadState->HasValidUserGestureActivation() || aUserActivation); |
12400 | |
12401 | loadState->SetTextDirectiveUserActivation( |
12402 | loadState->GetTextDirectiveUserActivation() || aUserActivation); |
12403 | |
12404 | return LoadHistoryEntry(loadState, aLoadType, aEntry.mLoadingCurrentEntry); |
12405 | } |
12406 | |
12407 | nsresult nsDocShell::LoadHistoryEntry(nsDocShellLoadState* aLoadState, |
12408 | uint32_t aLoadType, |
12409 | bool aLoadingCurrentEntry) { |
12410 | if (!IsNavigationAllowed()) { |
12411 | return NS_OK; |
12412 | } |
12413 | |
12414 | // We are setting load type afterwards so we don't have to |
12415 | // send it in an IPC message |
12416 | aLoadState->SetLoadType(aLoadType); |
12417 | |
12418 | nsresult rv; |
12419 | if (aLoadState->URI()->SchemeIs("javascript")) { |
12420 | // We're loading a URL that will execute script from inside asyncOpen. |
12421 | // Replace the current document with about:blank now to prevent |
12422 | // anything from the current document from leaking into any JavaScript |
12423 | // code in the URL. |
12424 | // Don't cache the presentation if we're going to just reload the |
12425 | // current entry. Caching would lead to trying to save the different |
12426 | // content viewers in the same nsISHEntry object. |
12427 | rv = CreateAboutBlankDocumentViewer( |
12428 | aLoadState->PrincipalToInherit(), |
12429 | aLoadState->PartitionedPrincipalToInherit(), nullptr, nullptr, |
12430 | /* aIsInitialDocument */ false, Nothing(), !aLoadingCurrentEntry); |
12431 | |
12432 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
12433 | // The creation of the intermittent about:blank content |
12434 | // viewer failed for some reason (potentially because the |
12435 | // user prevented it). Interrupt the history load. |
12436 | return NS_OK; |
12437 | } |
12438 | |
12439 | if (!aLoadState->TriggeringPrincipal()) { |
12440 | // Ensure that we have a triggeringPrincipal. Otherwise javascript: |
12441 | // URIs will pick it up from the about:blank page we just loaded, |
12442 | // and we don't really want even that in this case. |
12443 | nsCOMPtr<nsIPrincipal> principal = |
12444 | NullPrincipal::Create(GetOriginAttributes()); |
12445 | aLoadState->SetTriggeringPrincipal(principal); |
12446 | } |
12447 | } |
12448 | |
12449 | /* If there is a valid postdata *and* the user pressed |
12450 | * reload or shift-reload, take user's permission before we |
12451 | * repost the data to the server. |
12452 | */ |
12453 | if ((aLoadType & LOAD_CMD_RELOAD) && aLoadState->PostDataStream()) { |
12454 | bool repost; |
12455 | rv = ConfirmRepost(&repost); |
12456 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
12457 | return rv; |
12458 | } |
12459 | |
12460 | // If the user pressed cancel in the dialog, return. We're done here. |
12461 | if (!repost) { |
12462 | return NS_BINDING_ABORTED; |
12463 | } |
12464 | } |
12465 | |
12466 | // If there is no valid triggeringPrincipal, we deny the load |
12467 | MOZ_ASSERT(aLoadState->TriggeringPrincipal(),do { static_assert( mozilla::detail::AssertionConditionType< decltype(aLoadState->TriggeringPrincipal())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aLoadState->TriggeringPrincipal ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("aLoadState->TriggeringPrincipal()" " (" "need a valid triggeringPrincipal to load from history" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 12468 ); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->TriggeringPrincipal()" ") (" "need a valid triggeringPrincipal to load from history" ")"); do { MOZ_CrashSequence(__null, 12468); __attribute__(( nomerge)) ::abort(); } while (false); } } while (false) |
12468 | "need a valid triggeringPrincipal to load from history")do { static_assert( mozilla::detail::AssertionConditionType< decltype(aLoadState->TriggeringPrincipal())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aLoadState->TriggeringPrincipal ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("aLoadState->TriggeringPrincipal()" " (" "need a valid triggeringPrincipal to load from history" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 12468 ); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->TriggeringPrincipal()" ") (" "need a valid triggeringPrincipal to load from history" ")"); do { MOZ_CrashSequence(__null, 12468); __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
12469 | if (!aLoadState->TriggeringPrincipal()) { |
12470 | return NS_ERROR_FAILURE; |
12471 | } |
12472 | |
12473 | return InternalLoad(aLoadState); // No nsIRequest |
12474 | } |
12475 | |
12476 | NS_IMETHODIMPnsresult |
12477 | nsDocShell::PersistLayoutHistoryState() { |
12478 | nsresult rv = NS_OK; |
12479 | |
12480 | if (mozilla::SessionHistoryInParent() ? !!mActiveEntry : !!mOSHE) { |
12481 | bool scrollRestorationIsManual; |
12482 | if (mozilla::SessionHistoryInParent()) { |
12483 | scrollRestorationIsManual = mActiveEntry->GetScrollRestorationIsManual(); |
12484 | } else { |
12485 | scrollRestorationIsManual = mOSHE->GetScrollRestorationIsManual(); |
12486 | } |
12487 | nsCOMPtr<nsILayoutHistoryState> layoutState; |
12488 | if (RefPtr<PresShell> presShell = GetPresShell()) { |
12489 | rv = presShell->CaptureHistoryState(getter_AddRefs(layoutState)); |
12490 | } else if (scrollRestorationIsManual) { |
12491 | // Even if we don't have layout anymore, we may want to reset the |
12492 | // current scroll state in layout history. |
12493 | GetLayoutHistoryState(getter_AddRefs(layoutState)); |
12494 | } |
12495 | |
12496 | if (scrollRestorationIsManual && layoutState) { |
12497 | layoutState->ResetScrollState(); |
12498 | } |
12499 | } |
12500 | |
12501 | return rv; |
12502 | } |
12503 | |
12504 | void nsDocShell::SwapHistoryEntries(nsISHEntry* aOldEntry, |
12505 | nsISHEntry* aNewEntry) { |
12506 | if (aOldEntry == mOSHE) { |
12507 | mOSHE = aNewEntry; |
12508 | } |
12509 | |
12510 | if (aOldEntry == mLSHE) { |
12511 | mLSHE = aNewEntry; |
12512 | } |
12513 | } |
12514 | |
12515 | void nsDocShell::SetHistoryEntryAndUpdateBC(const Maybe<nsISHEntry*>& aLSHE, |
12516 | const Maybe<nsISHEntry*>& aOSHE) { |
12517 | // We want to hold on to the reference in mLSHE before we update it. |
12518 | // Otherwise, SetHistoryEntry could release the last reference to |
12519 | // the entry while aOSHE is pointing to it. |
12520 | nsCOMPtr<nsISHEntry> deathGripOldLSHE; |
12521 | if (aLSHE.isSome()) { |
12522 | deathGripOldLSHE = SetHistoryEntry(&mLSHE, aLSHE.value()); |
12523 | MOZ_ASSERT(mLSHE.get() == aLSHE.value())do { static_assert( mozilla::detail::AssertionConditionType< decltype(mLSHE.get() == aLSHE.value())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mLSHE.get() == aLSHE.value() ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "mLSHE.get() == aLSHE.value()", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 12523); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLSHE.get() == aLSHE.value()" ")"); do { MOZ_CrashSequence(__null, 12523); __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
12524 | } |
12525 | nsCOMPtr<nsISHEntry> deathGripOldOSHE; |
12526 | if (aOSHE.isSome()) { |
12527 | deathGripOldOSHE = SetHistoryEntry(&mOSHE, aOSHE.value()); |
12528 | MOZ_ASSERT(mOSHE.get() == aOSHE.value())do { static_assert( mozilla::detail::AssertionConditionType< decltype(mOSHE.get() == aOSHE.value())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mOSHE.get() == aOSHE.value() ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "mOSHE.get() == aOSHE.value()", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 12528); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mOSHE.get() == aOSHE.value()" ")"); do { MOZ_CrashSequence(__null, 12528); __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
12529 | } |
12530 | } |
12531 | |
12532 | already_AddRefed<nsISHEntry> nsDocShell::SetHistoryEntry( |
12533 | nsCOMPtr<nsISHEntry>* aPtr, nsISHEntry* aEntry) { |
12534 | // We need to sync up the docshell and session history trees for |
12535 | // subframe navigation. If the load was in a subframe, we forward up to |
12536 | // the root docshell, which will then recursively sync up all docshells |
12537 | // to their corresponding entries in the new session history tree. |
12538 | // If we don't do this, then we can cache a content viewer on the wrong |
12539 | // cloned entry, and subsequently restore it at the wrong time. |
12540 | RefPtr<BrowsingContext> topBC = mBrowsingContext->Top(); |
12541 | if (topBC->IsDiscarded()) { |
12542 | topBC = nullptr; |
12543 | } |
12544 | RefPtr<BrowsingContext> currBC = |
12545 | mBrowsingContext->IsDiscarded() ? nullptr : mBrowsingContext; |
12546 | if (topBC && *aPtr) { |
12547 | (*aPtr)->SyncTreesForSubframeNavigation(aEntry, topBC, currBC); |
12548 | } |
12549 | nsCOMPtr<nsISHEntry> entry(aEntry); |
12550 | entry.swap(*aPtr); |
12551 | return entry.forget(); |
12552 | } |
12553 | |
12554 | already_AddRefed<ChildSHistory> nsDocShell::GetRootSessionHistory() { |
12555 | RefPtr<ChildSHistory> childSHistory = |
12556 | mBrowsingContext->Top()->GetChildSessionHistory(); |
12557 | return childSHistory.forget(); |
12558 | } |
12559 | |
12560 | nsresult nsDocShell::GetHttpChannel(nsIChannel* aChannel, |
12561 | nsIHttpChannel** aReturn) { |
12562 | NS_ENSURE_ARG_POINTER(aReturn)do { if ((__builtin_expect(!!(!(aReturn)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aReturn" ") failed", nullptr , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 12562); return NS_ERROR_INVALID_POINTER; } } while (false); |
12563 | if (!aChannel) { |
12564 | return NS_ERROR_FAILURE; |
12565 | } |
12566 | |
12567 | nsCOMPtr<nsIMultiPartChannel> multiPartChannel(do_QueryInterface(aChannel)); |
12568 | if (multiPartChannel) { |
12569 | nsCOMPtr<nsIChannel> baseChannel; |
12570 | multiPartChannel->GetBaseChannel(getter_AddRefs(baseChannel)); |
12571 | nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(baseChannel)); |
12572 | *aReturn = httpChannel; |
12573 | NS_IF_ADDREF(*aReturn)ns_if_addref(*aReturn); |
12574 | } |
12575 | return NS_OK; |
12576 | } |
12577 | |
12578 | bool nsDocShell::ShouldDiscardLayoutState(nsIHttpChannel* aChannel) { |
12579 | // By default layout State will be saved. |
12580 | if (!aChannel) { |
12581 | return false; |
12582 | } |
12583 | |
12584 | // figure out if SH should be saving layout state |
12585 | bool noStore = false; |
12586 | Unused << aChannel->IsNoStoreResponse(&noStore); |
12587 | return noStore; |
12588 | } |
12589 | |
12590 | NS_IMETHODIMPnsresult |
12591 | nsDocShell::GetEditor(nsIEditor** aEditor) { |
12592 | NS_ENSURE_ARG_POINTER(aEditor)do { if ((__builtin_expect(!!(!(aEditor)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aEditor" ") failed", nullptr , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 12592); return NS_ERROR_INVALID_POINTER; } } while (false); |
12593 | RefPtr<HTMLEditor> htmlEditor = GetHTMLEditorInternal(); |
12594 | htmlEditor.forget(aEditor); |
12595 | return NS_OK; |
12596 | } |
12597 | |
12598 | NS_IMETHODIMPnsresult |
12599 | nsDocShell::SetEditor(nsIEditor* aEditor) { |
12600 | HTMLEditor* htmlEditor = aEditor ? aEditor->GetAsHTMLEditor() : nullptr; |
12601 | // If TextEditor comes, throw an error. |
12602 | if (aEditor && !htmlEditor) { |
12603 | return NS_ERROR_INVALID_ARG; |
12604 | } |
12605 | return SetHTMLEditorInternal(htmlEditor); |
12606 | } |
12607 | |
12608 | HTMLEditor* nsDocShell::GetHTMLEditorInternal() { |
12609 | return mEditorData ? mEditorData->GetHTMLEditor() : nullptr; |
12610 | } |
12611 | |
12612 | nsresult nsDocShell::SetHTMLEditorInternal(HTMLEditor* aHTMLEditor) { |
12613 | if (!aHTMLEditor && !mEditorData) { |
12614 | return NS_OK; |
12615 | } |
12616 | |
12617 | nsresult rv = EnsureEditorData(); |
12618 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
12619 | return rv; |
12620 | } |
12621 | |
12622 | return mEditorData->SetHTMLEditor(aHTMLEditor); |
12623 | } |
12624 | |
12625 | NS_IMETHODIMPnsresult |
12626 | nsDocShell::GetEditable(bool* aEditable) { |
12627 | NS_ENSURE_ARG_POINTER(aEditable)do { if ((__builtin_expect(!!(!(aEditable)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aEditable" ") failed", nullptr , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 12627); return NS_ERROR_INVALID_POINTER; } } while (false); |
12628 | *aEditable = mEditorData && mEditorData->GetEditable(); |
12629 | return NS_OK; |
12630 | } |
12631 | |
12632 | NS_IMETHODIMPnsresult |
12633 | nsDocShell::GetHasEditingSession(bool* aHasEditingSession) { |
12634 | NS_ENSURE_ARG_POINTER(aHasEditingSession)do { if ((__builtin_expect(!!(!(aHasEditingSession)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aHasEditingSession" ") failed" , nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 12634); return NS_ERROR_INVALID_POINTER; } } while (false); |
12635 | |
12636 | if (mEditorData) { |
12637 | *aHasEditingSession = !!mEditorData->GetEditingSession(); |
12638 | } else { |
12639 | *aHasEditingSession = false; |
12640 | } |
12641 | |
12642 | return NS_OK; |
12643 | } |
12644 | |
12645 | NS_IMETHODIMPnsresult |
12646 | nsDocShell::MakeEditable(bool aInWaitForUriLoad) { |
12647 | nsresult rv = EnsureEditorData(); |
12648 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
12649 | return rv; |
12650 | } |
12651 | |
12652 | return mEditorData->MakeEditable(aInWaitForUriLoad); |
12653 | } |
12654 | |
12655 | /* static */ bool nsDocShell::ShouldAddURIVisit(nsIChannel* aChannel) { |
12656 | bool needToAddURIVisit = true; |
12657 | nsCOMPtr<nsIPropertyBag2> props(do_QueryInterface(aChannel)); |
12658 | if (props) { |
12659 | mozilla::Unused << props->GetPropertyAsBool( |
12660 | u"docshell.needToAddURIVisit"_ns, &needToAddURIVisit); |
12661 | } |
12662 | |
12663 | return needToAddURIVisit; |
12664 | } |
12665 | |
12666 | /* static */ void nsDocShell::ExtractLastVisit( |
12667 | nsIChannel* aChannel, nsIURI** aURI, uint32_t* aChannelRedirectFlags) { |
12668 | nsCOMPtr<nsIPropertyBag2> props(do_QueryInterface(aChannel)); |
12669 | if (!props) { |
12670 | return; |
12671 | } |
12672 | |
12673 | nsresult rv; |
12674 | nsCOMPtr<nsIURI> uri(do_GetProperty(props, u"docshell.previousURI"_ns, &rv)); |
12675 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) { |
12676 | uri.forget(aURI); |
12677 | |
12678 | rv = props->GetPropertyAsUint32(u"docshell.previousFlags"_ns, |
12679 | aChannelRedirectFlags); |
12680 | |
12681 | NS_WARNING_ASSERTION(do { if (!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1 ))))) { NS_DebugBreak(NS_DEBUG_WARNING, "Could not fetch previous flags, URI will be treated like referrer" , "NS_SUCCEEDED(rv)", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 12683); } } while (false) |
12682 | NS_SUCCEEDED(rv),do { if (!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1 ))))) { NS_DebugBreak(NS_DEBUG_WARNING, "Could not fetch previous flags, URI will be treated like referrer" , "NS_SUCCEEDED(rv)", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 12683); } } while (false) |
12683 | "Could not fetch previous flags, URI will be treated like referrer")do { if (!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1 ))))) { NS_DebugBreak(NS_DEBUG_WARNING, "Could not fetch previous flags, URI will be treated like referrer" , "NS_SUCCEEDED(rv)", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 12683); } } while (false); |
12684 | |
12685 | } else { |
12686 | // There is no last visit for this channel, so this must be the first |
12687 | // link. Link the visit to the referrer of this request, if any. |
12688 | // Treat referrer as null if there is an error getting it. |
12689 | NS_GetReferrerFromChannel(aChannel, aURI); |
12690 | } |
12691 | } |
12692 | |
12693 | void nsDocShell::SaveLastVisit(nsIChannel* aChannel, nsIURI* aURI, |
12694 | uint32_t aChannelRedirectFlags) { |
12695 | nsCOMPtr<nsIWritablePropertyBag2> props(do_QueryInterface(aChannel)); |
12696 | if (!props || !aURI) { |
12697 | return; |
12698 | } |
12699 | |
12700 | props->SetPropertyAsInterface(u"docshell.previousURI"_ns, aURI); |
12701 | props->SetPropertyAsUint32(u"docshell.previousFlags"_ns, |
12702 | aChannelRedirectFlags); |
12703 | } |
12704 | |
12705 | /* static */ void nsDocShell::InternalAddURIVisit( |
12706 | nsIURI* aURI, nsIURI* aPreviousURI, uint32_t aChannelRedirectFlags, |
12707 | uint32_t aResponseStatus, BrowsingContext* aBrowsingContext, |
12708 | nsIWidget* aWidget, uint32_t aLoadType, bool aWasUpgraded) { |
12709 | MOZ_ASSERT(aURI, "Visited URI is null!")do { static_assert( mozilla::detail::AssertionConditionType< decltype(aURI)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(aURI))), 0))) { do { } while (false ); MOZ_ReportAssertionFailure("aURI" " (" "Visited URI is null!" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 12709 ); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aURI" ") (" "Visited URI is null!" ")"); do { MOZ_CrashSequence(__null, 12709); __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
12710 | MOZ_ASSERT(aLoadType != LOAD_ERROR_PAGE && aLoadType != LOAD_BYPASS_HISTORY,do { static_assert( mozilla::detail::AssertionConditionType< decltype(aLoadType != LOAD_ERROR_PAGE && aLoadType != LOAD_BYPASS_HISTORY)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aLoadType != LOAD_ERROR_PAGE && aLoadType != LOAD_BYPASS_HISTORY))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aLoadType != LOAD_ERROR_PAGE && aLoadType != LOAD_BYPASS_HISTORY" " (" "Do not add error or bypass pages to global history" ")" , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 12711); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadType != LOAD_ERROR_PAGE && aLoadType != LOAD_BYPASS_HISTORY" ") (" "Do not add error or bypass pages to global history" ")" ); do { MOZ_CrashSequence(__null, 12711); __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
12711 | "Do not add error or bypass pages to global history")do { static_assert( mozilla::detail::AssertionConditionType< decltype(aLoadType != LOAD_ERROR_PAGE && aLoadType != LOAD_BYPASS_HISTORY)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aLoadType != LOAD_ERROR_PAGE && aLoadType != LOAD_BYPASS_HISTORY))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aLoadType != LOAD_ERROR_PAGE && aLoadType != LOAD_BYPASS_HISTORY" " (" "Do not add error or bypass pages to global history" ")" , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 12711); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadType != LOAD_ERROR_PAGE && aLoadType != LOAD_BYPASS_HISTORY" ") (" "Do not add error or bypass pages to global history" ")" ); do { MOZ_CrashSequence(__null, 12711); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
12712 | |
12713 | bool usePrivateBrowsing = false; |
12714 | aBrowsingContext->GetUsePrivateBrowsing(&usePrivateBrowsing); |
12715 | |
12716 | // Only content-type docshells save URI visits. Also don't do |
12717 | // anything here if we're not supposed to use global history. |
12718 | if (!aBrowsingContext->IsContent() || |
12719 | !aBrowsingContext->GetUseGlobalHistory() || usePrivateBrowsing) { |
12720 | return; |
12721 | } |
12722 | |
12723 | nsCOMPtr<IHistory> history = components::History::Service(); |
12724 | |
12725 | if (history) { |
12726 | uint32_t visitURIFlags = 0; |
12727 | |
12728 | if (aBrowsingContext->IsTop()) { |
12729 | visitURIFlags |= IHistory::TOP_LEVEL; |
12730 | } |
12731 | |
12732 | if (aChannelRedirectFlags & nsIChannelEventSink::REDIRECT_TEMPORARY) { |
12733 | visitURIFlags |= IHistory::REDIRECT_TEMPORARY; |
12734 | } else if (aChannelRedirectFlags & |
12735 | nsIChannelEventSink::REDIRECT_PERMANENT) { |
12736 | visitURIFlags |= IHistory::REDIRECT_PERMANENT; |
12737 | } else { |
12738 | MOZ_ASSERT(!aChannelRedirectFlags,do { static_assert( mozilla::detail::AssertionConditionType< decltype(!aChannelRedirectFlags)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!aChannelRedirectFlags))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("!aChannelRedirectFlags" " (" "One of REDIRECT_TEMPORARY or REDIRECT_PERMANENT must be set " "if any flags in aChannelRedirectFlags is set." ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 12740); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aChannelRedirectFlags" ") (" "One of REDIRECT_TEMPORARY or REDIRECT_PERMANENT must be set " "if any flags in aChannelRedirectFlags is set." ")"); do { MOZ_CrashSequence (__null, 12740); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false) |
12739 | "One of REDIRECT_TEMPORARY or REDIRECT_PERMANENT must be set "do { static_assert( mozilla::detail::AssertionConditionType< decltype(!aChannelRedirectFlags)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!aChannelRedirectFlags))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("!aChannelRedirectFlags" " (" "One of REDIRECT_TEMPORARY or REDIRECT_PERMANENT must be set " "if any flags in aChannelRedirectFlags is set." ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 12740); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aChannelRedirectFlags" ") (" "One of REDIRECT_TEMPORARY or REDIRECT_PERMANENT must be set " "if any flags in aChannelRedirectFlags is set." ")"); do { MOZ_CrashSequence (__null, 12740); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false) |
12740 | "if any flags in aChannelRedirectFlags is set.")do { static_assert( mozilla::detail::AssertionConditionType< decltype(!aChannelRedirectFlags)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!aChannelRedirectFlags))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("!aChannelRedirectFlags" " (" "One of REDIRECT_TEMPORARY or REDIRECT_PERMANENT must be set " "if any flags in aChannelRedirectFlags is set." ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 12740); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aChannelRedirectFlags" ") (" "One of REDIRECT_TEMPORARY or REDIRECT_PERMANENT must be set " "if any flags in aChannelRedirectFlags is set." ")"); do { MOZ_CrashSequence (__null, 12740); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); |
12741 | } |
12742 | |
12743 | if (aResponseStatus >= 300 && aResponseStatus < 400) { |
12744 | visitURIFlags |= IHistory::REDIRECT_SOURCE; |
12745 | if (aResponseStatus == 301 || aResponseStatus == 308) { |
12746 | visitURIFlags |= IHistory::REDIRECT_SOURCE_PERMANENT; |
12747 | } |
12748 | } |
12749 | // Errors 400-501 and 505 are considered unrecoverable, in the sense a |
12750 | // simple retry attempt by the user is unlikely to solve them. |
12751 | // 408 is special cased, since may actually indicate a temporary |
12752 | // connection problem. |
12753 | else if (aResponseStatus != 408 && |
12754 | ((aResponseStatus >= 400 && aResponseStatus <= 501) || |
12755 | aResponseStatus == 505)) { |
12756 | visitURIFlags |= IHistory::UNRECOVERABLE_ERROR; |
12757 | } |
12758 | |
12759 | if (aWasUpgraded) { |
12760 | visitURIFlags |= |
12761 | IHistory::REDIRECT_SOURCE | IHistory::REDIRECT_SOURCE_UPGRADED; |
12762 | } |
12763 | |
12764 | mozilla::Unused << history->VisitURI(aWidget, aURI, aPreviousURI, |
12765 | visitURIFlags, |
12766 | aBrowsingContext->BrowserId()); |
12767 | } |
12768 | } |
12769 | |
12770 | void nsDocShell::AddURIVisit(nsIURI* aURI, nsIURI* aPreviousURI, |
12771 | uint32_t aChannelRedirectFlags, |
12772 | uint32_t aResponseStatus) { |
12773 | nsPIDOMWindowOuter* outer = GetWindow(); |
12774 | nsCOMPtr<nsIWidget> widget = widget::WidgetUtils::DOMWindowToWidget(outer); |
12775 | |
12776 | InternalAddURIVisit(aURI, aPreviousURI, aChannelRedirectFlags, |
12777 | aResponseStatus, mBrowsingContext, widget, mLoadType, |
12778 | false); |
12779 | } |
12780 | |
12781 | //***************************************************************************** |
12782 | // nsDocShell: Helper Routines |
12783 | //***************************************************************************** |
12784 | |
12785 | NS_IMETHODIMPnsresult |
12786 | nsDocShell::SetLoadType(uint32_t aLoadType) { |
12787 | mLoadType = aLoadType; |
12788 | return NS_OK; |
12789 | } |
12790 | |
12791 | NS_IMETHODIMPnsresult |
12792 | nsDocShell::GetLoadType(uint32_t* aLoadType) { |
12793 | *aLoadType = mLoadType; |
12794 | return NS_OK; |
12795 | } |
12796 | |
12797 | nsresult nsDocShell::ConfirmRepost(bool* aRepost) { |
12798 | if (StaticPrefs::dom_confirm_repost_testing_always_accept()) { |
12799 | *aRepost = true; |
12800 | return NS_OK; |
12801 | } |
12802 | |
12803 | nsCOMPtr<nsIPromptCollection> prompter = |
12804 | do_GetService("@mozilla.org/embedcomp/prompt-collection;1"); |
12805 | if (!prompter) { |
12806 | return NS_ERROR_NOT_AVAILABLE; |
12807 | } |
12808 | |
12809 | return prompter->ConfirmRepost(mBrowsingContext, aRepost); |
12810 | } |
12811 | |
12812 | nsresult nsDocShell::GetPromptAndStringBundle(nsIPrompt** aPrompt, |
12813 | nsIStringBundle** aStringBundle) { |
12814 | NS_ENSURE_SUCCESS(GetInterface(NS_GET_IID(nsIPrompt), (void**)aPrompt),do { nsresult __rv = GetInterface((nsIPrompt::kIID), (void**) aPrompt); if (((bool)(__builtin_expect(!!(NS_FAILED_impl(__rv )), 0)))) { const char* name = mozilla::GetStaticErrorName(__rv ); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "GetInterface((nsIPrompt::kIID), (void**)aPrompt)" , "NS_ERROR_FAILURE", static_cast<uint32_t>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""); NS_DebugBreak (NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 12815); return NS_ERROR_FAILURE; } } while (false) |
12815 | NS_ERROR_FAILURE)do { nsresult __rv = GetInterface((nsIPrompt::kIID), (void**) aPrompt); if (((bool)(__builtin_expect(!!(NS_FAILED_impl(__rv )), 0)))) { const char* name = mozilla::GetStaticErrorName(__rv ); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "GetInterface((nsIPrompt::kIID), (void**)aPrompt)" , "NS_ERROR_FAILURE", static_cast<uint32_t>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""); NS_DebugBreak (NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 12815); return NS_ERROR_FAILURE; } } while (false); |
12816 | |
12817 | nsCOMPtr<nsIStringBundleService> stringBundleService = |
12818 | mozilla::components::StringBundle::Service(); |
12819 | NS_ENSURE_TRUE(stringBundleService, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(stringBundleService)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "stringBundleService" ") failed", nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 12819); return NS_ERROR_FAILURE; } } while (false); |
12820 | |
12821 | NS_ENSURE_SUCCESS(do { nsresult __rv = stringBundleService->CreateBundle(kAppstringsBundleURL , aStringBundle); if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "stringBundleService->CreateBundle(kAppstringsBundleURL, aStringBundle)" , "NS_ERROR_FAILURE", static_cast<uint32_t>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""); NS_DebugBreak (NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 12823); return NS_ERROR_FAILURE; } } while (false) |
12822 | stringBundleService->CreateBundle(kAppstringsBundleURL, aStringBundle),do { nsresult __rv = stringBundleService->CreateBundle(kAppstringsBundleURL , aStringBundle); if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "stringBundleService->CreateBundle(kAppstringsBundleURL, aStringBundle)" , "NS_ERROR_FAILURE", static_cast<uint32_t>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""); NS_DebugBreak (NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 12823); return NS_ERROR_FAILURE; } } while (false) |
12823 | NS_ERROR_FAILURE)do { nsresult __rv = stringBundleService->CreateBundle(kAppstringsBundleURL , aStringBundle); if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "stringBundleService->CreateBundle(kAppstringsBundleURL, aStringBundle)" , "NS_ERROR_FAILURE", static_cast<uint32_t>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""); NS_DebugBreak (NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 12823); return NS_ERROR_FAILURE; } } while (false); |
12824 | |
12825 | return NS_OK; |
12826 | } |
12827 | |
12828 | ScrollContainerFrame* nsDocShell::GetRootScrollContainerFrame() { |
12829 | PresShell* presShell = GetPresShell(); |
12830 | NS_ENSURE_TRUE(presShell, nullptr)do { if ((__builtin_expect(!!(!(presShell)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "presShell" ") failed", nullptr , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 12830); return nullptr; } } while (false); |
12831 | |
12832 | return presShell->GetRootScrollContainerFrame(); |
12833 | } |
12834 | |
12835 | nsresult nsDocShell::EnsureScriptEnvironment() { |
12836 | if (mScriptGlobal) { |
12837 | return NS_OK; |
12838 | } |
12839 | |
12840 | if (mIsBeingDestroyed) { |
12841 | return NS_ERROR_NOT_AVAILABLE; |
12842 | } |
12843 | |
12844 | #ifdef DEBUG1 |
12845 | NS_ASSERTION(!mInEnsureScriptEnv,do { if (!(!mInEnsureScriptEnv)) { NS_DebugBreak(NS_DEBUG_ASSERTION , "Infinite loop! Calling EnsureScriptEnvironment() from " "within EnsureScriptEnvironment()!" , "!mInEnsureScriptEnv", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 12847); MOZ_PretendNoReturn(); } } while (0) |
12846 | "Infinite loop! Calling EnsureScriptEnvironment() from "do { if (!(!mInEnsureScriptEnv)) { NS_DebugBreak(NS_DEBUG_ASSERTION , "Infinite loop! Calling EnsureScriptEnvironment() from " "within EnsureScriptEnvironment()!" , "!mInEnsureScriptEnv", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 12847); MOZ_PretendNoReturn(); } } while (0) |
12847 | "within EnsureScriptEnvironment()!")do { if (!(!mInEnsureScriptEnv)) { NS_DebugBreak(NS_DEBUG_ASSERTION , "Infinite loop! Calling EnsureScriptEnvironment() from " "within EnsureScriptEnvironment()!" , "!mInEnsureScriptEnv", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 12847); MOZ_PretendNoReturn(); } } while (0); |
12848 | |
12849 | // Yeah, this isn't re-entrant safe, but that's ok since if we |
12850 | // re-enter this method, we'll infinitely loop... |
12851 | AutoRestore<bool> boolSetter(mInEnsureScriptEnv); |
12852 | mInEnsureScriptEnv = true; |
12853 | #endif |
12854 | |
12855 | nsCOMPtr<nsIWebBrowserChrome> browserChrome(do_GetInterface(mTreeOwner)); |
12856 | NS_ENSURE_TRUE(browserChrome, NS_ERROR_NOT_AVAILABLE)do { if ((__builtin_expect(!!(!(browserChrome)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "browserChrome" ") failed" , nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 12856); return NS_ERROR_NOT_AVAILABLE; } } while (false); |
12857 | |
12858 | uint32_t chromeFlags; |
12859 | browserChrome->GetChromeFlags(&chromeFlags); |
12860 | |
12861 | // If our window is modal and we're not opened as chrome, make |
12862 | // this window a modal content window. |
12863 | mScriptGlobal = nsGlobalWindowOuter::Create(this, mItemType == typeChrome); |
12864 | MOZ_ASSERT(mScriptGlobal)do { static_assert( mozilla::detail::AssertionConditionType< decltype(mScriptGlobal)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mScriptGlobal))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mScriptGlobal", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 12864); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "mScriptGlobal" ")"); do { MOZ_CrashSequence (__null, 12864); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); |
12865 | |
12866 | // Ensure the script object is set up to run script. |
12867 | return mScriptGlobal->EnsureScriptEnvironment(); |
12868 | } |
12869 | |
12870 | nsresult nsDocShell::EnsureEditorData() { |
12871 | MOZ_ASSERT(!mIsBeingDestroyed)do { static_assert( mozilla::detail::AssertionConditionType< decltype(!mIsBeingDestroyed)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!mIsBeingDestroyed))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!mIsBeingDestroyed" , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 12871); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mIsBeingDestroyed" ")"); do { MOZ_CrashSequence(__null, 12871); __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
12872 | |
12873 | bool openDocHasDetachedEditor = mOSHE && mOSHE->HasDetachedEditor(); |
12874 | if (!mEditorData && !mIsBeingDestroyed && !openDocHasDetachedEditor) { |
12875 | // We shouldn't recreate the editor data if it already exists, or |
12876 | // we're shutting down, or we already have a detached editor data |
12877 | // stored in the session history. We should only have one editordata |
12878 | // per docshell. |
12879 | mEditorData = MakeUnique<nsDocShellEditorData>(this); |
12880 | } |
12881 | |
12882 | return mEditorData ? NS_OK : NS_ERROR_NOT_AVAILABLE; |
12883 | } |
12884 | |
12885 | nsresult nsDocShell::EnsureFind() { |
12886 | if (!mFind) { |
12887 | mFind = new nsWebBrowserFind(); |
12888 | } |
12889 | |
12890 | // we promise that the nsIWebBrowserFind that we return has been set |
12891 | // up to point to the focused, or content window, so we have to |
12892 | // set that up each time. |
12893 | |
12894 | nsIScriptGlobalObject* scriptGO = GetScriptGlobalObject(); |
12895 | NS_ENSURE_TRUE(scriptGO, NS_ERROR_UNEXPECTED)do { if ((__builtin_expect(!!(!(scriptGO)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "scriptGO" ") failed", nullptr , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 12895); return NS_ERROR_UNEXPECTED; } } while (false); |
12896 | |
12897 | // default to our window |
12898 | nsCOMPtr<nsPIDOMWindowOuter> ourWindow = do_QueryInterface(scriptGO); |
12899 | nsCOMPtr<nsPIDOMWindowOuter> windowToSearch; |
12900 | nsFocusManager::GetFocusedDescendant(ourWindow, |
12901 | nsFocusManager::eIncludeAllDescendants, |
12902 | getter_AddRefs(windowToSearch)); |
12903 | |
12904 | nsCOMPtr<nsIWebBrowserFindInFrames> findInFrames = do_QueryInterface(mFind); |
12905 | if (!findInFrames) { |
12906 | return NS_ERROR_NO_INTERFACE; |
12907 | } |
12908 | |
12909 | nsresult rv = findInFrames->SetRootSearchFrame(ourWindow); |
12910 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
12911 | return rv; |
12912 | } |
12913 | rv = findInFrames->SetCurrentSearchFrame(windowToSearch); |
12914 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
12915 | return rv; |
12916 | } |
12917 | |
12918 | return NS_OK; |
12919 | } |
12920 | |
12921 | NS_IMETHODIMPnsresult |
12922 | nsDocShell::IsBeingDestroyed(bool* aDoomed) { |
12923 | NS_ENSURE_ARG(aDoomed)do { if ((__builtin_expect(!!(!(aDoomed)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aDoomed" ") failed", nullptr , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 12923); return NS_ERROR_INVALID_ARG; } } while (false); |
12924 | *aDoomed = mIsBeingDestroyed; |
12925 | return NS_OK; |
12926 | } |
12927 | |
12928 | NS_IMETHODIMPnsresult |
12929 | nsDocShell::GetIsExecutingOnLoadHandler(bool* aResult) { |
12930 | NS_ENSURE_ARG(aResult)do { if ((__builtin_expect(!!(!(aResult)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aResult" ") failed", nullptr , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 12930); return NS_ERROR_INVALID_ARG; } } while (false); |
12931 | *aResult = mIsExecutingOnLoadHandler; |
12932 | return NS_OK; |
12933 | } |
12934 | |
12935 | NS_IMETHODIMPnsresult |
12936 | nsDocShell::GetLayoutHistoryState(nsILayoutHistoryState** aLayoutHistoryState) { |
12937 | nsCOMPtr<nsILayoutHistoryState> state; |
12938 | if (mozilla::SessionHistoryInParent()) { |
12939 | if (mActiveEntry) { |
12940 | state = mActiveEntry->GetLayoutHistoryState(); |
12941 | } |
12942 | } else { |
12943 | if (mOSHE) { |
12944 | state = mOSHE->GetLayoutHistoryState(); |
12945 | } |
12946 | } |
12947 | state.forget(aLayoutHistoryState); |
12948 | return NS_OK; |
12949 | } |
12950 | |
12951 | NS_IMETHODIMPnsresult |
12952 | nsDocShell::SetLayoutHistoryState(nsILayoutHistoryState* aLayoutHistoryState) { |
12953 | if (mOSHE) { |
12954 | mOSHE->SetLayoutHistoryState(aLayoutHistoryState); |
12955 | } |
12956 | if (mActiveEntry) { |
12957 | mActiveEntry->SetLayoutHistoryState(aLayoutHistoryState); |
12958 | } |
12959 | return NS_OK; |
12960 | } |
12961 | |
12962 | nsDocShell::InterfaceRequestorProxy::InterfaceRequestorProxy( |
12963 | nsIInterfaceRequestor* aRequestor) { |
12964 | if (aRequestor) { |
12965 | mWeakPtr = do_GetWeakReference(aRequestor); |
12966 | } |
12967 | } |
12968 | |
12969 | nsDocShell::InterfaceRequestorProxy::~InterfaceRequestorProxy() { |
12970 | mWeakPtr = nullptr; |
12971 | } |
12972 | |
12973 | NS_IMPL_ISUPPORTS(nsDocShell::InterfaceRequestorProxy, nsIInterfaceRequestor)MozExternalRefCountType nsDocShell::InterfaceRequestorProxy:: AddRef(void) { static_assert(!std::is_destructible_v<nsDocShell ::InterfaceRequestorProxy>, "Reference-counted class " "nsDocShell::InterfaceRequestorProxy" " should not have a public destructor. " "Make this class's destructor non-public" ); do { static_assert( mozilla::detail::AssertionConditionType <decltype(int32_t(mRefCnt) >= 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0" " (" "illegal refcnt" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 12973); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0" ") (" "illegal refcnt" ")"); do { MOZ_CrashSequence(__null, 12973 ); __attribute__((nomerge)) ::abort(); } while (false); } } while (false); do { static_assert( mozilla::detail::AssertionConditionType <decltype("nsDocShell::InterfaceRequestorProxy" != nullptr )>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!("nsDocShell::InterfaceRequestorProxy" != nullptr))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("\"nsDocShell::InterfaceRequestorProxy\" != nullptr" " (" "Must specify a name" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 12973); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsDocShell::InterfaceRequestorProxy\" != nullptr" ") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null , 12973); __attribute__((nomerge)) ::abort(); } while (false) ; } } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread .AssertOwnership("nsDocShell::InterfaceRequestorProxy" " not thread-safe" ); nsrefcnt count = ++mRefCnt; NS_LogAddRef((this), (count), ( "nsDocShell::InterfaceRequestorProxy"), (uint32_t)(sizeof(*this ))); return count; } MozExternalRefCountType nsDocShell::InterfaceRequestorProxy ::Release(void) { do { static_assert( mozilla::detail::AssertionConditionType <decltype(int32_t(mRefCnt) > 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) > 0))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0" " (" "dup release" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 12973); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0" ") (" "dup release" ")"); do { MOZ_CrashSequence(__null, 12973 ); __attribute__((nomerge)) ::abort(); } while (false); } } while (false); do { static_assert( mozilla::detail::AssertionConditionType <decltype("nsDocShell::InterfaceRequestorProxy" != nullptr )>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!("nsDocShell::InterfaceRequestorProxy" != nullptr))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("\"nsDocShell::InterfaceRequestorProxy\" != nullptr" " (" "Must specify a name" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 12973); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsDocShell::InterfaceRequestorProxy\" != nullptr" ") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null , 12973); __attribute__((nomerge)) ::abort(); } while (false) ; } } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread .AssertOwnership("nsDocShell::InterfaceRequestorProxy" " not thread-safe" ); const char* const nametmp = "nsDocShell::InterfaceRequestorProxy" ; nsrefcnt count = --mRefCnt; NS_LogRelease((this), (count), ( nametmp)); if (count == 0) { mRefCnt = 1; delete (this); return 0; } return count; } nsresult nsDocShell::InterfaceRequestorProxy ::QueryInterface(const nsIID& aIID, void** aInstancePtr) { do { if (!(aInstancePtr)) { NS_DebugBreak(NS_DEBUG_ASSERTION , "QueryInterface requires a non-NULL destination!", "aInstancePtr" , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 12973); MOZ_PretendNoReturn(); } } while (0); nsresult rv = NS_ERROR_FAILURE ; static_assert(1 > 0, "Need more arguments to NS_INTERFACE_TABLE" ); static const QITableEntry table[] = { {&mozilla::detail ::kImplementedIID<nsDocShell::InterfaceRequestorProxy, nsIInterfaceRequestor >, int32_t( reinterpret_cast<char*>(static_cast<nsIInterfaceRequestor *>((nsDocShell::InterfaceRequestorProxy*)0x1000)) - reinterpret_cast <char*>((nsDocShell::InterfaceRequestorProxy*)0x1000))} , {&mozilla::detail::kImplementedIID<nsDocShell::InterfaceRequestorProxy , nsISupports>, int32_t(reinterpret_cast<char*>(static_cast <nsISupports*>( static_cast<nsIInterfaceRequestor*> ((nsDocShell::InterfaceRequestorProxy*)0x1000))) - reinterpret_cast <char*>((nsDocShell::InterfaceRequestorProxy*)0x1000))} , { nullptr, 0 } } ; static_assert(std::size(table) > 1, "need at least 1 interface" ); rv = NS_TableDrivenQI(static_cast<void*>(this), aIID , aInstancePtr, table); return rv; } |
12974 | |
12975 | NS_IMETHODIMPnsresult |
12976 | nsDocShell::InterfaceRequestorProxy::GetInterface(const nsIID& aIID, |
12977 | void** aSink) { |
12978 | NS_ENSURE_ARG_POINTER(aSink)do { if ((__builtin_expect(!!(!(aSink)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aSink" ") failed", nullptr , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 12978); return NS_ERROR_INVALID_POINTER; } } while (false); |
12979 | nsCOMPtr<nsIInterfaceRequestor> ifReq = do_QueryReferent(mWeakPtr); |
12980 | if (ifReq) { |
12981 | return ifReq->GetInterface(aIID, aSink); |
12982 | } |
12983 | *aSink = nullptr; |
12984 | return NS_NOINTERFACE; |
12985 | } |
12986 | |
12987 | //***************************************************************************** |
12988 | // nsDocShell::nsIAuthPromptProvider |
12989 | //***************************************************************************** |
12990 | |
12991 | NS_IMETHODIMPnsresult |
12992 | nsDocShell::GetAuthPrompt(uint32_t aPromptReason, const nsIID& aIID, |
12993 | void** aResult) { |
12994 | // a priority prompt request will override a false mAllowAuth setting |
12995 | bool priorityPrompt = (aPromptReason == PROMPT_PROXY); |
12996 | |
12997 | if (!mAllowAuth && !priorityPrompt) { |
12998 | return NS_ERROR_NOT_AVAILABLE; |
12999 | } |
13000 | |
13001 | // we're either allowing auth, or it's a proxy request |
13002 | nsresult rv; |
13003 | nsCOMPtr<nsIPromptFactory> wwatch = |
13004 | do_GetService(NS_WINDOWWATCHER_CONTRACTID"@mozilla.org/embedcomp/window-watcher;1", &rv); |
13005 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 13005); return rv; } } while (false); |
13006 | |
13007 | rv = EnsureScriptEnvironment(); |
13008 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 13008); return rv; } } while (false); |
13009 | |
13010 | // Get the an auth prompter for our window so that the parenting |
13011 | // of the dialogs works as it should when using tabs. |
13012 | |
13013 | return wwatch->GetPrompt(mScriptGlobal, aIID, |
13014 | reinterpret_cast<void**>(aResult)); |
13015 | } |
13016 | |
13017 | //***************************************************************************** |
13018 | // nsDocShell::nsILoadContext |
13019 | //***************************************************************************** |
13020 | |
13021 | NS_IMETHODIMPnsresult |
13022 | nsDocShell::GetAssociatedWindow(mozIDOMWindowProxy** aWindow) { |
13023 | CallGetInterface(this, aWindow); |
13024 | return NS_OK; |
13025 | } |
13026 | |
13027 | NS_IMETHODIMPnsresult |
13028 | nsDocShell::GetTopWindow(mozIDOMWindowProxy** aWindow) { |
13029 | return mBrowsingContext->GetTopWindow(aWindow); |
13030 | } |
13031 | |
13032 | NS_IMETHODIMPnsresult |
13033 | nsDocShell::GetTopFrameElement(Element** aElement) { |
13034 | return mBrowsingContext->GetTopFrameElement(aElement); |
13035 | } |
13036 | |
13037 | NS_IMETHODIMPnsresult |
13038 | nsDocShell::GetUseTrackingProtection(bool* aUseTrackingProtection) { |
13039 | return mBrowsingContext->GetUseTrackingProtection(aUseTrackingProtection); |
13040 | } |
13041 | |
13042 | NS_IMETHODIMPnsresult |
13043 | nsDocShell::SetUseTrackingProtection(bool aUseTrackingProtection) { |
13044 | return mBrowsingContext->SetUseTrackingProtection(aUseTrackingProtection); |
13045 | } |
13046 | |
13047 | NS_IMETHODIMPnsresult |
13048 | nsDocShell::GetIsContent(bool* aIsContent) { |
13049 | *aIsContent = (mItemType == typeContent); |
13050 | return NS_OK; |
13051 | } |
13052 | |
13053 | bool nsDocShell::IsOKToLoadURI(nsIURI* aURI) { |
13054 | MOZ_ASSERT(aURI, "Must have a URI!")do { static_assert( mozilla::detail::AssertionConditionType< decltype(aURI)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(aURI))), 0))) { do { } while (false ); MOZ_ReportAssertionFailure("aURI" " (" "Must have a URI!" ")" , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 13054); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aURI" ") (" "Must have a URI!" ")"); do { MOZ_CrashSequence(__null, 13054); __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
13055 | |
13056 | if (!mFiredUnloadEvent) { |
13057 | return true; |
13058 | } |
13059 | |
13060 | if (!mLoadingURI) { |
13061 | return false; |
13062 | } |
13063 | |
13064 | bool isPrivateWin = false; |
13065 | Document* doc = GetDocument(); |
13066 | if (doc) { |
13067 | isPrivateWin = |
13068 | doc->NodePrincipal()->OriginAttributesRef().IsPrivateBrowsing(); |
13069 | } |
13070 | |
13071 | nsCOMPtr<nsIScriptSecurityManager> secMan = |
13072 | do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID"@mozilla.org/scriptsecuritymanager;1"); |
13073 | return secMan && NS_SUCCEEDED(secMan->CheckSameOriginURI(((bool)(__builtin_expect(!!(!NS_FAILED_impl(secMan->CheckSameOriginURI ( aURI, mLoadingURI, false, isPrivateWin))), 1))) |
13074 | aURI, mLoadingURI, false, isPrivateWin))((bool)(__builtin_expect(!!(!NS_FAILED_impl(secMan->CheckSameOriginURI ( aURI, mLoadingURI, false, isPrivateWin))), 1))); |
13075 | } |
13076 | |
13077 | // |
13078 | // Routines for selection and clipboard |
13079 | // |
13080 | nsresult nsDocShell::GetControllerForCommand(const char* aCommand, |
13081 | nsIController** aResult) { |
13082 | NS_ENSURE_ARG_POINTER(aResult)do { if ((__builtin_expect(!!(!(aResult)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aResult" ") failed", nullptr , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 13082); return NS_ERROR_INVALID_POINTER; } } while (false); |
13083 | *aResult = nullptr; |
13084 | |
13085 | NS_ENSURE_TRUE(mScriptGlobal, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(mScriptGlobal)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "mScriptGlobal" ") failed" , nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 13085); return NS_ERROR_FAILURE; } } while (false); |
13086 | |
13087 | nsCOMPtr<nsPIWindowRoot> root = mScriptGlobal->GetTopWindowRoot(); |
13088 | NS_ENSURE_TRUE(root, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(root)), 0))) { NS_DebugBreak( NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "root" ") failed", nullptr , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 13088); return NS_ERROR_FAILURE; } } while (false); |
13089 | |
13090 | return root->GetControllerForCommand(aCommand, false /* for any window */, |
13091 | aResult); |
13092 | } |
13093 | |
13094 | NS_IMETHODIMPnsresult |
13095 | nsDocShell::IsCommandEnabled(const char* aCommand, bool* aResult) { |
13096 | NS_ENSURE_ARG_POINTER(aResult)do { if ((__builtin_expect(!!(!(aResult)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aResult" ") failed", nullptr , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 13096); return NS_ERROR_INVALID_POINTER; } } while (false); |
13097 | *aResult = false; |
13098 | |
13099 | nsresult rv = NS_ERROR_FAILURE; |
13100 | |
13101 | nsCOMPtr<nsIController> controller; |
13102 | rv = GetControllerForCommand(aCommand, getter_AddRefs(controller)); |
13103 | if (controller) { |
13104 | rv = controller->IsCommandEnabled(aCommand, aResult); |
13105 | } |
13106 | |
13107 | return rv; |
13108 | } |
13109 | |
13110 | NS_IMETHODIMPnsresult |
13111 | nsDocShell::DoCommand(const char* aCommand) { |
13112 | nsresult rv = NS_ERROR_FAILURE; |
13113 | |
13114 | nsCOMPtr<nsIController> controller; |
13115 | rv = GetControllerForCommand(aCommand, getter_AddRefs(controller)); |
13116 | if (controller) { |
13117 | rv = controller->DoCommand(aCommand); |
13118 | } |
13119 | |
13120 | return rv; |
13121 | } |
13122 | |
13123 | NS_IMETHODIMPnsresult |
13124 | nsDocShell::DoCommandWithParams(const char* aCommand, |
13125 | nsICommandParams* aParams) { |
13126 | nsCOMPtr<nsIController> controller; |
13127 | nsresult rv = GetControllerForCommand(aCommand, getter_AddRefs(controller)); |
13128 | if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv )), 0))), "NS_FAILED(rv)", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 13128)) { |
13129 | return rv; |
13130 | } |
13131 | |
13132 | nsCOMPtr<nsICommandController> commandController = |
13133 | do_QueryInterface(controller, &rv); |
13134 | if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv )), 0))), "NS_FAILED(rv)", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 13134)) { |
13135 | return rv; |
13136 | } |
13137 | |
13138 | return commandController->DoCommandWithParams(aCommand, aParams); |
13139 | } |
13140 | |
13141 | nsresult nsDocShell::EnsureCommandHandler() { |
13142 | if (!mCommandManager) { |
13143 | if (nsCOMPtr<nsPIDOMWindowOuter> domWindow = GetWindow()) { |
13144 | mCommandManager = new nsCommandManager(domWindow); |
13145 | } |
13146 | } |
13147 | return mCommandManager ? NS_OK : NS_ERROR_FAILURE; |
13148 | } |
13149 | |
13150 | // link handling |
13151 | |
13152 | class OnLinkClickEvent : public Runnable { |
13153 | public: |
13154 | OnLinkClickEvent(nsDocShell* aHandler, nsIContent* aContent, |
13155 | nsDocShellLoadState* aLoadState, bool aNoOpenerImplied, |
13156 | nsIPrincipal* aTriggeringPrincipal); |
13157 | |
13158 | NS_IMETHODvirtual nsresult Run() override { |
13159 | // We need to set up an AutoJSAPI here for the following reason: When we |
13160 | // do OnLinkClickSync we'll eventually end up in |
13161 | // nsGlobalWindow::OpenInternal which only does popup blocking if |
13162 | // !LegacyIsCallerChromeOrNativeCode(). So we need to fake things so that |
13163 | // we don't look like native code as far as LegacyIsCallerNativeCode() is |
13164 | // concerned. (Bug 1930445) |
13165 | AutoJSAPI jsapi; |
13166 | if (jsapi.Init(mContent->OwnerDoc()->GetScopeObject())) { |
13167 | mHandler->OnLinkClickSync(mContent, mLoadState, mNoOpenerImplied, |
13168 | mTriggeringPrincipal); |
13169 | } |
13170 | return NS_OK; |
13171 | } |
13172 | |
13173 | private: |
13174 | RefPtr<nsDocShell> mHandler; |
13175 | nsCOMPtr<nsIContent> mContent; |
13176 | RefPtr<nsDocShellLoadState> mLoadState; |
13177 | nsCOMPtr<nsIPrincipal> mTriggeringPrincipal; |
13178 | bool mNoOpenerImplied; |
13179 | }; |
13180 | |
13181 | OnLinkClickEvent::OnLinkClickEvent(nsDocShell* aHandler, nsIContent* aContent, |
13182 | nsDocShellLoadState* aLoadState, |
13183 | bool aNoOpenerImplied, |
13184 | nsIPrincipal* aTriggeringPrincipal) |
13185 | : mozilla::Runnable("OnLinkClickEvent"), |
13186 | mHandler(aHandler), |
13187 | mContent(aContent), |
13188 | mLoadState(aLoadState), |
13189 | mTriggeringPrincipal(aTriggeringPrincipal), |
13190 | mNoOpenerImplied(aNoOpenerImplied) {} |
13191 | |
13192 | nsresult nsDocShell::OnLinkClick( |
13193 | nsIContent* aContent, nsIURI* aURI, const nsAString& aTargetSpec, |
13194 | const nsAString& aFileName, nsIInputStream* aPostDataStream, |
13195 | nsIInputStream* aHeadersDataStream, bool aIsUserTriggered, |
13196 | UserNavigationInvolvement aUserInvolvement, |
13197 | nsIPrincipal* aTriggeringPrincipal, nsIContentSecurityPolicy* aCsp) { |
13198 | #ifndef ANDROID |
13199 | MOZ_ASSERT(aTriggeringPrincipal, "Need a valid triggeringPrincipal")do { static_assert( mozilla::detail::AssertionConditionType< decltype(aTriggeringPrincipal)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aTriggeringPrincipal))), 0)) ) { do { } while (false); MOZ_ReportAssertionFailure("aTriggeringPrincipal" " (" "Need a valid triggeringPrincipal" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 13199); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aTriggeringPrincipal" ") (" "Need a valid triggeringPrincipal" ")"); do { MOZ_CrashSequence (__null, 13199); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); |
13200 | #endif |
13201 | NS_ASSERTION(NS_IsMainThread(), "wrong thread")do { if (!(NS_IsMainThread())) { NS_DebugBreak(NS_DEBUG_ASSERTION , "wrong thread", "NS_IsMainThread()", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 13201); MOZ_PretendNoReturn(); } } while (0); |
13202 | |
13203 | if (!IsNavigationAllowed() || !IsOKToLoadURI(aURI)) { |
13204 | return NS_OK; |
13205 | } |
13206 | |
13207 | // On history navigation through Back/Forward buttons, don't execute |
13208 | // automatic JavaScript redirection such as |anchorElement.click()| or |
13209 | // |formElement.submit()|. |
13210 | // |
13211 | // XXX |formElement.submit()| bypasses this checkpoint because it calls |
13212 | // nsDocShell::OnLinkClickSync(...) instead. |
13213 | if (ShouldBlockLoadingForBackButton()) { |
13214 | return NS_OK; |
13215 | } |
13216 | |
13217 | if (aContent->IsEditable()) { |
13218 | return NS_OK; |
13219 | } |
13220 | |
13221 | Document* ownerDoc = aContent->OwnerDoc(); |
13222 | if (nsContentUtils::IsExternalProtocol(aURI)) { |
13223 | ownerDoc->EnsureNotEnteringAndExitFullscreen(); |
13224 | } |
13225 | |
13226 | bool noOpenerImplied = false; |
13227 | nsAutoString target(aTargetSpec); |
13228 | if (aFileName.IsVoid() && |
13229 | ShouldOpenInBlankTarget(aTargetSpec, aURI, aContent, aIsUserTriggered)) { |
13230 | target = u"_blank"; |
13231 | if (!aTargetSpec.Equals(target)) { |
13232 | noOpenerImplied = true; |
13233 | } |
13234 | } |
13235 | |
13236 | // https://html.spec.whatwg.org/#downloading-hyperlinks |
13237 | // Step 6, step 6.1, step 6.2 |
13238 | // aFileName not being void implies a download attribute, since we've already |
13239 | // checked if the attribute is present in `nsContentUtils::TriggerLinkClick` |
13240 | // and made it void otherwise. |
13241 | if (!aFileName.IsVoid() && |
13242 | aUserInvolvement != UserNavigationInvolvement::BrowserUI) { |
13243 | if (nsCOMPtr<nsPIDOMWindowInner> window = ownerDoc->GetInnerWindow()) { |
13244 | if (RefPtr<Navigation> navigation = window->Navigation()) { |
13245 | AutoJSAPI jsapi; |
13246 | if (jsapi.Init(window)) { |
13247 | RefPtr element = aContent->AsElement(); |
13248 | // Step 6.4 |
13249 | bool shouldContinue = navigation->FireDownloadRequestNavigateEvent( |
13250 | jsapi.cx(), aURI, aUserInvolvement, element, aFileName); |
13251 | |
13252 | // Step 6.5 |
13253 | if (!shouldContinue) { |
13254 | return NS_OK; |
13255 | } |
13256 | } |
13257 | } |
13258 | } |
13259 | } |
13260 | |
13261 | RefPtr<nsDocShellLoadState> loadState = new nsDocShellLoadState(aURI); |
13262 | loadState->SetTarget(target); |
13263 | loadState->SetFileName(aFileName); |
13264 | loadState->SetPostDataStream(aPostDataStream); |
13265 | loadState->SetHeadersStream(aHeadersDataStream); |
13266 | loadState->SetFirstParty(true); |
13267 | loadState->SetTriggeringPrincipal( |
13268 | aTriggeringPrincipal ? aTriggeringPrincipal : aContent->NodePrincipal()); |
13269 | loadState->SetPrincipalToInherit(aContent->NodePrincipal()); |
13270 | loadState->SetCsp(aCsp ? aCsp : aContent->GetCsp()); |
13271 | loadState->SetAllowFocusMove(UserActivation::IsHandlingUserInput()); |
13272 | |
13273 | const bool hasValidUserGestureActivation = |
13274 | ownerDoc->HasValidTransientUserGestureActivation(); |
13275 | loadState->SetHasValidUserGestureActivation(hasValidUserGestureActivation); |
13276 | loadState->SetTextDirectiveUserActivation( |
13277 | ownerDoc->ConsumeTextDirectiveUserActivation() || |
13278 | hasValidUserGestureActivation); |
13279 | loadState->SetUserNavigationInvolvement(aUserInvolvement); |
13280 | loadState->SetTriggeringClassificationFlags( |
13281 | ownerDoc->GetScriptTrackingFlags()); |
13282 | |
13283 | nsCOMPtr<nsIRunnable> ev = new OnLinkClickEvent( |
13284 | this, aContent, loadState, noOpenerImplied, aTriggeringPrincipal); |
13285 | return Dispatch(ev.forget()); |
13286 | } |
13287 | |
13288 | bool nsDocShell::ShouldOpenInBlankTarget(const nsAString& aOriginalTarget, |
13289 | nsIURI* aLinkURI, nsIContent* aContent, |
13290 | bool aIsUserTriggered) { |
13291 | if (aLinkURI->SchemeIs("javascript")) { |
13292 | return false; |
13293 | } |
13294 | |
13295 | // External links from within app tabs should always open in new tabs |
13296 | // instead of replacing the app tab's page (Bug 575561) |
13297 | // nsIURI.host can throw for non-nsStandardURL nsIURIs. If we fail to |
13298 | // get either host, just return false to use the original target. |
13299 | nsAutoCString linkHost; |
13300 | if (NS_FAILED(aLinkURI->GetHost(linkHost))((bool)(__builtin_expect(!!(NS_FAILED_impl(aLinkURI->GetHost (linkHost))), 0)))) { |
13301 | return false; |
13302 | } |
13303 | |
13304 | // The targetTopLevelLinkClicksToBlank property on BrowsingContext allows |
13305 | // privileged code to change the default targeting behaviour. In particular, |
13306 | // if a user-initiated link click for the (or targetting the) top-level frame |
13307 | // is detected, we default the target to "_blank" to give it a new |
13308 | // top-level BrowsingContext. |
13309 | if (mBrowsingContext->TargetTopLevelLinkClicksToBlank() && aIsUserTriggered && |
13310 | ((aOriginalTarget.IsEmpty() && mBrowsingContext->IsTop()) || |
13311 | aOriginalTarget == u"_top"_ns)) { |
13312 | return true; |
13313 | } |
13314 | |
13315 | // Don't modify non-default targets. |
13316 | if (!aOriginalTarget.IsEmpty()) { |
13317 | return false; |
13318 | } |
13319 | |
13320 | // Only check targets that are in extension panels or app tabs. |
13321 | // (isAppTab will be false for app tab subframes). |
13322 | nsString mmGroup = mBrowsingContext->Top()->GetMessageManagerGroup(); |
13323 | if (!mmGroup.EqualsLiteral("webext-browsers") && |
13324 | !mBrowsingContext->IsAppTab()) { |
13325 | return false; |
13326 | } |
13327 | |
13328 | nsCOMPtr<nsIURI> docURI = aContent->OwnerDoc()->GetDocumentURIObject(); |
13329 | if (!docURI) { |
13330 | return false; |
13331 | } |
13332 | |
13333 | nsAutoCString docHost; |
13334 | if (NS_FAILED(docURI->GetHost(docHost))((bool)(__builtin_expect(!!(NS_FAILED_impl(docURI->GetHost (docHost))), 0)))) { |
13335 | return false; |
13336 | } |
13337 | |
13338 | if (linkHost.Equals(docHost)) { |
13339 | return false; |
13340 | } |
13341 | |
13342 | // Special case: ignore "www" prefix if it is part of host string |
13343 | return linkHost.Length() < docHost.Length() |
13344 | ? !docHost.Equals("www."_ns + linkHost) |
13345 | : !linkHost.Equals("www."_ns + docHost); |
13346 | } |
13347 | |
13348 | static bool ElementCanHaveNoopener(nsIContent* aContent) { |
13349 | // Make sure we are dealing with either an <A>, <AREA>, or <FORM> element in |
13350 | // the HTML, XHTML, or SVG namespace. |
13351 | return aContent->IsAnyOfHTMLElements(nsGkAtoms::a, nsGkAtoms::area, |
13352 | nsGkAtoms::form) || |
13353 | aContent->IsSVGElement(nsGkAtoms::a); |
13354 | } |
13355 | |
13356 | nsresult nsDocShell::OnLinkClickSync(nsIContent* aContent, |
13357 | nsDocShellLoadState* aLoadState, |
13358 | bool aNoOpenerImplied, |
13359 | nsIPrincipal* aTriggeringPrincipal) { |
13360 | if (!IsNavigationAllowed() || !IsOKToLoadURI(aLoadState->URI())) { |
13361 | return NS_OK; |
13362 | } |
13363 | |
13364 | // XXX When the linking node was HTMLFormElement, it is synchronous event. |
13365 | // That is, the caller of this method is not |OnLinkClickEvent::Run()| |
13366 | // but |HTMLFormElement::SubmitSubmission(...)|. |
13367 | if (aContent->IsHTMLElement(nsGkAtoms::form) && |
13368 | ShouldBlockLoadingForBackButton()) { |
13369 | return NS_OK; |
13370 | } |
13371 | |
13372 | if (aContent->IsEditable()) { |
13373 | return NS_OK; |
13374 | } |
13375 | |
13376 | // if the triggeringPrincipal is not passed explicitly, then we |
13377 | // fall back to using doc->NodePrincipal() as the triggeringPrincipal. |
13378 | nsCOMPtr<nsIPrincipal> triggeringPrincipal = |
13379 | aTriggeringPrincipal ? aTriggeringPrincipal : aContent->NodePrincipal(); |
13380 | |
13381 | { |
13382 | // defer to an external protocol handler if necessary... |
13383 | nsCOMPtr<nsIExternalProtocolService> extProtService = |
13384 | do_GetService(NS_EXTERNALPROTOCOLSERVICE_CONTRACTID"@mozilla.org/uriloader/external-protocol-service;1"); |
13385 | if (extProtService) { |
13386 | nsAutoCString scheme; |
13387 | aLoadState->URI()->GetScheme(scheme); |
13388 | if (!scheme.IsEmpty()) { |
13389 | // if the URL scheme does not correspond to an exposed protocol, then |
13390 | // we need to hand this link click over to the external protocol |
13391 | // handler. |
13392 | bool isExposed; |
13393 | nsresult rv = |
13394 | extProtService->IsExposedProtocol(scheme.get(), &isExposed); |
13395 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && !isExposed) { |
13396 | return extProtService->LoadURI( |
13397 | aLoadState->URI(), triggeringPrincipal, nullptr, mBrowsingContext, |
13398 | /* aTriggeredExternally */ |
13399 | false, |
13400 | /* aHasValidUserGestureActivation */ |
13401 | aContent->OwnerDoc()->HasValidTransientUserGestureActivation(), |
13402 | /* aNewWindowTarget */ false); |
13403 | } |
13404 | } |
13405 | } |
13406 | } |
13407 | uint32_t triggeringSandboxFlags = 0; |
13408 | uint64_t triggeringWindowId = 0; |
13409 | bool triggeringStorageAccess = false; |
13410 | if (mBrowsingContext) { |
13411 | triggeringSandboxFlags = aContent->OwnerDoc()->GetSandboxFlags(); |
13412 | triggeringWindowId = aContent->OwnerDoc()->InnerWindowID(); |
13413 | triggeringStorageAccess = aContent->OwnerDoc()->UsingStorageAccess(); |
13414 | } |
13415 | |
13416 | uint32_t flags = INTERNAL_LOAD_FLAGS_NONE; |
13417 | bool elementCanHaveNoopener = ElementCanHaveNoopener(aContent); |
13418 | bool triggeringPrincipalIsSystemPrincipal = |
13419 | aLoadState->TriggeringPrincipal()->IsSystemPrincipal(); |
13420 | if (elementCanHaveNoopener) { |
13421 | MOZ_ASSERT(aContent->IsHTMLElement() || aContent->IsSVGElement())do { static_assert( mozilla::detail::AssertionConditionType< decltype(aContent->IsHTMLElement() || aContent->IsSVGElement ())>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(aContent->IsHTMLElement() || aContent->IsSVGElement ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("aContent->IsHTMLElement() || aContent->IsSVGElement()" , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 13421); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aContent->IsHTMLElement() || aContent->IsSVGElement()" ")"); do { MOZ_CrashSequence(__null, 13421); __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
13422 | nsAutoString relString; |
13423 | aContent->AsElement()->GetAttr(nsGkAtoms::rel, relString); |
13424 | nsWhitespaceTokenizerTemplate<nsContentUtils::IsHTMLWhitespace> tok( |
13425 | relString); |
13426 | |
13427 | bool targetBlank = aLoadState->Target().LowerCaseEqualsLiteral("_blank"); |
13428 | bool explicitOpenerSet = false; |
13429 | |
13430 | // The opener behaviour follows a hierarchy, such that if a higher |
13431 | // priority behaviour is specified, it always takes priority. That |
13432 | // priority is currently: norefrerer > noopener > opener > default |
13433 | |
13434 | while (tok.hasMoreTokens()) { |
13435 | const nsAString& token = tok.nextToken(); |
13436 | if (token.LowerCaseEqualsLiteral("noreferrer")) { |
13437 | flags |= INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER | |
13438 | INTERNAL_LOAD_FLAGS_NO_OPENER; |
13439 | // noreferrer cannot be overwritten by a 'rel=opener'. |
13440 | explicitOpenerSet = true; |
13441 | break; |
13442 | } |
13443 | |
13444 | if (token.LowerCaseEqualsLiteral("noopener")) { |
13445 | flags |= INTERNAL_LOAD_FLAGS_NO_OPENER; |
13446 | explicitOpenerSet = true; |
13447 | } |
13448 | |
13449 | if (targetBlank && StaticPrefs::dom_targetBlankNoOpener_enabled() && |
13450 | token.LowerCaseEqualsLiteral("opener") && !explicitOpenerSet) { |
13451 | explicitOpenerSet = true; |
13452 | } |
13453 | } |
13454 | |
13455 | if (targetBlank && StaticPrefs::dom_targetBlankNoOpener_enabled() && |
13456 | !explicitOpenerSet && !triggeringPrincipalIsSystemPrincipal) { |
13457 | flags |= INTERNAL_LOAD_FLAGS_NO_OPENER; |
13458 | } |
13459 | |
13460 | if (aNoOpenerImplied) { |
13461 | flags |= INTERNAL_LOAD_FLAGS_NO_OPENER; |
13462 | } |
13463 | } |
13464 | |
13465 | // Get the owner document of the link that was clicked, this will be |
13466 | // the document that the link is in, or the last document that the |
13467 | // link was in. From that document, we'll get the URI to use as the |
13468 | // referrer, since the current URI in this docshell may be a |
13469 | // new document that we're in the process of loading. |
13470 | RefPtr<Document> referrerDoc = aContent->OwnerDoc(); |
13471 | |
13472 | // Now check that the referrerDoc's inner window is the current inner |
13473 | // window for mScriptGlobal. If it's not, then we don't want to |
13474 | // follow this link. |
13475 | nsPIDOMWindowInner* referrerInner = referrerDoc->GetInnerWindow(); |
13476 | if (!mScriptGlobal || !referrerInner || |
13477 | mScriptGlobal->GetCurrentInnerWindow() != referrerInner) { |
13478 | // We're no longer the current inner window |
13479 | return NS_OK; |
13480 | } |
13481 | |
13482 | // referrer could be null here in some odd cases, but that's ok, |
13483 | // we'll just load the link w/o sending a referrer in those cases. |
13484 | |
13485 | // If this is an anchor element, grab its type property to use as a hint |
13486 | nsAutoString typeHint; |
13487 | RefPtr<HTMLAnchorElement> anchor = HTMLAnchorElement::FromNode(aContent); |
13488 | if (anchor) { |
13489 | anchor->GetType(typeHint); |
13490 | NS_ConvertUTF16toUTF8 utf8Hint(typeHint); |
13491 | nsAutoCString type, dummy; |
13492 | NS_ParseRequestContentType(utf8Hint, type, dummy); |
13493 | CopyUTF8toUTF16(type, typeHint); |
13494 | } |
13495 | |
13496 | uint32_t loadType = LOAD_LINK; |
13497 | if (aLoadState->IsFormSubmission()) { |
13498 | if (aLoadState->Target().IsEmpty()) { |
13499 | // We set the right load type here for form submissions with an empty |
13500 | // target. Form submission with a non-empty target are handled in |
13501 | // nsDocShell::PerformRetargeting after we've selected the correct target |
13502 | // BC. |
13503 | loadType = GetLoadTypeForFormSubmission(GetBrowsingContext(), aLoadState); |
13504 | } |
13505 | } else { |
13506 | // Link click can be triggered inside an onload handler, and we don't want |
13507 | // to add history entry in this case. |
13508 | bool inOnLoadHandler = false; |
13509 | GetIsExecutingOnLoadHandler(&inOnLoadHandler); |
13510 | if (inOnLoadHandler) { |
13511 | loadType = LOAD_NORMAL_REPLACE; |
13512 | } |
13513 | } |
13514 | |
13515 | nsCOMPtr<nsIReferrerInfo> referrerInfo = |
13516 | elementCanHaveNoopener ? new ReferrerInfo(*aContent->AsElement()) |
13517 | : new ReferrerInfo(*referrerDoc); |
13518 | |
13519 | aLoadState->SetTriggeringSandboxFlags(triggeringSandboxFlags); |
13520 | aLoadState->SetTriggeringWindowId(triggeringWindowId); |
13521 | aLoadState->SetTriggeringStorageAccess(triggeringStorageAccess); |
13522 | aLoadState->SetReferrerInfo(referrerInfo); |
13523 | aLoadState->SetInternalLoadFlags(flags); |
13524 | aLoadState->SetTypeHint(NS_ConvertUTF16toUTF8(typeHint)); |
13525 | aLoadState->SetLoadType(loadType); |
13526 | aLoadState->SetSourceBrowsingContext(mBrowsingContext); |
13527 | aLoadState->SetSourceElement(aContent->AsElement()); |
13528 | |
13529 | nsresult rv = InternalLoad(aLoadState); |
13530 | |
13531 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) { |
13532 | nsPingListener::DispatchPings(this, aContent, aLoadState->URI(), |
13533 | referrerInfo); |
13534 | } |
13535 | |
13536 | return rv; |
13537 | } |
13538 | |
13539 | nsresult nsDocShell::OnOverLink(nsIContent* aContent, nsIURI* aURI, |
13540 | const nsAString& aTargetSpec) { |
13541 | if (aContent->IsEditable()) { |
13542 | return NS_OK; |
13543 | } |
13544 | |
13545 | nsresult rv = NS_ERROR_FAILURE; |
13546 | |
13547 | nsCOMPtr<nsIWebBrowserChrome> browserChrome = do_GetInterface(mTreeOwner); |
13548 | if (!browserChrome) { |
13549 | return rv; |
13550 | } |
13551 | |
13552 | nsCOMPtr<nsIURI> exposableURI = nsIOService::CreateExposableURI(aURI); |
13553 | nsAutoCString spec; |
13554 | rv = exposableURI->GetDisplaySpec(spec); |
13555 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 13555); return rv; } } while (false); |
13556 | |
13557 | NS_ConvertUTF8toUTF16 uStr(spec); |
13558 | |
13559 | PredictorPredict(aURI, mCurrentURI, nsINetworkPredictor::PREDICT_LINK, |
13560 | aContent->NodePrincipal()->OriginAttributesRef(), nullptr); |
13561 | |
13562 | rv = browserChrome->SetLinkStatus(uStr); |
13563 | return rv; |
13564 | } |
13565 | |
13566 | nsresult nsDocShell::OnLeaveLink() { |
13567 | nsCOMPtr<nsIWebBrowserChrome> browserChrome(do_GetInterface(mTreeOwner)); |
13568 | nsresult rv = NS_ERROR_FAILURE; |
13569 | |
13570 | if (browserChrome) { |
13571 | rv = browserChrome->SetLinkStatus(u""_ns); |
13572 | } |
13573 | return rv; |
13574 | } |
13575 | |
13576 | bool nsDocShell::ShouldBlockLoadingForBackButton() { |
13577 | if (!(mLoadType & LOAD_CMD_HISTORY) || |
13578 | UserActivation::IsHandlingUserInput() || |
13579 | !Preferences::GetBool("accessibility.blockjsredirection")) { |
13580 | return false; |
13581 | } |
13582 | |
13583 | bool canGoForward = false; |
13584 | GetCanGoForward(&canGoForward); |
13585 | return canGoForward; |
13586 | } |
13587 | |
13588 | //---------------------------------------------------------------------- |
13589 | // Web Shell Services API |
13590 | |
13591 | // This functions is only called when a new charset is detected in loading a |
13592 | // document. |
13593 | nsresult nsDocShell::CharsetChangeReloadDocument( |
13594 | mozilla::NotNull<const mozilla::Encoding*> aEncoding, int32_t aSource) { |
13595 | // XXX hack. keep the aCharset and aSource wait to pick it up |
13596 | nsCOMPtr<nsIDocumentViewer> viewer; |
13597 | NS_ENSURE_SUCCESS(GetDocViewer(getter_AddRefs(viewer)), NS_ERROR_FAILURE)do { nsresult __rv = GetDocViewer(getter_AddRefs(viewer)); if (((bool)(__builtin_expect(!!(NS_FAILED_impl(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "GetDocViewer(getter_AddRefs(viewer))" , "NS_ERROR_FAILURE", static_cast<uint32_t>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""); NS_DebugBreak (NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 13597); return NS_ERROR_FAILURE; } } while (false); |
13598 | if (viewer) { |
13599 | int32_t source; |
13600 | Unused << viewer->GetReloadEncodingAndSource(&source); |
13601 | if (aSource > source) { |
13602 | viewer->SetReloadEncodingAndSource(aEncoding, aSource); |
13603 | if (eCharsetReloadRequested != mCharsetReloadState) { |
13604 | mCharsetReloadState = eCharsetReloadRequested; |
13605 | switch (mLoadType) { |
13606 | case LOAD_RELOAD_BYPASS_PROXY_AND_CACHE: |
13607 | return Reload(LOAD_FLAGS_CHARSET_CHANGE | LOAD_FLAGS_BYPASS_CACHE | |
13608 | LOAD_FLAGS_BYPASS_PROXY); |
13609 | case LOAD_RELOAD_BYPASS_CACHE: |
13610 | return Reload(LOAD_FLAGS_CHARSET_CHANGE | LOAD_FLAGS_BYPASS_CACHE); |
13611 | default: |
13612 | return Reload(LOAD_FLAGS_CHARSET_CHANGE); |
13613 | } |
13614 | } |
13615 | } |
13616 | } |
13617 | // return failure if this request is not accepted due to mCharsetReloadState |
13618 | return NS_ERROR_DOCSHELL_REQUEST_REJECTED; |
13619 | } |
13620 | |
13621 | nsresult nsDocShell::CharsetChangeStopDocumentLoad() { |
13622 | if (eCharsetReloadRequested != mCharsetReloadState) { |
13623 | Stop(nsIWebNavigation::STOP_ALL); |
13624 | return NS_OK; |
13625 | } |
13626 | // return failer if this request is not accepted due to mCharsetReloadState |
13627 | return NS_ERROR_DOCSHELL_REQUEST_REJECTED; |
13628 | } |
13629 | |
13630 | NS_IMETHODIMPnsresult nsDocShell::ExitPrintPreview() { |
13631 | #if NS_PRINT_PREVIEW1 |
13632 | nsCOMPtr<nsIWebBrowserPrint> viewer = do_QueryInterface(mDocumentViewer); |
13633 | return viewer->ExitPrintPreview(); |
13634 | #else |
13635 | return NS_OK; |
13636 | #endif |
13637 | } |
13638 | |
13639 | /* [infallible] */ |
13640 | NS_IMETHODIMPnsresult nsDocShell::GetIsTopLevelContentDocShell( |
13641 | bool* aIsTopLevelContentDocShell) { |
13642 | *aIsTopLevelContentDocShell = false; |
13643 | |
13644 | if (mItemType == typeContent) { |
13645 | *aIsTopLevelContentDocShell = mBrowsingContext->IsTopContent(); |
13646 | } |
13647 | |
13648 | return NS_OK; |
13649 | } |
13650 | |
13651 | // Implements nsILoadContext.originAttributes |
13652 | NS_IMETHODIMPnsresult |
13653 | nsDocShell::GetScriptableOriginAttributes(JSContext* aCx, |
13654 | JS::MutableHandle<JS::Value> aVal) { |
13655 | return mBrowsingContext->GetScriptableOriginAttributes(aCx, aVal); |
13656 | } |
13657 | |
13658 | // Implements nsIDocShell.GetOriginAttributes() |
13659 | NS_IMETHODIMPnsresult |
13660 | nsDocShell::GetOriginAttributes(JSContext* aCx, |
13661 | JS::MutableHandle<JS::Value> aVal) { |
13662 | return mBrowsingContext->GetScriptableOriginAttributes(aCx, aVal); |
13663 | } |
13664 | |
13665 | bool nsDocShell::ServiceWorkerAllowedToControlWindow(nsIPrincipal* aPrincipal, |
13666 | nsIURI* aURI) { |
13667 | MOZ_ASSERT(aPrincipal)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aPrincipal)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aPrincipal))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aPrincipal", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 13667); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPrincipal" ")"); do { MOZ_CrashSequence(__null, 13667); __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
13668 | MOZ_ASSERT(aURI)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aURI)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(aURI))), 0))) { do { } while (false ); MOZ_ReportAssertionFailure("aURI", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 13668); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aURI" ")") ; do { MOZ_CrashSequence(__null, 13668); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
13669 | |
13670 | if (UsePrivateBrowsing() || mBrowsingContext->GetSandboxFlags()) { |
13671 | return false; |
13672 | } |
13673 | |
13674 | nsCOMPtr<nsIDocShellTreeItem> parent; |
13675 | GetInProcessSameTypeParent(getter_AddRefs(parent)); |
13676 | nsPIDOMWindowOuter* parentOuter = parent ? parent->GetWindow() : nullptr; |
13677 | nsPIDOMWindowInner* parentInner = |
13678 | parentOuter ? parentOuter->GetCurrentInnerWindow() : nullptr; |
13679 | |
13680 | StorageAccess storage = |
13681 | StorageAllowedForNewWindow(aPrincipal, aURI, parentInner); |
13682 | |
13683 | // If the partitioned service worker is enabled, service worker is allowed to |
13684 | // control the window if partition is enabled. |
13685 | if (StaticPrefs::privacy_partition_serviceWorkers() && parentInner) { |
13686 | RefPtr<Document> doc = parentInner->GetExtantDoc(); |
13687 | |
13688 | if (doc && StoragePartitioningEnabled(storage, doc->CookieJarSettings())) { |
13689 | return true; |
13690 | } |
13691 | } |
13692 | |
13693 | return storage == StorageAccess::eAllow; |
13694 | } |
13695 | |
13696 | nsresult nsDocShell::SetOriginAttributes(const OriginAttributes& aAttrs) { |
13697 | MOZ_ASSERT(!mIsBeingDestroyed)do { static_assert( mozilla::detail::AssertionConditionType< decltype(!mIsBeingDestroyed)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!mIsBeingDestroyed))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!mIsBeingDestroyed" , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 13697); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mIsBeingDestroyed" ")"); do { MOZ_CrashSequence(__null, 13697); __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
13698 | return mBrowsingContext->SetOriginAttributes(aAttrs); |
13699 | } |
13700 | |
13701 | NS_IMETHODIMPnsresult |
13702 | nsDocShell::ResumeRedirectedLoad(uint64_t aIdentifier, int32_t aHistoryIndex) { |
13703 | RefPtr<nsDocShell> self = this; |
13704 | RefPtr<ChildProcessChannelListener> cpcl = |
13705 | ChildProcessChannelListener::GetSingleton(); |
13706 | |
13707 | // Call into InternalLoad with the pending channel when it is received. |
13708 | cpcl->RegisterCallback( |
13709 | aIdentifier, [self, aHistoryIndex]( |
13710 | nsDocShellLoadState* aLoadState, |
13711 | nsTArray<Endpoint<extensions::PStreamFilterParent>>&& |
13712 | aStreamFilterEndpoints, |
13713 | nsDOMNavigationTiming* aTiming) { |
13714 | MOZ_ASSERT(aLoadState->GetPendingRedirectedChannel())do { static_assert( mozilla::detail::AssertionConditionType< decltype(aLoadState->GetPendingRedirectedChannel())>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(aLoadState->GetPendingRedirectedChannel()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aLoadState->GetPendingRedirectedChannel()" , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 13714); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->GetPendingRedirectedChannel()" ")"); do { MOZ_CrashSequence(__null, 13714); __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
13715 | if (NS_WARN_IF(self->mIsBeingDestroyed)NS_warn_if_impl(self->mIsBeingDestroyed, "self->mIsBeingDestroyed" , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 13715)) { |
13716 | aLoadState->GetPendingRedirectedChannel()->CancelWithReason( |
13717 | NS_BINDING_ABORTED, "nsDocShell::mIsBeingDestroyed"_ns); |
13718 | return NS_BINDING_ABORTED; |
13719 | } |
13720 | |
13721 | self->mLoadType = aLoadState->LoadType(); |
13722 | nsCOMPtr<nsIURI> previousURI; |
13723 | uint32_t previousFlags = 0; |
13724 | ExtractLastVisit(aLoadState->GetPendingRedirectedChannel(), |
13725 | getter_AddRefs(previousURI), &previousFlags); |
13726 | self->SaveLastVisit(aLoadState->GetPendingRedirectedChannel(), |
13727 | previousURI, previousFlags); |
13728 | |
13729 | if (aTiming) { |
13730 | self->mTiming = new nsDOMNavigationTiming(self, aTiming); |
13731 | self->mBlankTiming = false; |
13732 | } |
13733 | |
13734 | // If we're performing a history load, locate the correct history entry, |
13735 | // and set the relevant bits on our loadState. |
13736 | if (aHistoryIndex >= 0 && self->GetSessionHistory() && |
13737 | !mozilla::SessionHistoryInParent()) { |
13738 | nsCOMPtr<nsISHistory> legacySHistory = |
13739 | self->GetSessionHistory()->LegacySHistory(); |
13740 | |
13741 | nsCOMPtr<nsISHEntry> entry; |
13742 | nsresult rv = legacySHistory->GetEntryAtIndex(aHistoryIndex, |
13743 | getter_AddRefs(entry)); |
13744 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) { |
13745 | legacySHistory->InternalSetRequestedIndex(aHistoryIndex); |
13746 | aLoadState->SetLoadType(LOAD_HISTORY); |
13747 | aLoadState->SetSHEntry(entry); |
13748 | } |
13749 | } |
13750 | |
13751 | self->InternalLoad(aLoadState); |
13752 | |
13753 | if (aLoadState->GetOriginalURIString().isSome()) { |
13754 | // Save URI string in case it's needed later when |
13755 | // sending to search engine service in EndPageLoad() |
13756 | self->mOriginalUriString = *aLoadState->GetOriginalURIString(); |
13757 | } |
13758 | |
13759 | for (auto& endpoint : aStreamFilterEndpoints) { |
13760 | extensions::StreamFilterParent::Attach( |
13761 | aLoadState->GetPendingRedirectedChannel(), std::move(endpoint)); |
13762 | } |
13763 | |
13764 | // If the channel isn't pending, then it means that InternalLoad |
13765 | // never connected it, and we shouldn't try to continue. This |
13766 | // can happen even if InternalLoad returned NS_OK. |
13767 | bool pending = false; |
13768 | aLoadState->GetPendingRedirectedChannel()->IsPending(&pending); |
13769 | NS_ASSERTION(pending, "We should have connected the pending channel!")do { if (!(pending)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "We should have connected the pending channel!" , "pending", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 13769); MOZ_PretendNoReturn(); } } while (0); |
13770 | if (!pending) { |
13771 | return NS_BINDING_ABORTED; |
13772 | } |
13773 | return NS_OK; |
13774 | }); |
13775 | return NS_OK; |
13776 | } |
13777 | |
13778 | NS_IMETHODIMPnsresult |
13779 | nsDocShell::SetOriginAttributes(JS::Handle<JS::Value> aOriginAttributes, |
13780 | JSContext* aCx) { |
13781 | OriginAttributes attrs; |
13782 | if (!aOriginAttributes.isObject() || !attrs.Init(aCx, aOriginAttributes)) { |
13783 | return NS_ERROR_INVALID_ARG; |
13784 | } |
13785 | |
13786 | return SetOriginAttributes(attrs); |
13787 | } |
13788 | |
13789 | NS_IMETHODIMPnsresult |
13790 | nsDocShell::GetAsyncPanZoomEnabled(bool* aOut) { |
13791 | if (PresShell* presShell = GetPresShell()) { |
13792 | *aOut = presShell->AsyncPanZoomEnabled(); |
13793 | return NS_OK; |
13794 | } |
13795 | |
13796 | // If we don't have a presShell, fall back to the default platform value of |
13797 | // whether or not APZ is enabled. |
13798 | *aOut = gfxPlatform::AsyncPanZoomEnabled(); |
13799 | return NS_OK; |
13800 | } |
13801 | |
13802 | bool nsDocShell::HasUnloadedParent() { |
13803 | for (WindowContext* wc = GetBrowsingContext()->GetParentWindowContext(); wc; |
13804 | wc = wc->GetParentWindowContext()) { |
13805 | if (!wc->IsCurrent() || wc->IsDiscarded() || |
13806 | wc->GetBrowsingContext()->IsDiscarded()) { |
13807 | // If a parent is OOP and the parent WindowContext is no |
13808 | // longer current, we can assume the parent was unloaded. |
13809 | return true; |
13810 | } |
13811 | |
13812 | if (wc->GetBrowsingContext()->IsInProcess() && |
13813 | (!wc->GetBrowsingContext()->GetDocShell() || |
13814 | wc->GetBrowsingContext()->GetDocShell()->GetIsInUnload())) { |
13815 | return true; |
13816 | } |
13817 | } |
13818 | return false; |
13819 | } |
13820 | |
13821 | /* static */ |
13822 | bool nsDocShell::ShouldUpdateGlobalHistory(uint32_t aLoadType) { |
13823 | return !(aLoadType == LOAD_BYPASS_HISTORY || aLoadType == LOAD_ERROR_PAGE || |
13824 | aLoadType & LOAD_CMD_HISTORY); |
13825 | } |
13826 | |
13827 | void nsDocShell::UpdateGlobalHistoryTitle(nsIURI* aURI) { |
13828 | if (!mBrowsingContext->GetUseGlobalHistory() || UsePrivateBrowsing()) { |
13829 | return; |
13830 | } |
13831 | |
13832 | // Global history is interested into sub-frame visits only for link-coloring |
13833 | // purposes, thus title updates are skipped for those. |
13834 | // |
13835 | // Moreover, some iframe documents (such as the ones created via |
13836 | // document.open()) inherit the document uri of the caller, which would cause |
13837 | // us to override a previously set page title with one from the subframe. |
13838 | if (IsSubframe()) { |
13839 | return; |
13840 | } |
13841 | |
13842 | if (nsCOMPtr<IHistory> history = components::History::Service()) { |
13843 | history->SetURITitle(aURI, mTitle); |
13844 | } |
13845 | } |
13846 | |
13847 | bool nsDocShell::IsInvisible() { return mInvisible; } |
13848 | |
13849 | void nsDocShell::SetInvisible(bool aInvisible) { mInvisible = aInvisible; } |
13850 | |
13851 | /* static */ |
13852 | void nsDocShell::MaybeNotifyKeywordSearchLoading(const nsString& aProvider, |
13853 | const nsString& aKeyword) { |
13854 | if (aProvider.IsEmpty()) { |
13855 | return; |
13856 | } |
13857 | nsresult rv; |
13858 | nsCOMPtr<nsISupportsString> isupportsString = |
13859 | do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID"@mozilla.org/supports-string;1", &rv); |
13860 | NS_ENSURE_SUCCESS_VOID(rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS_VOID(%s) failed with " "result 0x%" "X" "%s%s%s", "rv", static_cast<uint32_t> (__rv), name ? " (" : "", name ? name : "", name ? ")" : ""); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 13860); return; } } while (false); |
13861 | |
13862 | rv = isupportsString->SetData(aProvider); |
13863 | NS_ENSURE_SUCCESS_VOID(rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS_VOID(%s) failed with " "result 0x%" "X" "%s%s%s", "rv", static_cast<uint32_t> (__rv), name ? " (" : "", name ? name : "", name ? ")" : ""); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 13863); return; } } while (false); |
13864 | |
13865 | nsCOMPtr<nsIObserverService> obsSvc = services::GetObserverService(); |
13866 | if (obsSvc) { |
13867 | // Note that "keyword-search" refers to a search via the url |
13868 | // bar, not a bookmarks keyword search. |
13869 | obsSvc->NotifyObservers(isupportsString, "keyword-search", aKeyword.get()); |
13870 | } |
13871 | } |
13872 | |
13873 | NS_IMETHODIMPnsresult |
13874 | nsDocShell::ShouldPrepareForIntercept(nsIURI* aURI, nsIChannel* aChannel, |
13875 | bool* aShouldIntercept) { |
13876 | return mInterceptController->ShouldPrepareForIntercept(aURI, aChannel, |
13877 | aShouldIntercept); |
13878 | } |
13879 | |
13880 | NS_IMETHODIMPnsresult |
13881 | nsDocShell::ChannelIntercepted(nsIInterceptedChannel* aChannel) { |
13882 | return mInterceptController->ChannelIntercepted(aChannel); |
13883 | } |
13884 | |
13885 | bool nsDocShell::InFrameSwap() { |
13886 | RefPtr<nsDocShell> shell = this; |
13887 | do { |
13888 | if (shell->mInFrameSwap) { |
13889 | return true; |
13890 | } |
13891 | shell = shell->GetInProcessParentDocshell(); |
13892 | } while (shell); |
13893 | return false; |
13894 | } |
13895 | |
13896 | UniquePtr<ClientSource> nsDocShell::TakeInitialClientSource() { |
13897 | return std::move(mInitialClientSource); |
13898 | } |
13899 | |
13900 | NS_IMETHODIMPnsresult |
13901 | nsDocShell::GetEditingSession(nsIEditingSession** aEditSession) { |
13902 | if (!NS_SUCCEEDED(EnsureEditorData())((bool)(__builtin_expect(!!(!NS_FAILED_impl(EnsureEditorData( ))), 1)))) { |
13903 | return NS_ERROR_FAILURE; |
13904 | } |
13905 | |
13906 | *aEditSession = do_AddRef(mEditorData->GetEditingSession()).take(); |
13907 | return *aEditSession ? NS_OK : NS_ERROR_FAILURE; |
13908 | } |
13909 | |
13910 | NS_IMETHODIMPnsresult |
13911 | nsDocShell::GetScriptableBrowserChild(nsIBrowserChild** aBrowserChild) { |
13912 | *aBrowserChild = GetBrowserChild().take(); |
13913 | return *aBrowserChild ? NS_OK : NS_ERROR_FAILURE; |
13914 | } |
13915 | |
13916 | already_AddRefed<nsIBrowserChild> nsDocShell::GetBrowserChild() { |
13917 | nsCOMPtr<nsIBrowserChild> tc = do_QueryReferent(mBrowserChild); |
13918 | return tc.forget(); |
13919 | } |
13920 | |
13921 | nsCommandManager* nsDocShell::GetCommandManager() { |
13922 | NS_ENSURE_SUCCESS(EnsureCommandHandler(), nullptr)do { nsresult __rv = EnsureCommandHandler(); if (((bool)(__builtin_expect (!!(NS_FAILED_impl(__rv)), 0)))) { const char* name = mozilla ::GetStaticErrorName(__rv); mozilla::SmprintfPointer msg = mozilla ::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "EnsureCommandHandler()", "nullptr", static_cast <uint32_t>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 13922); return nullptr; } } while (false); |
13923 | return mCommandManager; |
13924 | } |
13925 | |
13926 | NS_IMETHODIMP_(void)void |
13927 | nsDocShell::GetOriginAttributes(mozilla::OriginAttributes& aAttrs) { |
13928 | mBrowsingContext->GetOriginAttributes(aAttrs); |
13929 | } |
13930 | |
13931 | HTMLEditor* nsIDocShell::GetHTMLEditor() { |
13932 | nsDocShell* docShell = static_cast<nsDocShell*>(this); |
13933 | return docShell->GetHTMLEditorInternal(); |
13934 | } |
13935 | |
13936 | nsresult nsIDocShell::SetHTMLEditor(HTMLEditor* aHTMLEditor) { |
13937 | nsDocShell* docShell = static_cast<nsDocShell*>(this); |
13938 | return docShell->SetHTMLEditorInternal(aHTMLEditor); |
13939 | } |
13940 | |
13941 | #define MATRIX_LENGTH 20 |
13942 | |
13943 | NS_IMETHODIMPnsresult |
13944 | nsDocShell::SetColorMatrix(const nsTArray<float>& aMatrix) { |
13945 | if (aMatrix.Length() == MATRIX_LENGTH) { |
13946 | mColorMatrix.reset(new gfx::Matrix5x4()); |
13947 | static_assert( |
13948 | MATRIX_LENGTH * sizeof(float) == sizeof(mColorMatrix->components), |
13949 | "Size mismatch for our memcpy"); |
13950 | memcpy(mColorMatrix->components, aMatrix.Elements(), |
13951 | sizeof(mColorMatrix->components)); |
13952 | } else if (aMatrix.Length() == 0) { |
13953 | mColorMatrix.reset(); |
13954 | } else { |
13955 | return NS_ERROR_INVALID_ARG; |
13956 | } |
13957 | |
13958 | PresShell* presShell = GetPresShell(); |
13959 | if (!presShell) { |
13960 | return NS_ERROR_FAILURE; |
13961 | } |
13962 | |
13963 | nsIFrame* frame = presShell->GetRootFrame(); |
13964 | if (!frame) { |
13965 | return NS_ERROR_FAILURE; |
13966 | } |
13967 | |
13968 | frame->SchedulePaint(); |
13969 | |
13970 | return NS_OK; |
13971 | } |
13972 | |
13973 | NS_IMETHODIMPnsresult |
13974 | nsDocShell::GetColorMatrix(nsTArray<float>& aMatrix) { |
13975 | if (mColorMatrix) { |
13976 | aMatrix.SetLength(MATRIX_LENGTH); |
13977 | static_assert( |
13978 | MATRIX_LENGTH * sizeof(float) == sizeof(mColorMatrix->components), |
13979 | "Size mismatch for our memcpy"); |
13980 | memcpy(aMatrix.Elements(), mColorMatrix->components, |
13981 | MATRIX_LENGTH * sizeof(float)); |
13982 | } |
13983 | |
13984 | return NS_OK; |
13985 | } |
13986 | |
13987 | #undef MATRIX_LENGTH |
13988 | |
13989 | NS_IMETHODIMPnsresult |
13990 | nsDocShell::GetIsForceReloading(bool* aForceReload) { |
13991 | *aForceReload = IsForceReloading(); |
13992 | return NS_OK; |
13993 | } |
13994 | |
13995 | bool nsDocShell::IsForceReloading() { return IsForceReloadType(mLoadType); } |
13996 | |
13997 | NS_IMETHODIMPnsresult |
13998 | nsDocShell::GetBrowsingContextXPCOM(BrowsingContext** aBrowsingContext) { |
13999 | *aBrowsingContext = do_AddRef(mBrowsingContext).take(); |
14000 | return NS_OK; |
14001 | } |
14002 | |
14003 | BrowsingContext* nsDocShell::GetBrowsingContext() { return mBrowsingContext; } |
14004 | |
14005 | bool nsDocShell::GetIsAttemptingToNavigate() { |
14006 | // XXXbz the document.open spec says to abort even if there's just a |
14007 | // queued navigation task, sort of. It's not clear whether browsers |
14008 | // actually do that, and we didn't use to do it, so for now let's |
14009 | // not do that. |
14010 | // https://github.com/whatwg/html/issues/3447 tracks the spec side of this. |
14011 | if (mDocumentRequest) { |
14012 | // There's definitely a navigation in progress. |
14013 | return true; |
14014 | } |
14015 | |
14016 | // javascript: channels have slightly weird behavior: they're LOAD_BACKGROUND |
14017 | // until the script runs, which means they're not sending loadgroup |
14018 | // notifications and hence not getting set as mDocumentRequest. Look through |
14019 | // our loadgroup for document-level javascript: loads. |
14020 | if (!mLoadGroup) { |
14021 | return false; |
14022 | } |
14023 | |
14024 | nsCOMPtr<nsISimpleEnumerator> requests; |
14025 | mLoadGroup->GetRequests(getter_AddRefs(requests)); |
14026 | bool hasMore = false; |
14027 | while (NS_SUCCEEDED(requests->HasMoreElements(&hasMore))((bool)(__builtin_expect(!!(!NS_FAILED_impl(requests->HasMoreElements (&hasMore))), 1))) && hasMore) { |
14028 | nsCOMPtr<nsISupports> elem; |
14029 | requests->GetNext(getter_AddRefs(elem)); |
14030 | nsCOMPtr<nsIScriptChannel> scriptChannel(do_QueryInterface(elem)); |
14031 | if (!scriptChannel) { |
14032 | continue; |
14033 | } |
14034 | |
14035 | if (scriptChannel->GetIsDocumentLoad()) { |
14036 | // This is a javascript: load that might lead to a new document, |
14037 | // hence a navigation. |
14038 | return true; |
14039 | } |
14040 | } |
14041 | |
14042 | return mCheckingSessionHistory; |
14043 | } |
14044 | |
14045 | mozilla::dom::SessionHistoryInfo* nsDocShell::GetActiveSessionHistoryInfo() |
14046 | const { |
14047 | return mActiveEntry.get(); |
14048 | } |
14049 | |
14050 | void nsDocShell::SetLoadingSessionHistoryInfo( |
14051 | const mozilla::dom::LoadingSessionHistoryInfo& aLoadingInfo, |
14052 | bool aNeedToReportActiveAfterLoadingBecomesActive) { |
14053 | // FIXME Would like to assert this, but can't yet. |
14054 | // MOZ_ASSERT(!mLoadingEntry); |
14055 | MOZ_LOG(gSHLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gSHLog; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "Setting the loading entry on nsDocShell %p to %s" , this, aLoadingInfo.mInfo.GetURI()->GetSpecOrDefault().get ()); } } while (0) |
14056 | ("Setting the loading entry on nsDocShell %p to %s", this,do { const ::mozilla::LogModule* moz_real_module = gSHLog; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "Setting the loading entry on nsDocShell %p to %s" , this, aLoadingInfo.mInfo.GetURI()->GetSpecOrDefault().get ()); } } while (0) |
14057 | aLoadingInfo.mInfo.GetURI()->GetSpecOrDefault().get()))do { const ::mozilla::LogModule* moz_real_module = gSHLog; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "Setting the loading entry on nsDocShell %p to %s" , this, aLoadingInfo.mInfo.GetURI()->GetSpecOrDefault().get ()); } } while (0); |
14058 | mLoadingEntry = MakeUnique<LoadingSessionHistoryInfo>(aLoadingInfo); |
14059 | mNeedToReportActiveAfterLoadingBecomesActive = |
14060 | aNeedToReportActiveAfterLoadingBecomesActive; |
14061 | } |
14062 | |
14063 | void nsDocShell::MoveLoadingToActiveEntry(bool aExpired, uint32_t aCacheKey, |
14064 | nsIURI* aPreviousURI, |
14065 | nsIPrincipal* aPartitionedPrincipal) { |
14066 | MOZ_ASSERT(mozilla::SessionHistoryInParent())do { static_assert( mozilla::detail::AssertionConditionType< decltype(mozilla::SessionHistoryInParent())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mozilla::SessionHistoryInParent ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("mozilla::SessionHistoryInParent()", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 14066); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mozilla::SessionHistoryInParent()" ")"); do { MOZ_CrashSequence(__null, 14066); __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
14067 | |
14068 | MOZ_LOG(gSHLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gSHLog; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "nsDocShell %p MoveLoadingToActiveEntry", this ); } } while (0) |
14069 | ("nsDocShell %p MoveLoadingToActiveEntry", this))do { const ::mozilla::LogModule* moz_real_module = gSHLog; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "nsDocShell %p MoveLoadingToActiveEntry", this ); } } while (0); |
14070 | |
14071 | UniquePtr<SessionHistoryInfo> previousActiveEntry(mActiveEntry.release()); |
14072 | mozilla::UniquePtr<mozilla::dom::LoadingSessionHistoryInfo> loadingEntry; |
14073 | mActiveEntryIsLoadingFromSessionHistory = |
14074 | mLoadingEntry && mLoadingEntry->mLoadIsFromSessionHistory; |
14075 | if (mLoadingEntry) { |
14076 | MOZ_LOG(gSHLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gSHLog; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "Moving the loading entry to the active entry on nsDocShell %p " "to %s", this, mLoadingEntry->mInfo.GetURI()->GetSpecOrDefault ().get()); } } while (0) |
14077 | ("Moving the loading entry to the active entry on nsDocShell %p "do { const ::mozilla::LogModule* moz_real_module = gSHLog; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "Moving the loading entry to the active entry on nsDocShell %p " "to %s", this, mLoadingEntry->mInfo.GetURI()->GetSpecOrDefault ().get()); } } while (0) |
14078 | "to %s",do { const ::mozilla::LogModule* moz_real_module = gSHLog; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "Moving the loading entry to the active entry on nsDocShell %p " "to %s", this, mLoadingEntry->mInfo.GetURI()->GetSpecOrDefault ().get()); } } while (0) |
14079 | this, mLoadingEntry->mInfo.GetURI()->GetSpecOrDefault().get()))do { const ::mozilla::LogModule* moz_real_module = gSHLog; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "Moving the loading entry to the active entry on nsDocShell %p " "to %s", this, mLoadingEntry->mInfo.GetURI()->GetSpecOrDefault ().get()); } } while (0); |
14080 | mLoadingEntry->mInfo.SetPartitionedPrincipalToInherit( |
14081 | aPartitionedPrincipal); |
14082 | mActiveEntry = MakeUnique<SessionHistoryInfo>(mLoadingEntry->mInfo); |
14083 | mLoadingEntry.swap(loadingEntry); |
14084 | if (!mActiveEntryIsLoadingFromSessionHistory) { |
14085 | if (mNeedToReportActiveAfterLoadingBecomesActive) { |
14086 | // Needed to pass various history length WPTs. |
14087 | mBrowsingContext->SetActiveSessionHistoryEntry( |
14088 | mozilla::Nothing(), mActiveEntry.get(), previousActiveEntry.get(), |
14089 | mLoadType, |
14090 | /* aUpdatedCacheKey = */ 0, false); |
14091 | } |
14092 | if (!(previousActiveEntry && previousActiveEntry->IsTransient())) { |
14093 | mBrowsingContext->IncrementHistoryEntryCountForBrowsingContext(); |
14094 | } |
14095 | } |
14096 | } |
14097 | mNeedToReportActiveAfterLoadingBecomesActive = false; |
14098 | |
14099 | if (mActiveEntry) { |
14100 | if (aCacheKey != 0) { |
14101 | mActiveEntry->SetCacheKey(aCacheKey); |
14102 | } |
14103 | |
14104 | mActiveEntry->SetPartitionedPrincipalToInherit(aPartitionedPrincipal); |
14105 | MOZ_ASSERT(loadingEntry)do { static_assert( mozilla::detail::AssertionConditionType< decltype(loadingEntry)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(loadingEntry))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("loadingEntry", "/root/firefox-clang/docshell/base/nsDocShell.cpp" , 14105); AnnotateMozCrashReason("MOZ_ASSERT" "(" "loadingEntry" ")"); do { MOZ_CrashSequence(__null, 14105); __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
14106 | uint32_t loadType = |
14107 | mLoadType == LOAD_ERROR_PAGE ? mFailedLoadType : mLoadType; |
14108 | |
14109 | if (loadingEntry->mLoadId != UINT64_MAX(18446744073709551615UL)) { |
14110 | // We're passing in mCurrentURI, which could be null. SessionHistoryCommit |
14111 | // does require a non-null uri if this is for a refresh load of the same |
14112 | // URI, but in that case mCurrentURI won't be null here. |
14113 | mBrowsingContext->SessionHistoryCommit( |
14114 | *loadingEntry, loadType, aPreviousURI, previousActiveEntry.get(), |
14115 | false, aExpired, aCacheKey, aPartitionedPrincipal); |
14116 | } |
14117 | |
14118 | // Only update navigation if the new entry will be persisted (i.e., is not |
14119 | // an about: page). |
14120 | if (!loadingEntry->mInfo.IsTransient() && GetWindow() && |
14121 | GetWindow()->GetCurrentInnerWindow()) { |
14122 | if (RefPtr navigation = |
14123 | GetWindow()->GetCurrentInnerWindow()->Navigation()) { |
14124 | mBrowsingContext->GetContiguousHistoryEntries(*mActiveEntry, |
14125 | navigation); |
14126 | } |
14127 | } |
14128 | } |
14129 | } |
14130 | |
14131 | static bool IsFaviconLoad(nsIRequest* aRequest) { |
14132 | nsCOMPtr<nsIChannel> channel = do_QueryInterface(aRequest); |
14133 | if (!channel) { |
14134 | return false; |
14135 | } |
14136 | |
14137 | nsCOMPtr<nsILoadInfo> li = channel->LoadInfo(); |
14138 | return li && li->InternalContentPolicyType() == |
14139 | nsIContentPolicy::TYPE_INTERNAL_IMAGE_FAVICON; |
14140 | } |
14141 | |
14142 | void nsDocShell::RecordSingleChannelId(bool aStartRequest, |
14143 | nsIRequest* aRequest) { |
14144 | // Ignore favicon loads, they don't need to block caching. |
14145 | if (IsFaviconLoad(aRequest)) { |
14146 | return; |
14147 | } |
14148 | |
14149 | MOZ_ASSERT_IF(!aStartRequest, mRequestForBlockingFromBFCacheCount > 0)do { if (!aStartRequest) { do { static_assert( mozilla::detail ::AssertionConditionType<decltype(mRequestForBlockingFromBFCacheCount > 0)>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(mRequestForBlockingFromBFCacheCount > 0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mRequestForBlockingFromBFCacheCount > 0" , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 14149); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mRequestForBlockingFromBFCacheCount > 0" ")"); do { MOZ_CrashSequence(__null, 14149); __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); } } while (false); |
14150 | |
14151 | mRequestForBlockingFromBFCacheCount += aStartRequest ? 1 : -1; |
14152 | |
14153 | if (mBrowsingContext->GetCurrentWindowContext()) { |
14154 | // We have three states: no request, one request with an id and |
14155 | // eiher one request without an id or multiple requests. Nothing() is no |
14156 | // request, Some(non-zero) is one request with an id and Some(0) is one |
14157 | // request without an id or multiple requests. |
14158 | Maybe<uint64_t> singleChannelId; |
14159 | if (mRequestForBlockingFromBFCacheCount > 1) { |
14160 | singleChannelId = Some(0); |
14161 | } else if (mRequestForBlockingFromBFCacheCount == 1) { |
14162 | nsCOMPtr<nsIIdentChannel> identChannel; |
14163 | if (aStartRequest) { |
14164 | identChannel = do_QueryInterface(aRequest); |
14165 | } else { |
14166 | // aChannel is the channel that's being removed, but we need to check if |
14167 | // the remaining channel in the loadgroup has an id. |
14168 | nsCOMPtr<nsISimpleEnumerator> requests; |
14169 | mLoadGroup->GetRequests(getter_AddRefs(requests)); |
14170 | for (const auto& request : SimpleEnumerator<nsIRequest>(requests)) { |
14171 | if (!IsFaviconLoad(request) && |
14172 | !!(identChannel = do_QueryInterface(request))) { |
14173 | break; |
14174 | } |
14175 | } |
14176 | } |
14177 | |
14178 | if (identChannel) { |
14179 | singleChannelId = Some(identChannel->ChannelId()); |
14180 | } else { |
14181 | singleChannelId = Some(0); |
14182 | } |
14183 | } else { |
14184 | MOZ_ASSERT(mRequestForBlockingFromBFCacheCount == 0)do { static_assert( mozilla::detail::AssertionConditionType< decltype(mRequestForBlockingFromBFCacheCount == 0)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(mRequestForBlockingFromBFCacheCount == 0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mRequestForBlockingFromBFCacheCount == 0" , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 14184); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mRequestForBlockingFromBFCacheCount == 0" ")"); do { MOZ_CrashSequence(__null, 14184); __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
14185 | singleChannelId = Nothing(); |
14186 | } |
14187 | |
14188 | if (MOZ_UNLIKELY(MOZ_LOG_TEST(gSHIPBFCacheLog, LogLevel::Verbose))(__builtin_expect(!!((__builtin_expect(!!(mozilla::detail::log_test (gSHIPBFCacheLog, LogLevel::Verbose)), 0))), 0))) { |
14189 | nsAutoCString uri("[no uri]"); |
14190 | if (mCurrentURI) { |
14191 | uri = mCurrentURI->GetSpecOrDefault(); |
14192 | } |
14193 | if (singleChannelId.isNothing()) { |
14194 | MOZ_LOG(gSHIPBFCacheLog, LogLevel::Verbose,do { const ::mozilla::LogModule* moz_real_module = gSHIPBFCacheLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Verbose)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Verbose, "Loadgroup for %s doesn't have any requests relevant for " "blocking BFCache", uri.get()); } } while (0) |
14195 | ("Loadgroup for %s doesn't have any requests relevant for "do { const ::mozilla::LogModule* moz_real_module = gSHIPBFCacheLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Verbose)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Verbose, "Loadgroup for %s doesn't have any requests relevant for " "blocking BFCache", uri.get()); } } while (0) |
14196 | "blocking BFCache",do { const ::mozilla::LogModule* moz_real_module = gSHIPBFCacheLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Verbose)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Verbose, "Loadgroup for %s doesn't have any requests relevant for " "blocking BFCache", uri.get()); } } while (0) |
14197 | uri.get()))do { const ::mozilla::LogModule* moz_real_module = gSHIPBFCacheLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Verbose)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Verbose, "Loadgroup for %s doesn't have any requests relevant for " "blocking BFCache", uri.get()); } } while (0); |
14198 | } else if (singleChannelId.value() == 0) { |
14199 | MOZ_LOG(gSHIPBFCacheLog, LogLevel::Verbose,do { const ::mozilla::LogModule* moz_real_module = gSHIPBFCacheLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Verbose)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Verbose, "Loadgroup for %s has multiple requests relevant for blocking " "BFCache", uri.get()); } } while (0) |
14200 | ("Loadgroup for %s has multiple requests relevant for blocking "do { const ::mozilla::LogModule* moz_real_module = gSHIPBFCacheLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Verbose)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Verbose, "Loadgroup for %s has multiple requests relevant for blocking " "BFCache", uri.get()); } } while (0) |
14201 | "BFCache",do { const ::mozilla::LogModule* moz_real_module = gSHIPBFCacheLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Verbose)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Verbose, "Loadgroup for %s has multiple requests relevant for blocking " "BFCache", uri.get()); } } while (0) |
14202 | uri.get()))do { const ::mozilla::LogModule* moz_real_module = gSHIPBFCacheLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Verbose)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Verbose, "Loadgroup for %s has multiple requests relevant for blocking " "BFCache", uri.get()); } } while (0); |
14203 | } else { |
14204 | MOZ_LOG(gSHIPBFCacheLog, LogLevel::Verbose,do { const ::mozilla::LogModule* moz_real_module = gSHIPBFCacheLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Verbose)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Verbose, "Loadgroup for %s has one request with id %" "l" "u" " relevant for blocking BFCache", uri.get(), singleChannelId .value()); } } while (0) |
14205 | ("Loadgroup for %s has one request with id %" PRIu64do { const ::mozilla::LogModule* moz_real_module = gSHIPBFCacheLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Verbose)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Verbose, "Loadgroup for %s has one request with id %" "l" "u" " relevant for blocking BFCache", uri.get(), singleChannelId .value()); } } while (0) |
14206 | " relevant for blocking BFCache",do { const ::mozilla::LogModule* moz_real_module = gSHIPBFCacheLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Verbose)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Verbose, "Loadgroup for %s has one request with id %" "l" "u" " relevant for blocking BFCache", uri.get(), singleChannelId .value()); } } while (0) |
14207 | uri.get(), singleChannelId.value()))do { const ::mozilla::LogModule* moz_real_module = gSHIPBFCacheLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Verbose)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Verbose, "Loadgroup for %s has one request with id %" "l" "u" " relevant for blocking BFCache", uri.get(), singleChannelId .value()); } } while (0); |
14208 | } |
14209 | } |
14210 | |
14211 | if (mSingleChannelId != singleChannelId) { |
14212 | mSingleChannelId = singleChannelId; |
14213 | WindowGlobalChild* wgc = |
14214 | mBrowsingContext->GetCurrentWindowContext()->GetWindowGlobalChild(); |
14215 | if (wgc) { |
14216 | wgc->SendSetSingleChannelId(singleChannelId); |
14217 | } |
14218 | } |
14219 | } |
14220 | } |
14221 | |
14222 | NS_IMETHODIMPnsresult |
14223 | nsDocShell::OnStartRequest(nsIRequest* aRequest) { |
14224 | if (MOZ_UNLIKELY(MOZ_LOG_TEST(gSHIPBFCacheLog, LogLevel::Verbose))(__builtin_expect(!!((__builtin_expect(!!(mozilla::detail::log_test (gSHIPBFCacheLog, LogLevel::Verbose)), 0))), 0))) { |
14225 | nsAutoCString uri("[no uri]"); |
14226 | if (mCurrentURI) { |
14227 | uri = mCurrentURI->GetSpecOrDefault(); |
14228 | } |
14229 | nsAutoCString name; |
14230 | aRequest->GetName(name); |
14231 | MOZ_LOG(gSHIPBFCacheLog, LogLevel::Verbose,do { const ::mozilla::LogModule* moz_real_module = gSHIPBFCacheLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Verbose)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Verbose, "Adding request %s to loadgroup for %s", name.get(), uri.get()); } } while (0) |
14232 | ("Adding request %s to loadgroup for %s", name.get(), uri.get()))do { const ::mozilla::LogModule* moz_real_module = gSHIPBFCacheLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Verbose)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Verbose, "Adding request %s to loadgroup for %s", name.get(), uri.get()); } } while (0); |
14233 | } |
14234 | RecordSingleChannelId(true, aRequest); |
14235 | return nsDocLoader::OnStartRequest(aRequest); |
14236 | } |
14237 | |
14238 | NS_IMETHODIMPnsresult |
14239 | nsDocShell::OnStopRequest(nsIRequest* aRequest, nsresult aStatusCode) { |
14240 | if (MOZ_UNLIKELY(MOZ_LOG_TEST(gSHIPBFCacheLog, LogLevel::Verbose))(__builtin_expect(!!((__builtin_expect(!!(mozilla::detail::log_test (gSHIPBFCacheLog, LogLevel::Verbose)), 0))), 0))) { |
14241 | nsAutoCString uri("[no uri]"); |
14242 | if (mCurrentURI) { |
14243 | uri = mCurrentURI->GetSpecOrDefault(); |
14244 | } |
14245 | nsAutoCString name; |
14246 | aRequest->GetName(name); |
14247 | MOZ_LOG(do { const ::mozilla::LogModule* moz_real_module = gSHIPBFCacheLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Verbose)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Verbose, "Removing request %s from loadgroup for %s" , name.get(), uri.get()); } } while (0) |
14248 | gSHIPBFCacheLog, LogLevel::Verbose,do { const ::mozilla::LogModule* moz_real_module = gSHIPBFCacheLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Verbose)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Verbose, "Removing request %s from loadgroup for %s" , name.get(), uri.get()); } } while (0) |
14249 | ("Removing request %s from loadgroup for %s", name.get(), uri.get()))do { const ::mozilla::LogModule* moz_real_module = gSHIPBFCacheLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Verbose)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Verbose, "Removing request %s from loadgroup for %s" , name.get(), uri.get()); } } while (0); |
14250 | } |
14251 | RecordSingleChannelId(false, aRequest); |
14252 | return nsDocLoader::OnStopRequest(aRequest, aStatusCode); |
14253 | } |
14254 | |
14255 | void nsDocShell::MaybeDisconnectChildListenersOnPageHide() { |
14256 | MOZ_RELEASE_ASSERT(XRE_IsContentProcess())do { static_assert( mozilla::detail::AssertionConditionType< decltype(XRE_IsContentProcess())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(XRE_IsContentProcess()))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("XRE_IsContentProcess()" , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 14256); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "XRE_IsContentProcess()" ")"); do { MOZ_CrashSequence(__null, 14256); __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
14257 | |
14258 | if (mChannelToDisconnectOnPageHide != 0 && mLoadGroup) { |
14259 | nsCOMPtr<nsISimpleEnumerator> requests; |
14260 | mLoadGroup->GetRequests(getter_AddRefs(requests)); |
14261 | for (const auto& request : SimpleEnumerator<nsIRequest>(requests)) { |
14262 | RefPtr<DocumentChannel> channel = do_QueryObject(request); |
14263 | if (channel && channel->ChannelId() == mChannelToDisconnectOnPageHide) { |
14264 | static_cast<DocumentChannelChild*>(channel.get()) |
14265 | ->DisconnectChildListeners(NS_BINDING_ABORTED, NS_BINDING_ABORTED); |
14266 | } |
14267 | } |
14268 | mChannelToDisconnectOnPageHide = 0; |
14269 | } |
14270 | } |
14271 | |
14272 | bool nsDocShell::IsSameDocumentAsActiveEntry( |
14273 | const mozilla::dom::SessionHistoryInfo& aSHInfo) { |
14274 | return mActiveEntry ? mActiveEntry->SharesDocumentWith(aSHInfo) : false; |
14275 | } |
14276 | |
14277 | // https://html.spec.whatwg.org/#nav-window |
14278 | nsPIDOMWindowInner* nsDocShell::GetActiveWindow() { |
14279 | nsPIDOMWindowOuter* outer = GetWindow(); |
14280 | return outer ? outer->GetCurrentInnerWindow() : nullptr; |
14281 | } |
14282 | |
14283 | // https://html.spec.whatwg.org/#inform-the-navigation-api-about-aborting-navigation |
14284 | void nsDocShell::InformNavigationAPIAboutAbortingNavigation() { |
14285 | // Step 1 |
14286 | // This becomes an assert since we have a common event loop. |
14287 | MOZ_DIAGNOSTIC_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/root/firefox-clang/docshell/base/nsDocShell.cpp", 14287); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence(__null, 14287); __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
14288 | |
14289 | // No ongoing navigations if we don't have a window. |
14290 | RefPtr<nsPIDOMWindowInner> window = GetActiveWindow(); |
14291 | if (!window) { |
14292 | return; |
14293 | } |
14294 | |
14295 | // Step 2 |
14296 | RefPtr<Navigation> navigation = window->Navigation(); |
14297 | if (!navigation) { |
14298 | return; |
14299 | } |
14300 | |
14301 | // Step 3 |
14302 | if (!navigation->HasOngoingNavigateEvent()) { |
14303 | return; |
14304 | } |
14305 | |
14306 | AutoJSAPI jsapi; |
14307 | if (!jsapi.Init(navigation->GetOwnerGlobal())) { |
14308 | return; |
14309 | } |
14310 | |
14311 | // Step 4 |
14312 | navigation->AbortOngoingNavigation(jsapi.cx()); |
14313 | } |
14314 | |
14315 | // https://html.spec.whatwg.org/#set-the-ongoing-navigation |
14316 | void nsDocShell::SetOngoingNavigation( |
14317 | const Maybe<OngoingNavigation>& aOngoingNavigation) { |
14318 | // We currently only use #set-the-ongoing-navigation to call, |
14319 | // #inform-the-navigation-api-about-aborting-navigation, but really it should |
14320 | // be used for more. The spec keeps a piece of state on the navigable: |
14321 | // https://html.spec.whatwg.org/#ongoing-navigation. Spec uses it for several |
14322 | // things, for example right here in #set-the-ongoing-navigation to make sure |
14323 | // that we don't call #inform-the-navigation-api-about-aborting-navigation if |
14324 | // we're setting it to the same value. We currently only care about aborting |
14325 | // the currently firing navigate event. Also, in reality, this is very much |
14326 | // related to nsDocShell::GetIsAttemptingToNavigate() which is what we |
14327 | // currently use to determine if we need to stop an ongoing navigation in |
14328 | // Document::Open, whereas the spec checks if the ongoing navigation is a |
14329 | // NavigationID. |
14330 | |
14331 | // Step 1, with the exception that we assume setting the ongoing navigation to |
14332 | // an id always means a fresh id. |
14333 | if (aOngoingNavigation == mOngoingNavigation && |
14334 | aOngoingNavigation != Some(OngoingNavigation::NavigationID)) { |
14335 | return; |
14336 | } |
14337 | |
14338 | // Step 2 |
14339 | InformNavigationAPIAboutAbortingNavigation(); |
14340 | |
14341 | // Step 3 |
14342 | mOngoingNavigation = aOngoingNavigation; |
14343 | } |