File: | var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp |
Warning: | line 3397, 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 | |
11 | #ifdef XP_WIN |
12 | # include <process.h> |
13 | # define getpid _getpid |
14 | #else |
15 | # include <unistd.h> // for getpid() |
16 | #endif |
17 | |
18 | #include "mozilla/ArrayUtils.h" |
19 | #include "mozilla/Attributes.h" |
20 | #include "mozilla/AutoRestore.h" |
21 | #include "mozilla/BasePrincipal.h" |
22 | #include "mozilla/Casting.h" |
23 | #include "mozilla/CheckedInt.h" |
24 | #include "mozilla/Components.h" |
25 | #include "mozilla/DebugOnly.h" |
26 | #include "mozilla/Encoding.h" |
27 | #include "mozilla/EventStateManager.h" |
28 | #include "mozilla/HTMLEditor.h" |
29 | #include "mozilla/InputTaskManager.h" |
30 | #include "mozilla/LoadInfo.h" |
31 | #include "mozilla/Logging.h" |
32 | #include "mozilla/MediaFeatureChange.h" |
33 | #include "mozilla/Preferences.h" |
34 | #include "mozilla/PresShell.h" |
35 | #include "mozilla/ResultExtensions.h" |
36 | #include "mozilla/SchedulerGroup.h" |
37 | #include "mozilla/ScopeExit.h" |
38 | #include "mozilla/ScrollContainerFrame.h" |
39 | #include "mozilla/ScrollTypes.h" |
40 | #include "mozilla/SimpleEnumerator.h" |
41 | #include "mozilla/StaticPrefs_browser.h" |
42 | #include "mozilla/StaticPrefs_docshell.h" |
43 | #include "mozilla/StaticPrefs_dom.h" |
44 | #include "mozilla/StaticPrefs_extensions.h" |
45 | #include "mozilla/StaticPrefs_privacy.h" |
46 | #include "mozilla/StaticPrefs_security.h" |
47 | #include "mozilla/StaticPrefs_ui.h" |
48 | #include "mozilla/StaticPrefs_fission.h" |
49 | #include "mozilla/StartupTimeline.h" |
50 | #include "mozilla/StorageAccess.h" |
51 | #include "mozilla/StoragePrincipalHelper.h" |
52 | #include "mozilla/Telemetry.h" |
53 | |
54 | #include "mozilla/Unused.h" |
55 | #include "mozilla/WidgetUtils.h" |
56 | |
57 | #include "mozilla/dom/AutoEntryScript.h" |
58 | #include "mozilla/dom/ChildProcessChannelListener.h" |
59 | #include "mozilla/dom/ClientChannelHelper.h" |
60 | #include "mozilla/dom/ClientHandle.h" |
61 | #include "mozilla/dom/ClientInfo.h" |
62 | #include "mozilla/dom/ClientManager.h" |
63 | #include "mozilla/dom/ClientSource.h" |
64 | #include "mozilla/dom/ContentChild.h" |
65 | #include "mozilla/dom/ContentFrameMessageManager.h" |
66 | #include "mozilla/dom/DocGroup.h" |
67 | #include "mozilla/dom/Element.h" |
68 | #include "mozilla/dom/FragmentDirective.h" |
69 | #include "mozilla/dom/HTMLAnchorElement.h" |
70 | #include "mozilla/dom/HTMLIFrameElement.h" |
71 | #include "mozilla/dom/PerformanceNavigation.h" |
72 | #include "mozilla/dom/PermissionMessageUtils.h" |
73 | #include "mozilla/dom/PopupBlocker.h" |
74 | #include "mozilla/dom/ScreenOrientation.h" |
75 | #include "mozilla/dom/ScriptSettings.h" |
76 | #include "mozilla/dom/ServiceWorkerInterceptController.h" |
77 | #include "mozilla/dom/ServiceWorkerUtils.h" |
78 | #include "mozilla/dom/SessionHistoryEntry.h" |
79 | #include "mozilla/dom/SessionStorageManager.h" |
80 | #include "mozilla/dom/SessionStoreChangeListener.h" |
81 | #include "mozilla/dom/SessionStoreChild.h" |
82 | #include "mozilla/dom/SessionStoreUtils.h" |
83 | #include "mozilla/dom/BrowserChild.h" |
84 | #include "mozilla/dom/ToJSValue.h" |
85 | #include "mozilla/dom/UserActivation.h" |
86 | #include "mozilla/dom/ChildSHistory.h" |
87 | #include "mozilla/dom/nsCSPContext.h" |
88 | #include "mozilla/dom/nsHTTPSOnlyUtils.h" |
89 | #include "mozilla/dom/LoadURIOptionsBinding.h" |
90 | #include "mozilla/dom/JSWindowActorChild.h" |
91 | #include "mozilla/dom/DocumentBinding.h" |
92 | #include "mozilla/ipc/ProtocolUtils.h" |
93 | #include "mozilla/net/DocumentChannel.h" |
94 | #include "mozilla/net/DocumentChannelChild.h" |
95 | #include "mozilla/net/ParentChannelWrapper.h" |
96 | #include "mozilla/net/UrlClassifierFeatureFactory.h" |
97 | #include "ReferrerInfo.h" |
98 | |
99 | #include "nsIAuthPrompt.h" |
100 | #include "nsIAuthPrompt2.h" |
101 | #include "nsICachingChannel.h" |
102 | #include "nsICaptivePortalService.h" |
103 | #include "nsIChannel.h" |
104 | #include "nsIChannelEventSink.h" |
105 | #include "nsIClassOfService.h" |
106 | #include "nsIConsoleReportCollector.h" |
107 | #include "nsIContent.h" |
108 | #include "nsIContentInlines.h" |
109 | #include "nsIContentSecurityPolicy.h" |
110 | #include "nsIController.h" |
111 | #include "nsIDocShellTreeItem.h" |
112 | #include "nsIDocShellTreeOwner.h" |
113 | #include "nsIDocumentViewer.h" |
114 | #include "mozilla/dom/Document.h" |
115 | #include "nsHTMLDocument.h" |
116 | #include "nsIDocumentLoaderFactory.h" |
117 | #include "nsIDOMWindow.h" |
118 | #include "nsIEditingSession.h" |
119 | #include "nsIEffectiveTLDService.h" |
120 | #include "nsIExternalProtocolService.h" |
121 | #include "nsIFormPOSTActionChannel.h" |
122 | #include "nsIFrame.h" |
123 | #include "nsIGlobalObject.h" |
124 | #include "nsIHttpChannel.h" |
125 | #include "nsIHttpChannelInternal.h" |
126 | #include "nsIIDNService.h" |
127 | #include "nsIInputStreamChannel.h" |
128 | #include "nsIInterfaceRequestorUtils.h" |
129 | #include "nsILayoutHistoryState.h" |
130 | #include "nsILoadInfo.h" |
131 | #include "nsILoadURIDelegate.h" |
132 | #include "nsIMultiPartChannel.h" |
133 | #include "nsINestedURI.h" |
134 | #include "nsINetworkPredictor.h" |
135 | #include "nsINode.h" |
136 | #include "nsINSSErrorsService.h" |
137 | #include "nsIObserverService.h" |
138 | #include "nsIOService.h" |
139 | #include "nsIPrincipal.h" |
140 | #include "nsIPrivacyTransitionObserver.h" |
141 | #include "nsIPrompt.h" |
142 | #include "nsIPromptCollection.h" |
143 | #include "nsIPromptFactory.h" |
144 | #include "nsIPublicKeyPinningService.h" |
145 | #include "nsIReflowObserver.h" |
146 | #include "nsIScriptChannel.h" |
147 | #include "nsIScriptObjectPrincipal.h" |
148 | #include "nsIScriptSecurityManager.h" |
149 | #include "nsScriptSecurityManager.h" |
150 | #include "nsIScrollObserver.h" |
151 | #include "nsISupportsPrimitives.h" |
152 | #include "nsISecureBrowserUI.h" |
153 | #include "nsISeekableStream.h" |
154 | #include "nsISelectionDisplay.h" |
155 | #include "nsISHEntry.h" |
156 | #include "nsISiteSecurityService.h" |
157 | #include "nsISocketProvider.h" |
158 | #include "nsIStringBundle.h" |
159 | #include "nsIStructuredCloneContainer.h" |
160 | #include "nsIBrowserChild.h" |
161 | #include "nsITextToSubURI.h" |
162 | #include "nsITimedChannel.h" |
163 | #include "nsITimer.h" |
164 | #include "nsITransportSecurityInfo.h" |
165 | #include "nsIUploadChannel.h" |
166 | #include "nsIURIFixup.h" |
167 | #include "nsIURIMutator.h" |
168 | #include "nsIURILoader.h" |
169 | #include "nsIViewSourceChannel.h" |
170 | #include "nsIWebBrowserChrome.h" |
171 | #include "nsIWebBrowserFind.h" |
172 | #include "nsIWebProgress.h" |
173 | #include "nsIWidget.h" |
174 | #include "nsIWindowWatcher.h" |
175 | #include "nsIWritablePropertyBag2.h" |
176 | #include "nsIX509Cert.h" |
177 | #include "nsIXULRuntime.h" |
178 | |
179 | #include "nsCommandManager.h" |
180 | #include "nsPIDOMWindow.h" |
181 | #include "nsPIWindowRoot.h" |
182 | |
183 | #include "IHistory.h" |
184 | #include "IUrlClassifierUITelemetry.h" |
185 | |
186 | #include "nsArray.h" |
187 | #include "nsArrayUtils.h" |
188 | #include "nsCExternalHandlerService.h" |
189 | #include "nsContentDLF.h" |
190 | #include "nsContentPolicyUtils.h" // NS_CheckContentLoadPolicy(...) |
191 | #include "nsContentSecurityManager.h" |
192 | #include "nsContentSecurityUtils.h" |
193 | #include "nsContentUtils.h" |
194 | #include "nsCURILoader.h" |
195 | #include "nsDocShellCID.h" |
196 | #include "nsDocShellEditorData.h" |
197 | #include "nsDocShellEnumerator.h" |
198 | #include "nsDocShellLoadState.h" |
199 | #include "nsDocShellLoadTypes.h" |
200 | #include "nsDOMCID.h" |
201 | #include "nsDOMNavigationTiming.h" |
202 | #include "nsDSURIContentListener.h" |
203 | #include "nsEditingSession.h" |
204 | #include "nsError.h" |
205 | #include "nsEscape.h" |
206 | #include "nsFocusManager.h" |
207 | #include "nsGlobalWindowInner.h" |
208 | #include "nsGlobalWindowOuter.h" |
209 | #include "nsJSEnvironment.h" |
210 | #include "nsNetCID.h" |
211 | #include "nsNetUtil.h" |
212 | #include "nsObjectLoadingContent.h" |
213 | #include "nsPingListener.h" |
214 | #include "nsPoint.h" |
215 | #include "nsQueryObject.h" |
216 | #include "nsQueryActor.h" |
217 | #include "nsRect.h" |
218 | #include "nsRefreshTimer.h" |
219 | #include "nsSandboxFlags.h" |
220 | #include "nsSHEntry.h" |
221 | #include "nsSHistory.h" |
222 | #include "nsSHEntry.h" |
223 | #include "nsStructuredCloneContainer.h" |
224 | #include "nsSubDocumentFrame.h" |
225 | #include "nsURILoader.h" |
226 | #include "nsURLHelper.h" |
227 | #include "nsView.h" |
228 | #include "nsViewManager.h" |
229 | #include "nsViewSourceHandler.h" |
230 | #include "nsWebBrowserFind.h" |
231 | #include "nsWhitespaceTokenizer.h" |
232 | #include "nsWidgetsCID.h" |
233 | #include "nsXULAppAPI.h" |
234 | |
235 | #include "CertVerifier.h" |
236 | #include "ThirdPartyUtil.h" |
237 | #include "GeckoProfiler.h" |
238 | #include "mozilla/NullPrincipal.h" |
239 | #include "Navigator.h" |
240 | #include "prenv.h" |
241 | #include "mozilla/ipc/URIUtils.h" |
242 | #include "sslerr.h" |
243 | #include "mozpkix/pkix.h" |
244 | #include "NSSErrorsService.h" |
245 | |
246 | #include "nsDocShellTelemetryUtils.h" |
247 | |
248 | #ifdef MOZ_PLACES1 |
249 | # include "nsIFaviconService.h" |
250 | # include "mozIPlacesPendingOperation.h" |
251 | #endif |
252 | |
253 | #if NS_PRINT_PREVIEW1 |
254 | # include "nsIDocumentViewerPrint.h" |
255 | # include "nsIWebBrowserPrint.h" |
256 | #endif |
257 | |
258 | using namespace mozilla; |
259 | using namespace mozilla::dom; |
260 | using namespace mozilla::net; |
261 | |
262 | using mozilla::ipc::Endpoint; |
263 | |
264 | // Threshold value in ms for META refresh based redirects |
265 | #define REFRESH_REDIRECT_TIMER15000 15000 |
266 | |
267 | static mozilla::LazyLogModule gCharsetMenuLog("CharsetMenu"); |
268 | |
269 | #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) \ |
270 | 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) |
271 | |
272 | #ifdef DEBUG1 |
273 | unsigned long nsDocShell::gNumberOfDocShells = 0; |
274 | static uint64_t gDocshellIDCounter = 0; |
275 | |
276 | static mozilla::LazyLogModule gDocShellLog("nsDocShell"); |
277 | static mozilla::LazyLogModule gDocShellAndDOMWindowLeakLogging( |
278 | "DocShellAndDOMWindowLeak"); |
279 | #endif |
280 | static mozilla::LazyLogModule gDocShellLeakLog("nsDocShellLeak"); |
281 | extern mozilla::LazyLogModule gPageCacheLog; |
282 | mozilla::LazyLogModule gSHLog("SessionHistory"); |
283 | extern mozilla::LazyLogModule gSHIPBFCacheLog; |
284 | |
285 | const char kAppstringsBundleURL[] = |
286 | "chrome://global/locale/appstrings.properties"; |
287 | |
288 | static bool IsTopLevelDoc(BrowsingContext* aBrowsingContext, |
289 | nsILoadInfo* aLoadInfo) { |
290 | 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" , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 290); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aBrowsingContext" ")"); do { *((volatile int*)__null) = 290; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
291 | 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", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 291); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadInfo" ")" ); do { *((volatile int*)__null) = 291; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
292 | |
293 | if (aLoadInfo->GetExternalContentPolicyType() != |
294 | ExtContentPolicy::TYPE_DOCUMENT) { |
295 | return false; |
296 | } |
297 | |
298 | return aBrowsingContext->IsTopContent(); |
299 | } |
300 | |
301 | // True if loading for top level document loading in active tab. |
302 | static bool IsUrgentStart(BrowsingContext* aBrowsingContext, |
303 | nsILoadInfo* aLoadInfo, uint32_t aLoadType) { |
304 | 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" , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 304); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aBrowsingContext" ")"); do { *((volatile int*)__null) = 304; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
305 | 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", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 305); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadInfo" ")" ); do { *((volatile int*)__null) = 305; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
306 | |
307 | if (!IsTopLevelDoc(aBrowsingContext, aLoadInfo)) { |
308 | return false; |
309 | } |
310 | |
311 | if (aLoadType & |
312 | (nsIDocShell::LOAD_CMD_NORMAL | nsIDocShell::LOAD_CMD_HISTORY)) { |
313 | return true; |
314 | } |
315 | |
316 | return aBrowsingContext->IsActive(); |
317 | } |
318 | |
319 | nsDocShell::nsDocShell(BrowsingContext* aBrowsingContext, |
320 | uint64_t aContentWindowID) |
321 | : nsDocLoader(true), |
322 | mContentWindowID(aContentWindowID), |
323 | mBrowsingContext(aBrowsingContext), |
324 | mParentCharset(nullptr), |
325 | mTreeOwner(nullptr), |
326 | mScrollbarPref(ScrollbarPreference::Auto), |
327 | mCharsetReloadState(eCharsetReloadInit), |
328 | mParentCharsetSource(0), |
329 | mFrameMargins(-1, -1), |
330 | mItemType(aBrowsingContext->IsContent() ? typeContent : typeChrome), |
331 | mPreviousEntryIndex(-1), |
332 | mLoadedEntryIndex(-1), |
333 | mBusyFlags(BUSY_FLAGS_NONE), |
334 | mAppType(nsIDocShell::APP_TYPE_UNKNOWN), |
335 | mLoadType(0), |
336 | mFailedLoadType(0), |
337 | mChannelToDisconnectOnPageHide(0), |
338 | mCreatingDocument(false), |
339 | #ifdef DEBUG1 |
340 | mInEnsureScriptEnv(false), |
341 | #endif |
342 | mInitialized(false), |
343 | mAllowSubframes(true), |
344 | mAllowMetaRedirects(true), |
345 | mAllowImages(true), |
346 | mAllowMedia(true), |
347 | mAllowDNSPrefetch(true), |
348 | mAllowWindowControl(true), |
349 | mCSSErrorReportingEnabled(false), |
350 | mAllowAuth(mItemType == typeContent), |
351 | mAllowKeywordFixup(false), |
352 | mDisableMetaRefreshWhenInactive(false), |
353 | mWindowDraggingAllowed(false), |
354 | mInFrameSwap(false), |
355 | mFiredUnloadEvent(false), |
356 | mEODForCurrentDocument(false), |
357 | mURIResultedInDocument(false), |
358 | mIsBeingDestroyed(false), |
359 | mIsExecutingOnLoadHandler(false), |
360 | mSavingOldViewer(false), |
361 | mInvisible(false), |
362 | mHasLoadedNonBlankURI(false), |
363 | mBlankTiming(false), |
364 | mTitleValidForCurrentURI(false), |
365 | mWillChangeProcess(false), |
366 | mIsNavigating(false), |
367 | mForcedAutodetection(false), |
368 | mCheckingSessionHistory(false), |
369 | mNeedToReportActiveAfterLoadingBecomesActive(false) { |
370 | // If no outer window ID was provided, generate a new one. |
371 | if (aContentWindowID == 0) { |
372 | mContentWindowID = nsContentUtils::GenerateWindowId(); |
373 | } |
374 | |
375 | 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); |
376 | |
377 | #ifdef DEBUG1 |
378 | mDocShellID = gDocshellIDCounter++; |
379 | // We're counting the number of |nsDocShells| to help find leaks |
380 | ++gNumberOfDocShells; |
381 | 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) |
382 | ("++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) |
383 | 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); |
384 | #endif |
385 | } |
386 | |
387 | nsDocShell::~nsDocShell() { |
388 | // Avoid notifying observers while we're in the dtor. |
389 | mIsBeingDestroyed = true; |
390 | |
391 | Destroy(); |
392 | |
393 | if (mDocumentViewer) { |
394 | mDocumentViewer->Close(nullptr); |
395 | mDocumentViewer->Destroy(); |
396 | mDocumentViewer = nullptr; |
397 | } |
398 | |
399 | 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); |
400 | |
401 | #ifdef DEBUG1 |
402 | if (MOZ_LOG_TEST(gDocShellAndDOMWindowLeakLogging, LogLevel::Info)(__builtin_expect(!!(mozilla::detail::log_test(gDocShellAndDOMWindowLeakLogging , LogLevel::Info)), 0))) { |
403 | nsAutoCString url; |
404 | if (mLastOpenedURI) { |
405 | url = mLastOpenedURI->GetSpecOrDefault(); |
406 | |
407 | // Data URLs can be very long, so truncate to avoid flooding the log. |
408 | const uint32_t maxURLLength = 1000; |
409 | if (url.Length() > maxURLLength) { |
410 | url.Truncate(maxURLLength); |
411 | } |
412 | } |
413 | |
414 | // We're counting the number of |nsDocShells| to help find leaks |
415 | --gNumberOfDocShells; |
416 | 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) |
417 | 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) |
418 | ("--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) |
419 | (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); |
420 | } |
421 | #endif |
422 | } |
423 | |
424 | bool nsDocShell::Initialize() { |
425 | if (mInitialized) { |
426 | // We've already been initialized. |
427 | return true; |
428 | } |
429 | |
430 | 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", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 431); MOZ_PretendNoReturn(); } } while (0) |
431 | "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", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 431); MOZ_PretendNoReturn(); } } while (0); |
432 | |
433 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 433); return false; } } while (false); |
434 | mInitialized = true; |
435 | |
436 | mDisableMetaRefreshWhenInactive = |
437 | Preferences::GetBool("browser.meta_refresh_when_inactive.disabled", |
438 | mDisableMetaRefreshWhenInactive); |
439 | |
440 | if (nsCOMPtr<nsIObserverService> serv = services::GetObserverService()) { |
441 | const char* msg = mItemType == typeContent ? NS_WEBNAVIGATION_CREATE"webnavigation-create" |
442 | : NS_CHROME_WEBNAVIGATION_CREATE"chrome-webnavigation-create"; |
443 | serv->NotifyWhenScriptSafe(GetAsSupports(this), msg, nullptr); |
444 | } |
445 | |
446 | return true; |
447 | } |
448 | |
449 | /* static */ |
450 | already_AddRefed<nsDocShell> nsDocShell::Create( |
451 | BrowsingContext* aBrowsingContext, uint64_t aContentWindowID) { |
452 | 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!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 452); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aBrowsingContext" ") (" "DocShell without a BrowsingContext!" ")"); do { *((volatile int*)__null) = 452; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
453 | |
454 | nsresult rv; |
455 | RefPtr<nsDocShell> ds = new nsDocShell(aBrowsingContext, aContentWindowID); |
456 | |
457 | // Initialize the underlying nsDocLoader. |
458 | rv = ds->nsDocLoader::InitWithBrowsingContext(aBrowsingContext); |
459 | if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv )), 0))), "NS_FAILED(rv)", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 459)) { |
460 | return nullptr; |
461 | } |
462 | |
463 | // Create our ContentListener |
464 | ds->mContentListener = new nsDSURIContentListener(ds); |
465 | |
466 | // We enable if we're in the parent process in order to support non-e10s |
467 | // configurations. |
468 | // Note: This check is duplicated in SharedWorkerInterfaceRequestor's |
469 | // constructor. |
470 | if (XRE_IsParentProcess()) { |
471 | ds->mInterceptController = new ServiceWorkerInterceptController(); |
472 | } |
473 | |
474 | // We want to hold a strong ref to the loadgroup, so it better hold a weak |
475 | // ref to us... use an InterfaceRequestorProxy to do this. |
476 | nsCOMPtr<nsIInterfaceRequestor> proxy = new InterfaceRequestorProxy(ds); |
477 | ds->mLoadGroup->SetNotificationCallbacks(proxy); |
478 | |
479 | // XXX(nika): We have our BrowsingContext, so we might be able to skip this. |
480 | // It could be nice to directly set up our DocLoader tree? |
481 | rv = nsDocLoader::AddDocLoaderAsChildOfRoot(ds); |
482 | if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv )), 0))), "NS_FAILED(rv)", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 482)) { |
483 | return nullptr; |
484 | } |
485 | |
486 | // Add |ds| as a progress listener to itself. A little weird, but simpler |
487 | // than reproducing all the listener-notification logic in overrides of the |
488 | // various methods via which nsDocLoader can be notified. Note that this |
489 | // holds an nsWeakPtr to |ds|, so it's ok. |
490 | rv = ds->AddProgressListener(ds, nsIWebProgress::NOTIFY_STATE_DOCUMENT | |
491 | nsIWebProgress::NOTIFY_STATE_NETWORK | |
492 | nsIWebProgress::NOTIFY_LOCATION); |
493 | if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv )), 0))), "NS_FAILED(rv)", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 493)) { |
494 | return nullptr; |
495 | } |
496 | |
497 | // If our BrowsingContext has private browsing enabled, update the number of |
498 | // private browsing docshells. |
499 | if (aBrowsingContext->UsePrivateBrowsing()) { |
500 | ds->NotifyPrivateBrowsingChanged(); |
501 | } |
502 | |
503 | // If our parent window is present in this process, set up our parent now. |
504 | RefPtr<WindowContext> parentWC = aBrowsingContext->GetParentWindowContext(); |
505 | if (parentWC && parentWC->IsInProcess()) { |
506 | // If we don't have a parent element anymore, we can't finish this load! |
507 | // How'd we get here? |
508 | RefPtr<Element> parentElement = aBrowsingContext->GetEmbedderElement(); |
509 | if (!parentElement) { |
510 | 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 510); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: " "nsDocShell::Create() - !parentElement" ")"); do { *((volatile int*)__null) = 510; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
511 | return nullptr; |
512 | } |
513 | |
514 | // We have an in-process parent window, but don't have a parent nsDocShell? |
515 | // How'd we get here! |
516 | nsCOMPtr<nsIDocShell> parentShell = |
517 | parentElement->OwnerDoc()->GetDocShell(); |
518 | if (!parentShell) { |
519 | 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 519); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: " "nsDocShell::Create() - !parentShell" ")"); do { *((volatile int*)__null) = 519; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
520 | return nullptr; |
521 | } |
522 | parentShell->AddChild(ds); |
523 | } |
524 | |
525 | // Make |ds| the primary DocShell for the given context. |
526 | aBrowsingContext->SetDocShell(ds); |
527 | |
528 | // Set |ds| default load flags on load group. |
529 | ds->SetLoadGroupDefaultLoadFlags(aBrowsingContext->GetDefaultLoadFlags()); |
530 | |
531 | if (XRE_IsParentProcess()) { |
532 | aBrowsingContext->Canonical()->MaybeAddAsProgressListener(ds); |
533 | } |
534 | |
535 | return ds.forget(); |
536 | } |
537 | |
538 | void nsDocShell::DestroyChildren() { |
539 | for (auto* child : mChildList.ForwardRange()) { |
540 | nsCOMPtr<nsIDocShellTreeItem> shell = do_QueryObject(child); |
541 | NS_ASSERTION(shell, "docshell has null child")do { if (!(shell)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "docshell has null child" , "shell", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 541); MOZ_PretendNoReturn(); } } while (0); |
542 | |
543 | if (shell) { |
544 | shell->SetTreeOwner(nullptr); |
545 | } |
546 | } |
547 | |
548 | nsDocLoader::DestroyChildren(); |
549 | } |
550 | |
551 | 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); 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); (void)tmp; return NS_OK; } |
552 | 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); 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); (void)tmp; return NS_OK; } |
553 | 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); 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); (void)tmp; return NS_OK; } |
554 | 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); 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); (void)tmp; return NS_OK; } |
555 | |
556 | 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; } |
557 | 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; } |
558 | |
559 | 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", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 559); MOZ_PretendNoReturn(); } } while (0); nsISupports* foundInterface ; if (TopThreeWordsEquals( aIID, (nsXPCOMCycleCollectionParticipant ::COMTypeInfo<nsXPCOMCycleCollectionParticipant, void>:: kIID), (nsCycleCollectionISupports::COMTypeInfo<nsCycleCollectionISupports , void>::kIID)) && (LowWordEquals(aIID, (nsXPCOMCycleCollectionParticipant ::COMTypeInfo<nsXPCOMCycleCollectionParticipant, void>:: kIID)) || LowWordEquals(aIID, (nsCycleCollectionISupports::COMTypeInfo <nsCycleCollectionISupports, void>::kIID)))) { if (LowWordEquals (aIID, (nsXPCOMCycleCollectionParticipant::COMTypeInfo<nsXPCOMCycleCollectionParticipant , void>::kIID))) { *aInstancePtr = nsDocShell::cycleCollection ::GetParticipant(); return NS_OK; } if (LowWordEquals(aIID, ( nsCycleCollectionISupports::COMTypeInfo<nsCycleCollectionISupports , void>::kIID))) { *aInstancePtr = nsDocShell::cycleCollection ::Upcast(this); return NS_OK; } foundInterface = nullptr; } else |
560 | NS_INTERFACE_MAP_ENTRY(nsIDocShell)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t <decltype(*this)>, nsIDocShell>)) foundInterface = static_cast <nsIDocShell*>(this); else |
561 | NS_INTERFACE_MAP_ENTRY(nsIDocShellTreeItem)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t <decltype(*this)>, nsIDocShellTreeItem>)) foundInterface = static_cast<nsIDocShellTreeItem*>(this); else |
562 | NS_INTERFACE_MAP_ENTRY(nsIWebNavigation)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t <decltype(*this)>, nsIWebNavigation>)) foundInterface = static_cast<nsIWebNavigation*>(this); else |
563 | NS_INTERFACE_MAP_ENTRY(nsIBaseWindow)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t <decltype(*this)>, nsIBaseWindow>)) foundInterface = static_cast<nsIBaseWindow*>(this); else |
564 | NS_INTERFACE_MAP_ENTRY(nsIRefreshURI)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t <decltype(*this)>, nsIRefreshURI>)) foundInterface = static_cast<nsIRefreshURI*>(this); else |
565 | NS_INTERFACE_MAP_ENTRY(nsIWebProgressListener)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t <decltype(*this)>, nsIWebProgressListener>)) foundInterface = static_cast<nsIWebProgressListener*>(this); else |
566 | NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t <decltype(*this)>, nsISupportsWeakReference>)) foundInterface = static_cast<nsISupportsWeakReference*>(this); else |
567 | NS_INTERFACE_MAP_ENTRY(nsIWebPageDescriptor)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t <decltype(*this)>, nsIWebPageDescriptor>)) foundInterface = static_cast<nsIWebPageDescriptor*>(this); else |
568 | NS_INTERFACE_MAP_ENTRY(nsIAuthPromptProvider)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t <decltype(*this)>, nsIAuthPromptProvider>)) foundInterface = static_cast<nsIAuthPromptProvider*>(this); else |
569 | NS_INTERFACE_MAP_ENTRY(nsILoadContext)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t <decltype(*this)>, nsILoadContext>)) foundInterface = static_cast<nsILoadContext*>(this); else |
570 | 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 |
571 | mInterceptController)if ((mInterceptController) && aIID.Equals(mozilla::detail ::kImplementedIID<std::remove_reference_t<decltype(*this )>, nsINetworkInterceptController>)) foundInterface = static_cast <nsINetworkInterceptController*>(this); else |
572 | 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; } |
573 | |
574 | NS_IMETHODIMPnsresult |
575 | nsDocShell::GetInterface(const nsIID& aIID, void** aSink) { |
576 | 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 576); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aSink" ") (" "null out param" ")"); do { *((volatile int*)__null) = 576; __attribute__ ((nomerge)) ::abort(); } while (false); } } while (false); |
577 | |
578 | *aSink = nullptr; |
579 | |
580 | if (aIID.Equals(NS_GET_IID(nsICommandManager)(nsICommandManager::COMTypeInfo<nsICommandManager, void> ::kIID))) { |
581 | 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 , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 581); return NS_ERROR_FAILURE; } } while (false); |
582 | *aSink = static_cast<nsICommandManager*>(mCommandManager.get()); |
583 | } else if (aIID.Equals(NS_GET_IID(nsIURIContentListener)(nsIURIContentListener::COMTypeInfo<nsIURIContentListener, void>::kIID))) { |
584 | *aSink = mContentListener; |
585 | } else if ((aIID.Equals(NS_GET_IID(nsIScriptGlobalObject)(nsIScriptGlobalObject::COMTypeInfo<nsIScriptGlobalObject, void>::kIID)) || |
586 | aIID.Equals(NS_GET_IID(nsIGlobalObject)(nsIGlobalObject::COMTypeInfo<nsIGlobalObject, void>::kIID )) || |
587 | aIID.Equals(NS_GET_IID(nsPIDOMWindowOuter)(nsPIDOMWindowOuter::COMTypeInfo<nsPIDOMWindowOuter, void> ::kIID)) || |
588 | aIID.Equals(NS_GET_IID(mozIDOMWindowProxy)(mozIDOMWindowProxy::COMTypeInfo<mozIDOMWindowProxy, void> ::kIID)) || |
589 | aIID.Equals(NS_GET_IID(nsIDOMWindow)(nsIDOMWindow::COMTypeInfo<nsIDOMWindow, void>::kIID))) && |
590 | NS_SUCCEEDED(EnsureScriptEnvironment())((bool)(__builtin_expect(!!(!NS_FAILED_impl(EnsureScriptEnvironment ())), 1)))) { |
591 | return mScriptGlobal->QueryInterface(aIID, aSink); |
592 | } else if (aIID.Equals(NS_GET_IID(Document)(Document::COMTypeInfo<Document, void>::kIID)) && |
593 | NS_SUCCEEDED(EnsureDocumentViewer())((bool)(__builtin_expect(!!(!NS_FAILED_impl(EnsureDocumentViewer ())), 1)))) { |
594 | RefPtr<Document> doc = mDocumentViewer->GetDocument(); |
595 | doc.forget(aSink); |
596 | return *aSink ? NS_OK : NS_NOINTERFACE; |
597 | } else if (aIID.Equals(NS_GET_IID(nsIPrompt)(nsIPrompt::COMTypeInfo<nsIPrompt, void>::kIID)) && |
598 | NS_SUCCEEDED(EnsureScriptEnvironment())((bool)(__builtin_expect(!!(!NS_FAILED_impl(EnsureScriptEnvironment ())), 1)))) { |
599 | nsresult rv; |
600 | nsCOMPtr<nsIWindowWatcher> wwatch = |
601 | do_GetService(NS_WINDOWWATCHER_CONTRACTID"@mozilla.org/embedcomp/window-watcher;1", &rv); |
602 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 602); return rv; } } while (false); |
603 | |
604 | // Get the an auth prompter for our window so that the parenting |
605 | // of the dialogs works as it should when using tabs. |
606 | nsIPrompt* prompt; |
607 | rv = wwatch->GetNewPrompter(mScriptGlobal, &prompt); |
608 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 608); return rv; } } while (false); |
609 | |
610 | *aSink = prompt; |
611 | return NS_OK; |
612 | } else if (aIID.Equals(NS_GET_IID(nsIAuthPrompt)(nsIAuthPrompt::COMTypeInfo<nsIAuthPrompt, void>::kIID)) || |
613 | aIID.Equals(NS_GET_IID(nsIAuthPrompt2)(nsIAuthPrompt2::COMTypeInfo<nsIAuthPrompt2, void>::kIID ))) { |
614 | return NS_SUCCEEDED(GetAuthPrompt(PROMPT_NORMAL, aIID, aSink))((bool)(__builtin_expect(!!(!NS_FAILED_impl(GetAuthPrompt(PROMPT_NORMAL , aIID, aSink))), 1))) |
615 | ? NS_OK |
616 | : NS_NOINTERFACE; |
617 | } else if (aIID.Equals(NS_GET_IID(nsISHistory)(nsISHistory::COMTypeInfo<nsISHistory, void>::kIID))) { |
618 | // This is deprecated, you should instead directly get |
619 | // ChildSHistory from the browsing context. |
620 | 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 621); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false" ") (" "Do not try to get a nsISHistory interface from nsIDocShell" ")"); do { *((volatile int*)__null) = 621; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
621 | 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 621); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false" ") (" "Do not try to get a nsISHistory interface from nsIDocShell" ")"); do { *((volatile int*)__null) = 621; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
622 | return NS_NOINTERFACE; |
623 | } else if (aIID.Equals(NS_GET_IID(nsIWebBrowserFind)(nsIWebBrowserFind::COMTypeInfo<nsIWebBrowserFind, void> ::kIID))) { |
624 | nsresult rv = EnsureFind(); |
625 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
626 | return rv; |
627 | } |
628 | |
629 | *aSink = mFind; |
630 | NS_ADDREF((nsISupports*)*aSink)((nsISupports*)*aSink)->AddRef(); |
631 | return NS_OK; |
632 | } else if (aIID.Equals(NS_GET_IID(nsISelectionDisplay)(nsISelectionDisplay::COMTypeInfo<nsISelectionDisplay, void >::kIID))) { |
633 | if (PresShell* presShell = GetPresShell()) { |
634 | return presShell->QueryInterface(aIID, aSink); |
635 | } |
636 | } else if (aIID.Equals(NS_GET_IID(nsIDocShellTreeOwner)(nsIDocShellTreeOwner::COMTypeInfo<nsIDocShellTreeOwner, void >::kIID))) { |
637 | nsCOMPtr<nsIDocShellTreeOwner> treeOwner; |
638 | nsresult rv = GetTreeOwner(getter_AddRefs(treeOwner)); |
639 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && treeOwner) { |
640 | return treeOwner->QueryInterface(aIID, aSink); |
641 | } |
642 | } else if (aIID.Equals(NS_GET_IID(nsIBrowserChild)(nsIBrowserChild::COMTypeInfo<nsIBrowserChild, void>::kIID ))) { |
643 | *aSink = GetBrowserChild().take(); |
644 | return *aSink ? NS_OK : NS_ERROR_FAILURE; |
645 | } else { |
646 | return nsDocLoader::GetInterface(aIID, aSink); |
647 | } |
648 | |
649 | NS_IF_ADDREF(((nsISupports*)*aSink))ns_if_addref(((nsISupports*)*aSink)); |
650 | return *aSink ? NS_OK : NS_NOINTERFACE; |
651 | } |
652 | |
653 | NS_IMETHODIMPnsresult |
654 | nsDocShell::SetCancelContentJSEpoch(int32_t aEpoch) { |
655 | // Note: this gets called fairly early (before a pageload actually starts). |
656 | // We could probably defer this even longer. |
657 | nsCOMPtr<nsIBrowserChild> browserChild = GetBrowserChild(); |
658 | static_cast<BrowserChild*>(browserChild.get()) |
659 | ->SetCancelContentJSEpoch(aEpoch); |
660 | return NS_OK; |
661 | } |
662 | |
663 | nsresult nsDocShell::CheckDisallowedJavascriptLoad( |
664 | nsDocShellLoadState* aLoadState) { |
665 | if (!net::SchemeIsJavascript(aLoadState->URI())) { |
666 | return NS_OK; |
667 | } |
668 | |
669 | if (nsCOMPtr<nsIPrincipal> targetPrincipal = |
670 | GetInheritedPrincipal(/* aConsiderCurrentDocument */ true)) { |
671 | if (!aLoadState->TriggeringPrincipal()->Subsumes(targetPrincipal)) { |
672 | return NS_ERROR_DOM_BAD_CROSS_ORIGIN_URI; |
673 | } |
674 | return NS_OK; |
675 | } |
676 | return NS_ERROR_DOM_BAD_CROSS_ORIGIN_URI; |
677 | } |
678 | |
679 | NS_IMETHODIMPnsresult |
680 | nsDocShell::LoadURI(nsDocShellLoadState* aLoadState, bool aSetNavigating) { |
681 | return LoadURI(aLoadState, aSetNavigating, false); |
682 | } |
683 | |
684 | nsresult nsDocShell::LoadURI(nsDocShellLoadState* aLoadState, |
685 | bool aSetNavigating, |
686 | bool aContinueHandlingSubframeHistory) { |
687 | 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!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 687); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState" ") (" "Must have a valid load state!" ")"); do { *((volatile int*) __null) = 687; __attribute__((nomerge)) ::abort(); } while (false ); } } while (false); |
688 | // NOTE: This comparison between what appears to be internal/external load |
689 | // flags is intentional, as it's ensuring that the caller isn't using any of |
690 | // the flags reserved for implementations by the `nsIWebNavigation` interface. |
691 | // In the future, this check may be dropped. |
692 | 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 694); AnnotateMozCrashReason("MOZ_ASSERT" "(" "(aLoadState->LoadFlags() & INTERNAL_LOAD_FLAGS_LOADURI_SETUP_FLAGS) == 0" ") (" "Should not have these flags set" ")"); do { *((volatile int*)__null) = 694; __attribute__((nomerge)) ::abort(); } while (false); } } while (false) |
693 | (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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 694); AnnotateMozCrashReason("MOZ_ASSERT" "(" "(aLoadState->LoadFlags() & INTERNAL_LOAD_FLAGS_LOADURI_SETUP_FLAGS) == 0" ") (" "Should not have these flags set" ")"); do { *((volatile int*)__null) = 694; __attribute__((nomerge)) ::abort(); } while (false); } } while (false) |
694 | "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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 694); AnnotateMozCrashReason("MOZ_ASSERT" "(" "(aLoadState->LoadFlags() & INTERNAL_LOAD_FLAGS_LOADURI_SETUP_FLAGS) == 0" ") (" "Should not have these flags set" ")"); do { *((volatile int*)__null) = 694; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
695 | 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 696); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->TargetBrowsingContext().IsNull()" ") (" "Targeting doesn't occur until InternalLoad" ")"); do { *((volatile int*)__null) = 696; __attribute__((nomerge)) ::abort (); } while (false); } } while (false) |
696 | "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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 696); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->TargetBrowsingContext().IsNull()" ") (" "Targeting doesn't occur until InternalLoad" ")"); do { *((volatile int*)__null) = 696; __attribute__((nomerge)) ::abort (); } while (false); } } while (false); |
697 | |
698 | if (!aLoadState->TriggeringPrincipal()) { |
699 | 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 699); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "LoadURI must have a triggering principal" ")"); do { *((volatile int*)__null) = 699; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
700 | return NS_ERROR_FAILURE; |
701 | } |
702 | |
703 | MOZ_TRY(CheckDisallowedJavascriptLoad(aLoadState))do { auto mozTryTempResult_ = ::mozilla::ToResult(CheckDisallowedJavascriptLoad (aLoadState)); if ((__builtin_expect(!!(mozTryTempResult_.isErr ()), 0))) { return mozTryTempResult_.propagateErr(); } } while (0); |
704 | |
705 | bool oldIsNavigating = mIsNavigating; |
706 | auto cleanupIsNavigating = |
707 | MakeScopeExit([&]() { mIsNavigating = oldIsNavigating; }); |
708 | if (aSetNavigating) { |
709 | mIsNavigating = true; |
710 | } |
711 | |
712 | PopupBlocker::PopupControlState popupState = PopupBlocker::openOverridden; |
713 | if (aLoadState->HasLoadFlags(LOAD_FLAGS_ALLOW_POPUPS)) { |
714 | popupState = PopupBlocker::openAllowed; |
715 | // If we allow popups as part of the navigation, ensure we fake a user |
716 | // interaction, so that popups can, in fact, be allowed to open. |
717 | if (WindowContext* wc = mBrowsingContext->GetCurrentWindowContext()) { |
718 | wc->NotifyUserGestureActivation(); |
719 | } |
720 | } |
721 | |
722 | AutoPopupStatePusherAutoPopupStatePusherInternal statePusher(popupState); |
723 | |
724 | if (aLoadState->GetCancelContentJSEpoch().isSome()) { |
725 | SetCancelContentJSEpoch(*aLoadState->GetCancelContentJSEpoch()); |
726 | } |
727 | |
728 | // Note: we allow loads to get through here even if mFiredUnloadEvent is |
729 | // true; that case will get handled in LoadInternal or LoadHistoryEntry, |
730 | // so we pass false as the second parameter to IsNavigationAllowed. |
731 | // However, we don't allow the page to change location *in the middle of* |
732 | // firing beforeunload, so we do need to check if *beforeunload* is currently |
733 | // firing, so we call IsNavigationAllowed rather than just IsPrintingOrPP. |
734 | if (!IsNavigationAllowed(true, false)) { |
735 | return NS_OK; // JS may not handle returning of an error code |
736 | } |
737 | |
738 | nsLoadFlags defaultLoadFlags = mBrowsingContext->GetDefaultLoadFlags(); |
739 | if (aLoadState->HasLoadFlags(LOAD_FLAGS_FORCE_TRR)) { |
740 | defaultLoadFlags |= nsIRequest::LOAD_TRR_ONLY_MODE; |
741 | } else if (aLoadState->HasLoadFlags(LOAD_FLAGS_DISABLE_TRR)) { |
742 | defaultLoadFlags |= nsIRequest::LOAD_TRR_DISABLED_MODE; |
743 | } |
744 | |
745 | MOZ_ALWAYS_SUCCEEDS(mBrowsingContext->SetDefaultLoadFlags(defaultLoadFlags))do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl (mBrowsingContext->SetDefaultLoadFlags(defaultLoadFlags))) , 1)))), 1))) { } else { do { static_assert( mozilla::detail:: AssertionConditionType<decltype(false)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("false" " (" "NS_SUCCEEDED(mBrowsingContext->SetDefaultLoadFlags(defaultLoadFlags))" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 745); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false" ") (" "NS_SUCCEEDED(mBrowsingContext->SetDefaultLoadFlags(defaultLoadFlags))" ")"); do { *((volatile int*)__null) = 745; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); |
746 | |
747 | if (!StartupTimeline::HasRecord(StartupTimeline::FIRST_LOAD_URI) && |
748 | mItemType == typeContent && !NS_IsAboutBlank(aLoadState->URI())) { |
749 | StartupTimeline::RecordOnce(StartupTimeline::FIRST_LOAD_URI); |
750 | } |
751 | |
752 | // LoadType used to be set to a default value here, if no LoadInfo/LoadState |
753 | // object was passed in. That functionality has been removed as of bug |
754 | // 1492648. LoadType should now be set up by the caller at the time they |
755 | // create their nsDocShellLoadState object to pass into LoadURI. |
756 | |
757 | 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) |
758 | 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) |
759 | ("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) |
760 | 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); |
761 | |
762 | if ((!aLoadState->LoadIsFromSessionHistory() && |
763 | !LOAD_TYPE_HAS_FLAGS(aLoadState->LoadType(),((aLoadState->LoadType()) & ((LOAD_FLAGS_REPLACE_HISTORY ) << 16)) |
764 | LOAD_FLAGS_REPLACE_HISTORY)((aLoadState->LoadType()) & ((LOAD_FLAGS_REPLACE_HISTORY ) << 16))) || |
765 | aContinueHandlingSubframeHistory) { |
766 | // This is possibly a subframe, so handle it accordingly. |
767 | // |
768 | // If history exists, it will be loaded into the aLoadState object, and the |
769 | // LoadType will be changed. |
770 | if (MaybeHandleSubframeHistory(aLoadState, |
771 | aContinueHandlingSubframeHistory)) { |
772 | // MaybeHandleSubframeHistory returns true if we need to continue loading |
773 | // asynchronously. |
774 | return NS_OK; |
775 | } |
776 | } |
777 | |
778 | if (aLoadState->LoadIsFromSessionHistory()) { |
779 | 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) |
780 | ("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); |
781 | |
782 | if (!mozilla::SessionHistoryInParent()) { |
783 | nsCOMPtr<nsISHEntry> entry = aLoadState->SHEntry(); |
784 | return LoadHistoryEntry(entry, aLoadState->LoadType(), |
785 | aLoadState->HasValidUserGestureActivation()); |
786 | } |
787 | |
788 | // FIXME Null check aLoadState->GetLoadingSessionHistoryInfo()? |
789 | return LoadHistoryEntry(*aLoadState->GetLoadingSessionHistoryInfo(), |
790 | aLoadState->LoadType(), |
791 | aLoadState->HasValidUserGestureActivation()); |
792 | } |
793 | |
794 | // On history navigation via Back/Forward buttons, don't execute |
795 | // automatic JavaScript redirection such as |location.href = ...| or |
796 | // |window.open()| |
797 | // |
798 | // LOAD_NORMAL: window.open(...) etc. |
799 | // LOAD_STOP_CONTENT: location.href = ..., location.assign(...) |
800 | if ((aLoadState->LoadType() == LOAD_NORMAL || |
801 | aLoadState->LoadType() == LOAD_STOP_CONTENT) && |
802 | ShouldBlockLoadingForBackButton()) { |
803 | return NS_OK; |
804 | } |
805 | |
806 | BrowsingContext::Type bcType = mBrowsingContext->GetType(); |
807 | |
808 | // Set up the inheriting principal in LoadState. |
809 | nsresult rv = aLoadState->SetupInheritingPrincipal( |
810 | bcType, mBrowsingContext->OriginAttributesRef()); |
811 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 811); return rv; } } while (false); |
812 | |
813 | rv = aLoadState->SetupTriggeringPrincipal( |
814 | mBrowsingContext->OriginAttributesRef()); |
815 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 815); return rv; } } while (false); |
816 | |
817 | aLoadState->CalculateLoadURIFlags(); |
818 | |
819 | 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 820); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->TypeHint().IsVoid()" ") (" "Typehint should be null when calling InternalLoad from LoadURI" ")"); do { *((volatile int*)__null) = 820; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
820 | "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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 820); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->TypeHint().IsVoid()" ") (" "Typehint should be null when calling InternalLoad from LoadURI" ")"); do { *((volatile int*)__null) = 820; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
821 | 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 822); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->FileName().IsVoid()" ") (" "FileName should be null when calling InternalLoad from LoadURI" ")"); do { *((volatile int*)__null) = 822; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
822 | "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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 822); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->FileName().IsVoid()" ") (" "FileName should be null when calling InternalLoad from LoadURI" ")"); do { *((volatile int*)__null) = 822; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
823 | 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 825); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aLoadState->LoadIsFromSessionHistory()" ") (" "Shouldn't be loading from an entry when calling InternalLoad " "from LoadURI" ")"); do { *((volatile int*)__null) = 825; __attribute__ ((nomerge)) ::abort(); } while (false); } } while (false) |
824 | "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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 825); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aLoadState->LoadIsFromSessionHistory()" ") (" "Shouldn't be loading from an entry when calling InternalLoad " "from LoadURI" ")"); do { *((volatile int*)__null) = 825; __attribute__ ((nomerge)) ::abort(); } while (false); } } while (false) |
825 | "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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 825); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aLoadState->LoadIsFromSessionHistory()" ") (" "Shouldn't be loading from an entry when calling InternalLoad " "from LoadURI" ")"); do { *((volatile int*)__null) = 825; __attribute__ ((nomerge)) ::abort(); } while (false); } } while (false); |
826 | |
827 | // If we have a system triggering principal, we can assume that this load was |
828 | // triggered by some UI in the browser chrome, such as the URL bar or |
829 | // bookmark bar. This should count as a user interaction for the current sh |
830 | // entry, so that the user may navigate back to the current entry, from the |
831 | // entry that is going to be added as part of this load. |
832 | nsCOMPtr<nsIPrincipal> triggeringPrincipal = |
833 | aLoadState->TriggeringPrincipal(); |
834 | if (triggeringPrincipal && triggeringPrincipal->IsSystemPrincipal()) { |
835 | if (mozilla::SessionHistoryInParent()) { |
836 | WindowContext* topWc = mBrowsingContext->GetTopWindowContext(); |
837 | if (topWc && !topWc->IsDiscarded()) { |
838 | MOZ_ALWAYS_SUCCEEDS(topWc->SetSHEntryHasUserInteraction(true))do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl (topWc->SetSHEntryHasUserInteraction(true))), 1)))), 1))) { } else { do { static_assert( mozilla::detail::AssertionConditionType <decltype(false)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("false" " (" "NS_SUCCEEDED(topWc->SetSHEntryHasUserInteraction(true))" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 838); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false" ") (" "NS_SUCCEEDED(topWc->SetSHEntryHasUserInteraction(true))" ")"); do { *((volatile int*)__null) = 838; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); |
839 | } |
840 | } else { |
841 | bool oshe = false; |
842 | nsCOMPtr<nsISHEntry> currentSHEntry; |
843 | GetCurrentSHEntry(getter_AddRefs(currentSHEntry), &oshe); |
844 | if (currentSHEntry) { |
845 | currentSHEntry->SetHasUserInteraction(true); |
846 | } |
847 | } |
848 | } |
849 | |
850 | rv = InternalLoad(aLoadState); |
851 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 851); return rv; } } while (false); |
852 | |
853 | if (aLoadState->GetOriginalURIString().isSome()) { |
854 | // Save URI string in case it's needed later when |
855 | // sending to search engine service in EndPageLoad() |
856 | mOriginalUriString = *aLoadState->GetOriginalURIString(); |
857 | } |
858 | |
859 | return NS_OK; |
860 | } |
861 | |
862 | bool nsDocShell::IsLoadingFromSessionHistory() { |
863 | return mActiveEntryIsLoadingFromSessionHistory; |
864 | } |
865 | |
866 | // StopDetector is modeled similarly to OnloadBlocker; it is a rather |
867 | // dummy nsIRequest implementation which can be added to an nsILoadGroup to |
868 | // detect Cancel calls. |
869 | class StopDetector final : public nsIRequest { |
870 | public: |
871 | StopDetector() = default; |
872 | |
873 | 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: |
874 | 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; |
875 | |
876 | bool Canceled() { return mCanceled; } |
877 | |
878 | private: |
879 | ~StopDetector() = default; |
880 | |
881 | bool mCanceled = false; |
882 | }; |
883 | |
884 | 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 884); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0" ") (" "illegal refcnt" ")"); do { *((volatile int*)__null) = 884; __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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 884); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"StopDetector\" != nullptr" ") (" "Must specify a name" ")"); do { *((volatile int*)__null ) = 884; __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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 884); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0" ") (" "dup release" ")"); do { *((volatile int*)__null) = 884 ; __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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 884); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"StopDetector\" != nullptr" ") (" "Must specify a name" ")"); do { *((volatile int*)__null ) = 884; __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" , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 884); 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((sizeof(table) / sizeof(table [0])) > 1, "need at least 1 interface"); rv = NS_TableDrivenQI (static_cast<void*>(this), aIID, aInstancePtr, table); return rv; } |
885 | |
886 | NS_IMETHODIMPnsresult |
887 | StopDetector::GetName(nsACString& aResult) { |
888 | aResult.AssignLiteral("about:stop-detector"); |
889 | return NS_OK; |
890 | } |
891 | |
892 | NS_IMETHODIMPnsresult |
893 | StopDetector::IsPending(bool* aRetVal) { |
894 | *aRetVal = true; |
895 | return NS_OK; |
896 | } |
897 | |
898 | NS_IMETHODIMPnsresult |
899 | StopDetector::GetStatus(nsresult* aStatus) { |
900 | *aStatus = NS_OK; |
901 | return NS_OK; |
902 | } |
903 | |
904 | NS_IMETHODIMPnsresult StopDetector::SetCanceledReason(const nsACString& aReason) { |
905 | return SetCanceledReasonImpl(aReason); |
906 | } |
907 | |
908 | NS_IMETHODIMPnsresult StopDetector::GetCanceledReason(nsACString& aReason) { |
909 | return GetCanceledReasonImpl(aReason); |
910 | } |
911 | |
912 | NS_IMETHODIMPnsresult StopDetector::CancelWithReason(nsresult aStatus, |
913 | const nsACString& aReason) { |
914 | return CancelWithReasonImpl(aStatus, aReason); |
915 | } |
916 | |
917 | NS_IMETHODIMPnsresult |
918 | StopDetector::Cancel(nsresult aStatus) { |
919 | mCanceled = true; |
920 | return NS_OK; |
921 | } |
922 | |
923 | NS_IMETHODIMPnsresult |
924 | StopDetector::Suspend(void) { return NS_OK; } |
925 | NS_IMETHODIMPnsresult |
926 | StopDetector::Resume(void) { return NS_OK; } |
927 | |
928 | NS_IMETHODIMPnsresult |
929 | StopDetector::GetLoadGroup(nsILoadGroup** aLoadGroup) { |
930 | *aLoadGroup = nullptr; |
931 | return NS_OK; |
932 | } |
933 | |
934 | NS_IMETHODIMPnsresult |
935 | StopDetector::SetLoadGroup(nsILoadGroup* aLoadGroup) { return NS_OK; } |
936 | |
937 | NS_IMETHODIMPnsresult |
938 | StopDetector::GetLoadFlags(nsLoadFlags* aLoadFlags) { |
939 | *aLoadFlags = nsIRequest::LOAD_NORMAL; |
940 | return NS_OK; |
941 | } |
942 | |
943 | NS_IMETHODIMPnsresult |
944 | StopDetector::GetTRRMode(nsIRequest::TRRMode* aTRRMode) { |
945 | return GetTRRModeImpl(aTRRMode); |
946 | } |
947 | |
948 | NS_IMETHODIMPnsresult |
949 | StopDetector::SetTRRMode(nsIRequest::TRRMode aTRRMode) { |
950 | return SetTRRModeImpl(aTRRMode); |
951 | } |
952 | |
953 | NS_IMETHODIMPnsresult |
954 | StopDetector::SetLoadFlags(nsLoadFlags aLoadFlags) { return NS_OK; } |
955 | |
956 | bool nsDocShell::MaybeHandleSubframeHistory( |
957 | nsDocShellLoadState* aLoadState, bool aContinueHandlingSubframeHistory) { |
958 | // First, verify if this is a subframe. |
959 | // Note, it is ok to rely on docshell here and not browsing context since when |
960 | // an iframe is created, it has first in-process docshell. |
961 | nsCOMPtr<nsIDocShellTreeItem> parentAsItem; |
962 | GetInProcessSameTypeParent(getter_AddRefs(parentAsItem)); |
963 | nsCOMPtr<nsIDocShell> parentDS(do_QueryInterface(parentAsItem)); |
964 | |
965 | if (!parentDS || parentDS == static_cast<nsIDocShell*>(this)) { |
966 | if (mBrowsingContext && mBrowsingContext->IsTop()) { |
967 | // This is the root docshell. If we got here while |
968 | // executing an onLoad Handler,this load will not go |
969 | // into session history. |
970 | // XXX Why is this code in a method which deals with iframes! |
971 | if (aLoadState->IsFormSubmission()) { |
972 | #ifdef DEBUG1 |
973 | if (!mEODForCurrentDocument) { |
974 | const MaybeDiscarded<BrowsingContext>& targetBC = |
975 | aLoadState->TargetBrowsingContext(); |
976 | 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", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 977); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->LoadType() == LOAD_NORMAL_REPLACE" ")"); do { *((volatile int*)__null) = 977; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) |
977 | 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", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 977); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->LoadType() == LOAD_NORMAL_REPLACE" ")"); do { *((volatile int*)__null) = 977; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); |
978 | } |
979 | #endif |
980 | } else { |
981 | bool inOnLoadHandler = false; |
982 | GetIsExecutingOnLoadHandler(&inOnLoadHandler); |
983 | if (inOnLoadHandler) { |
984 | aLoadState->SetLoadType(LOAD_NORMAL_REPLACE); |
985 | } |
986 | } |
987 | } |
988 | return false; |
989 | } |
990 | |
991 | /* OK. It is a subframe. Checkout the parent's loadtype. If the parent was |
992 | * loaded through a history mechanism, then get the SH entry for the child |
993 | * from the parent. This is done to restore frameset navigation while going |
994 | * back/forward. If the parent was loaded through any other loadType, set the |
995 | * child's loadType too accordingly, so that session history does not get |
996 | * confused. |
997 | */ |
998 | |
999 | // Get the parent's load type |
1000 | uint32_t parentLoadType; |
1001 | parentDS->GetLoadType(&parentLoadType); |
1002 | |
1003 | if (!aContinueHandlingSubframeHistory) { |
1004 | if (mozilla::SessionHistoryInParent()) { |
1005 | if (nsDocShell::Cast(parentDS.get())->IsLoadingFromSessionHistory() && |
1006 | !GetCreatedDynamically()) { |
1007 | if (XRE_IsContentProcess()) { |
1008 | dom::ContentChild* contentChild = dom::ContentChild::GetSingleton(); |
1009 | nsCOMPtr<nsILoadGroup> loadGroup; |
1010 | GetLoadGroup(getter_AddRefs(loadGroup)); |
1011 | if (contentChild && loadGroup && !mCheckingSessionHistory) { |
1012 | RefPtr<Document> parentDoc = parentDS->GetDocument(); |
1013 | parentDoc->BlockOnload(); |
1014 | RefPtr<BrowsingContext> browsingContext = mBrowsingContext; |
1015 | Maybe<uint64_t> currentLoadIdentifier = |
1016 | mBrowsingContext->GetCurrentLoadIdentifier(); |
1017 | RefPtr<nsDocShellLoadState> loadState = aLoadState; |
1018 | bool isNavigating = mIsNavigating; |
1019 | RefPtr<StopDetector> stopDetector = new StopDetector(); |
1020 | loadGroup->AddRequest(stopDetector, nullptr); |
1021 | // Need to set mCheckingSessionHistory so that |
1022 | // GetIsAttemptingToNavigate() returns true. |
1023 | mCheckingSessionHistory = true; |
1024 | |
1025 | auto resolve = |
1026 | [currentLoadIdentifier, browsingContext, parentDoc, loadState, |
1027 | isNavigating, loadGroup, stopDetector]( |
1028 | mozilla::Maybe<LoadingSessionHistoryInfo>&& aResult) { |
1029 | RefPtr<nsDocShell> docShell = |
1030 | static_cast<nsDocShell*>(browsingContext->GetDocShell()); |
1031 | auto unblockParent = MakeScopeExit( |
1032 | [loadGroup, stopDetector, parentDoc, docShell]() { |
1033 | if (docShell) { |
1034 | docShell->mCheckingSessionHistory = false; |
1035 | } |
1036 | loadGroup->RemoveRequest(stopDetector, nullptr, NS_OK); |
1037 | parentDoc->UnblockOnload(false); |
1038 | }); |
1039 | |
1040 | if (!docShell || !docShell->mCheckingSessionHistory) { |
1041 | return; |
1042 | } |
1043 | |
1044 | if (stopDetector->Canceled()) { |
1045 | return; |
1046 | } |
1047 | if (currentLoadIdentifier == |
1048 | browsingContext->GetCurrentLoadIdentifier() && |
1049 | aResult.isSome()) { |
1050 | loadState->SetLoadingSessionHistoryInfo(aResult.value()); |
1051 | // This is an initial subframe load from the session |
1052 | // history, index doesn't need to be updated. |
1053 | loadState->SetLoadIsFromSessionHistory(0, false); |
1054 | } |
1055 | |
1056 | // We got the results back from the parent process, call |
1057 | // LoadURI again with the possibly updated data. |
1058 | docShell->LoadURI(loadState, isNavigating, true); |
1059 | }; |
1060 | auto reject = [loadGroup, stopDetector, browsingContext, |
1061 | parentDoc](mozilla::ipc::ResponseRejectReason) { |
1062 | RefPtr<nsDocShell> docShell = |
1063 | static_cast<nsDocShell*>(browsingContext->GetDocShell()); |
1064 | if (docShell) { |
1065 | docShell->mCheckingSessionHistory = false; |
1066 | } |
1067 | // In practise reject shouldn't be called ever. |
1068 | loadGroup->RemoveRequest(stopDetector, nullptr, NS_OK); |
1069 | parentDoc->UnblockOnload(false); |
1070 | }; |
1071 | contentChild->SendGetLoadingSessionHistoryInfoFromParent( |
1072 | mBrowsingContext, std::move(resolve), std::move(reject)); |
1073 | return true; |
1074 | } |
1075 | } else { |
1076 | Maybe<LoadingSessionHistoryInfo> info; |
1077 | mBrowsingContext->Canonical()->GetLoadingSessionHistoryInfoFromParent( |
1078 | info); |
1079 | if (info.isSome()) { |
1080 | aLoadState->SetLoadingSessionHistoryInfo(info.value()); |
1081 | // This is an initial subframe load from the session |
1082 | // history, index doesn't need to be updated. |
1083 | aLoadState->SetLoadIsFromSessionHistory(0, false); |
1084 | } |
1085 | } |
1086 | } |
1087 | } else { |
1088 | // Get the ShEntry for the child from the parent |
1089 | nsCOMPtr<nsISHEntry> currentSH; |
1090 | bool oshe = false; |
1091 | parentDS->GetCurrentSHEntry(getter_AddRefs(currentSH), &oshe); |
1092 | bool dynamicallyAddedChild = GetCreatedDynamically(); |
1093 | |
1094 | if (!dynamicallyAddedChild && !oshe && currentSH) { |
1095 | // Only use the old SHEntry, if we're sure enough that |
1096 | // it wasn't originally for some other frame. |
1097 | nsCOMPtr<nsISHEntry> shEntry; |
1098 | currentSH->GetChildSHEntryIfHasNoDynamicallyAddedChild( |
1099 | mBrowsingContext->ChildOffset(), getter_AddRefs(shEntry)); |
1100 | if (shEntry) { |
1101 | aLoadState->SetSHEntry(shEntry); |
1102 | } |
1103 | } |
1104 | } |
1105 | } |
1106 | |
1107 | // Make some decisions on the child frame's loadType based on the |
1108 | // parent's loadType, if the subframe hasn't loaded anything into it. |
1109 | // |
1110 | // In some cases privileged scripts may try to get the DOMWindow |
1111 | // reference of this docshell before the loading starts, causing the |
1112 | // initial about:blank content viewer being created and mCurrentURI being |
1113 | // set. To handle this case we check if mCurrentURI is about:blank and |
1114 | // currentSHEntry is null. |
1115 | bool oshe = false; |
1116 | nsCOMPtr<nsISHEntry> currentChildEntry; |
1117 | GetCurrentSHEntry(getter_AddRefs(currentChildEntry), &oshe); |
1118 | |
1119 | if (mCurrentURI && (!NS_IsAboutBlank(mCurrentURI) || currentChildEntry || |
1120 | mLoadingEntry || mActiveEntry)) { |
1121 | // This is a pre-existing subframe. If |
1122 | // 1. The load of this frame was not originally initiated by session |
1123 | // history directly (i.e. (!shEntry) condition succeeded, but it can |
1124 | // still be a history load on parent which causes this frame being |
1125 | // loaded), which we checked with the above assert, and |
1126 | // 2. mCurrentURI is not null, nor the initial about:blank, |
1127 | // it is possible that a parent's onLoadHandler or even self's |
1128 | // onLoadHandler is loading a new page in this child. Check parent's and |
1129 | // self's busy flag and if it is set, we don't want this onLoadHandler |
1130 | // load to get in to session history. |
1131 | BusyFlags parentBusy = parentDS->GetBusyFlags(); |
1132 | BusyFlags selfBusy = GetBusyFlags(); |
1133 | |
1134 | if (parentBusy & BUSY_FLAGS_BUSY || selfBusy & BUSY_FLAGS_BUSY) { |
1135 | aLoadState->SetLoadType(LOAD_NORMAL_REPLACE); |
1136 | aLoadState->ClearLoadIsFromSessionHistory(); |
1137 | } |
1138 | return false; |
1139 | } |
1140 | |
1141 | // This is a newly created frame. Check for exception cases first. |
1142 | // By default the subframe will inherit the parent's loadType. |
1143 | if (aLoadState->LoadIsFromSessionHistory() && |
1144 | (parentLoadType == LOAD_NORMAL || parentLoadType == LOAD_LINK)) { |
1145 | // The parent was loaded normally. In this case, this *brand new* |
1146 | // child really shouldn't have a SHEntry. If it does, it could be |
1147 | // because the parent is replacing an existing frame with a new frame, |
1148 | // in the onLoadHandler. We don't want this url to get into session |
1149 | // history. Clear off shEntry, and set load type to |
1150 | // LOAD_BYPASS_HISTORY. |
1151 | bool inOnLoadHandler = false; |
1152 | parentDS->GetIsExecutingOnLoadHandler(&inOnLoadHandler); |
1153 | if (inOnLoadHandler) { |
1154 | aLoadState->SetLoadType(LOAD_NORMAL_REPLACE); |
1155 | aLoadState->ClearLoadIsFromSessionHistory(); |
1156 | } |
1157 | } else if (parentLoadType == LOAD_REFRESH) { |
1158 | // Clear shEntry. For refresh loads, we have to load |
1159 | // what comes through the pipe, not what's in history. |
1160 | aLoadState->ClearLoadIsFromSessionHistory(); |
1161 | } else if ((parentLoadType == LOAD_BYPASS_HISTORY) || |
1162 | (aLoadState->LoadIsFromSessionHistory() && |
1163 | ((parentLoadType & LOAD_CMD_HISTORY) || |
1164 | (parentLoadType == LOAD_RELOAD_NORMAL) || |
1165 | (parentLoadType == LOAD_RELOAD_CHARSET_CHANGE) || |
1166 | (parentLoadType == LOAD_RELOAD_CHARSET_CHANGE_BYPASS_CACHE) || |
1167 | (parentLoadType == |
1168 | LOAD_RELOAD_CHARSET_CHANGE_BYPASS_PROXY_AND_CACHE)))) { |
1169 | // If the parent url, bypassed history or was loaded from |
1170 | // history, pass on the parent's loadType to the new child |
1171 | // frame too, so that the child frame will also |
1172 | // avoid getting into history. |
1173 | aLoadState->SetLoadType(parentLoadType); |
1174 | } else if (parentLoadType == LOAD_ERROR_PAGE) { |
1175 | // If the parent document is an error page, we don't |
1176 | // want to update global/session history. However, |
1177 | // this child frame is not an error page. |
1178 | aLoadState->SetLoadType(LOAD_BYPASS_HISTORY); |
1179 | } else if ((parentLoadType == LOAD_RELOAD_BYPASS_CACHE) || |
1180 | (parentLoadType == LOAD_RELOAD_BYPASS_PROXY) || |
1181 | (parentLoadType == LOAD_RELOAD_BYPASS_PROXY_AND_CACHE)) { |
1182 | // the new frame should inherit the parent's load type so that it also |
1183 | // bypasses the cache and/or proxy |
1184 | aLoadState->SetLoadType(parentLoadType); |
1185 | } |
1186 | |
1187 | return false; |
1188 | } |
1189 | |
1190 | /* |
1191 | * Reset state to a new content model within the current document and the |
1192 | * document viewer. Called by the document before initiating an out of band |
1193 | * document.write(). |
1194 | */ |
1195 | NS_IMETHODIMPnsresult |
1196 | nsDocShell::PrepareForNewContentModel() { |
1197 | // Clear out our form control state, because the state of controls |
1198 | // in the pre-open() document should not affect the state of |
1199 | // controls that are now going to be written. |
1200 | SetLayoutHistoryState(nullptr); |
1201 | mEODForCurrentDocument = false; |
1202 | return NS_OK; |
1203 | } |
1204 | |
1205 | NS_IMETHODIMPnsresult |
1206 | nsDocShell::FirePageHideNotification(bool aIsUnload) { |
1207 | FirePageHideNotificationInternal(aIsUnload, false); |
1208 | return NS_OK; |
1209 | } |
1210 | |
1211 | void nsDocShell::FirePageHideNotificationInternal( |
1212 | bool aIsUnload, bool aSkipCheckingDynEntries) { |
1213 | if (mDocumentViewer && !mFiredUnloadEvent) { |
1214 | // Keep an explicit reference since calling PageHide could release |
1215 | // mDocumentViewer |
1216 | nsCOMPtr<nsIDocumentViewer> viewer(mDocumentViewer); |
1217 | mFiredUnloadEvent = true; |
1218 | |
1219 | if (mTiming) { |
1220 | mTiming->NotifyUnloadEventStart(); |
1221 | } |
1222 | |
1223 | viewer->PageHide(aIsUnload); |
1224 | |
1225 | if (mTiming) { |
1226 | mTiming->NotifyUnloadEventEnd(); |
1227 | } |
1228 | |
1229 | AutoTArray<nsCOMPtr<nsIDocShell>, 8> kids; |
1230 | uint32_t n = mChildList.Length(); |
1231 | kids.SetCapacity(n); |
1232 | for (uint32_t i = 0; i < n; i++) { |
1233 | kids.AppendElement(do_QueryInterface(ChildAt(i))); |
1234 | } |
1235 | |
1236 | n = kids.Length(); |
1237 | for (uint32_t i = 0; i < n; ++i) { |
1238 | RefPtr<nsDocShell> child = static_cast<nsDocShell*>(kids[i].get()); |
1239 | if (child) { |
1240 | // Skip checking dynamic subframe entries in our children. |
1241 | child->FirePageHideNotificationInternal(aIsUnload, true); |
1242 | } |
1243 | } |
1244 | |
1245 | // If the document is unloading, remove all dynamic subframe entries. |
1246 | if (aIsUnload && !aSkipCheckingDynEntries) { |
1247 | RefPtr<ChildSHistory> rootSH = GetRootSessionHistory(); |
1248 | if (rootSH) { |
1249 | 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) |
1250 | 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) |
1251 | ("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); |
1252 | if (mozilla::SessionHistoryInParent()) { |
1253 | if (mActiveEntry) { |
1254 | mBrowsingContext->RemoveDynEntriesFromActiveSessionHistoryEntry(); |
1255 | } |
1256 | 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) |
1257 | ("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); |
1258 | } else if (mOSHE) { |
1259 | int32_t index = rootSH->Index(); |
1260 | rootSH->LegacySHistory()->RemoveDynEntries(index, mOSHE); |
1261 | } |
1262 | } |
1263 | } |
1264 | |
1265 | // Now make sure our editor, if any, is detached before we go |
1266 | // any farther. |
1267 | DetachEditorFromWindow(); |
1268 | } |
1269 | } |
1270 | |
1271 | void nsDocShell::ThawFreezeNonRecursive(bool aThaw) { |
1272 | 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()" , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 1272); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mozilla::BFCacheInParent()" ")"); do { *((volatile int*)__null) = 1272; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1273 | |
1274 | if (!mScriptGlobal) { |
1275 | return; |
1276 | } |
1277 | |
1278 | if (RefPtr<nsGlobalWindowInner> inner = |
1279 | nsGlobalWindowInner::Cast(mScriptGlobal->GetCurrentInnerWindow())) { |
1280 | if (aThaw) { |
1281 | inner->Thaw(false); |
1282 | } else { |
1283 | inner->Freeze(false); |
1284 | } |
1285 | } |
1286 | } |
1287 | |
1288 | void nsDocShell::FirePageHideShowNonRecursive(bool aShow) { |
1289 | MOZ_ASSERT(mozilla::BFCacheInParent())do { static_assert( mozilla::detail::AssertionConditionType< decltype(mozilla::BFCacheInParent())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mozilla::BFCacheInParent())) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mozilla::BFCacheInParent()" , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 1289); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mozilla::BFCacheInParent()" ")"); do { *((volatile int*)__null) = 1289; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1290 | |
1291 | if (!mDocumentViewer) { |
1292 | return; |
1293 | } |
1294 | |
1295 | // Emulate what non-SHIP BFCache does too. In pageshow case |
1296 | // add and remove a request and before that call SetCurrentURI to get |
1297 | // the location change notification. |
1298 | // For pagehide, set mFiredUnloadEvent to true, so that unload doesn't fire. |
1299 | nsCOMPtr<nsIDocumentViewer> viewer(mDocumentViewer); |
1300 | if (aShow) { |
1301 | viewer->SetIsHidden(false); |
1302 | mRefreshURIList = std::move(mBFCachedRefreshURIList); |
1303 | RefreshURIFromQueue(); |
1304 | mFiredUnloadEvent = false; |
1305 | RefPtr<Document> doc = viewer->GetDocument(); |
1306 | if (doc) { |
1307 | doc->NotifyActivityChanged(); |
1308 | nsCOMPtr<nsPIDOMWindowInner> inner = |
1309 | mScriptGlobal ? mScriptGlobal->GetCurrentInnerWindow() : nullptr; |
1310 | if (mBrowsingContext->IsTop()) { |
1311 | doc->NotifyPossibleTitleChange(false); |
1312 | doc->SetLoadingOrRestoredFromBFCacheTimeStampToNow(); |
1313 | if (inner) { |
1314 | // Now that we have found the inner window of the page restored |
1315 | // from the history, we have to make sure that |
1316 | // performance.navigation.type is 2. |
1317 | // Traditionally this type change has been done to the top level page |
1318 | // only. |
1319 | Performance* performance = inner->GetPerformance(); |
1320 | if (performance) { |
1321 | performance->GetDOMTiming()->NotifyRestoreStart(); |
1322 | } |
1323 | } |
1324 | } |
1325 | |
1326 | nsCOMPtr<nsIChannel> channel = doc->GetChannel(); |
1327 | if (channel) { |
1328 | SetLoadType(LOAD_HISTORY); |
1329 | mEODForCurrentDocument = false; |
1330 | mIsRestoringDocument = true; |
1331 | mLoadGroup->AddRequest(channel, nullptr); |
1332 | nsCOMPtr<nsIURI> uri; |
1333 | if (doc->FragmentDirective()) { |
1334 | // If we have fragment directives, then we've mutated the document |
1335 | // uri. Set the current URI from session history instead. |
1336 | if (mozilla::SessionHistoryInParent()) { |
1337 | uri = mActiveEntry ? mActiveEntry->GetURI() : nullptr; |
1338 | } else if (mOSHE) { |
1339 | uri = mOSHE->GetURI(); |
1340 | } |
1341 | } |
1342 | if (!uri) { |
1343 | uri = doc->GetDocumentURI(); |
1344 | } |
1345 | SetCurrentURI(uri, channel, |
1346 | /* aFireOnLocationChange */ true, |
1347 | /* aIsInitialAboutBlank */ false, |
1348 | /* aLocationFlags */ 0); |
1349 | mLoadGroup->RemoveRequest(channel, nullptr, NS_OK); |
1350 | mIsRestoringDocument = false; |
1351 | } |
1352 | RefPtr<PresShell> presShell = GetPresShell(); |
1353 | if (presShell) { |
1354 | presShell->Thaw(false); |
1355 | } |
1356 | |
1357 | if (inner) { |
1358 | inner->FireDelayedDOMEvents(false); |
1359 | } |
1360 | } |
1361 | } else if (!mFiredUnloadEvent) { |
1362 | // XXXBFCache check again that the page can enter bfcache. |
1363 | // XXXBFCache should mTiming->NotifyUnloadEventStart()/End() be called here? |
1364 | |
1365 | if (mRefreshURIList) { |
1366 | RefreshURIToQueue(); |
1367 | mBFCachedRefreshURIList = std::move(mRefreshURIList); |
1368 | } else { |
1369 | // If Stop was called, the list was moved to mSavedRefreshURIList after |
1370 | // calling SuspendRefreshURIs, which calls RefreshURIToQueue. |
1371 | mBFCachedRefreshURIList = std::move(mSavedRefreshURIList); |
1372 | } |
1373 | |
1374 | mFiredUnloadEvent = true; |
1375 | viewer->PageHide(false); |
1376 | |
1377 | RefPtr<PresShell> presShell = GetPresShell(); |
1378 | if (presShell) { |
1379 | presShell->Freeze(false); |
1380 | } |
1381 | } |
1382 | } |
1383 | |
1384 | nsresult nsDocShell::Dispatch(already_AddRefed<nsIRunnable>&& aRunnable) { |
1385 | nsCOMPtr<nsIRunnable> runnable(aRunnable); |
1386 | if (NS_WARN_IF(!GetWindow())NS_warn_if_impl(!GetWindow(), "!GetWindow()", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 1386)) { |
1387 | // Window should only be unavailable after destroyed. |
1388 | 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" , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 1388); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mIsBeingDestroyed" ")"); do { *((volatile int*)__null) = 1388; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1389 | return NS_ERROR_FAILURE; |
1390 | } |
1391 | return SchedulerGroup::Dispatch(runnable.forget()); |
1392 | } |
1393 | |
1394 | NS_IMETHODIMPnsresult |
1395 | nsDocShell::DispatchLocationChangeEvent() { |
1396 | return Dispatch(NewRunnableMethod("nsDocShell::FireDummyOnLocationChange", |
1397 | this, |
1398 | &nsDocShell::FireDummyOnLocationChange)); |
1399 | } |
1400 | |
1401 | NS_IMETHODIMPnsresult |
1402 | nsDocShell::StartDelayedAutoplayMediaComponents() { |
1403 | RefPtr<nsPIDOMWindowOuter> outerWindow = GetWindow(); |
1404 | if (outerWindow) { |
1405 | outerWindow->ActivateMediaComponents(); |
1406 | } |
1407 | return NS_OK; |
1408 | } |
1409 | |
1410 | bool nsDocShell::MaybeInitTiming() { |
1411 | if (mTiming && !mBlankTiming) { |
1412 | return false; |
1413 | } |
1414 | |
1415 | bool canBeReset = false; |
1416 | |
1417 | if (mScriptGlobal && mBlankTiming) { |
1418 | nsPIDOMWindowInner* innerWin = mScriptGlobal->GetCurrentInnerWindow(); |
1419 | if (innerWin && innerWin->GetPerformance()) { |
1420 | mTiming = innerWin->GetPerformance()->GetDOMTiming(); |
1421 | mBlankTiming = false; |
1422 | } |
1423 | } |
1424 | |
1425 | if (!mTiming) { |
1426 | mTiming = new nsDOMNavigationTiming(this); |
1427 | canBeReset = true; |
1428 | } |
1429 | |
1430 | mTiming->NotifyNavigationStart( |
1431 | mBrowsingContext->IsActive() |
1432 | ? nsDOMNavigationTiming::DocShellState::eActive |
1433 | : nsDOMNavigationTiming::DocShellState::eInactive); |
1434 | |
1435 | return canBeReset; |
1436 | } |
1437 | |
1438 | void nsDocShell::MaybeResetInitTiming(bool aReset) { |
1439 | if (aReset) { |
1440 | mTiming = nullptr; |
1441 | } |
1442 | } |
1443 | |
1444 | nsDOMNavigationTiming* nsDocShell::GetNavigationTiming() const { |
1445 | return mTiming; |
1446 | } |
1447 | |
1448 | nsPresContext* nsDocShell::GetEldestPresContext() { |
1449 | nsIDocumentViewer* viewer = mDocumentViewer; |
1450 | while (viewer) { |
1451 | nsIDocumentViewer* prevViewer = viewer->GetPreviousViewer(); |
1452 | if (!prevViewer) { |
1453 | return viewer->GetPresContext(); |
1454 | } |
1455 | viewer = prevViewer; |
1456 | } |
1457 | |
1458 | return nullptr; |
1459 | } |
1460 | |
1461 | nsPresContext* nsDocShell::GetPresContext() { |
1462 | if (!mDocumentViewer) { |
1463 | return nullptr; |
1464 | } |
1465 | |
1466 | return mDocumentViewer->GetPresContext(); |
1467 | } |
1468 | |
1469 | PresShell* nsDocShell::GetPresShell() { |
1470 | nsPresContext* presContext = GetPresContext(); |
1471 | return presContext ? presContext->GetPresShell() : nullptr; |
1472 | } |
1473 | |
1474 | PresShell* nsDocShell::GetEldestPresShell() { |
1475 | nsPresContext* presContext = GetEldestPresContext(); |
1476 | |
1477 | if (presContext) { |
1478 | return presContext->GetPresShell(); |
1479 | } |
1480 | |
1481 | return nullptr; |
1482 | } |
1483 | |
1484 | NS_IMETHODIMPnsresult |
1485 | nsDocShell::GetDocViewer(nsIDocumentViewer** aDocumentViewer) { |
1486 | NS_ENSURE_ARG_POINTER(aDocumentViewer)do { if ((__builtin_expect(!!(!(aDocumentViewer)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aDocumentViewer" ") failed" , nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 1486); return NS_ERROR_INVALID_POINTER; } } while (false); |
1487 | |
1488 | *aDocumentViewer = mDocumentViewer; |
1489 | NS_IF_ADDREF(*aDocumentViewer)ns_if_addref(*aDocumentViewer); |
1490 | return NS_OK; |
1491 | } |
1492 | |
1493 | NS_IMETHODIMPnsresult |
1494 | nsDocShell::GetOuterWindowID(uint64_t* aWindowID) { |
1495 | *aWindowID = mContentWindowID; |
1496 | return NS_OK; |
1497 | } |
1498 | |
1499 | NS_IMETHODIMPnsresult |
1500 | nsDocShell::SetChromeEventHandler(EventTarget* aChromeEventHandler) { |
1501 | mChromeEventHandler = aChromeEventHandler; |
1502 | |
1503 | if (mScriptGlobal) { |
1504 | mScriptGlobal->SetChromeEventHandler(mChromeEventHandler); |
1505 | } |
1506 | |
1507 | return NS_OK; |
1508 | } |
1509 | |
1510 | NS_IMETHODIMPnsresult |
1511 | nsDocShell::GetChromeEventHandler(EventTarget** aChromeEventHandler) { |
1512 | NS_ENSURE_ARG_POINTER(aChromeEventHandler)do { if ((__builtin_expect(!!(!(aChromeEventHandler)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aChromeEventHandler" ") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 1512); return NS_ERROR_INVALID_POINTER; } } while (false); |
1513 | RefPtr<EventTarget> handler = mChromeEventHandler; |
1514 | handler.forget(aChromeEventHandler); |
1515 | return NS_OK; |
1516 | } |
1517 | |
1518 | NS_IMETHODIMPnsresult |
1519 | nsDocShell::SetCurrentURIForSessionStore(nsIURI* aURI) { |
1520 | // Note that securityUI will set STATE_IS_INSECURE, even if |
1521 | // the scheme of |aURI| is "https". |
1522 | SetCurrentURI(aURI, nullptr, |
1523 | /* aFireOnLocationChange */ |
1524 | true, |
1525 | /* aIsInitialAboutBlank */ |
1526 | false, |
1527 | /* aLocationFlags */ |
1528 | nsIWebProgressListener::LOCATION_CHANGE_SESSION_STORE); |
1529 | return NS_OK; |
1530 | } |
1531 | |
1532 | bool nsDocShell::SetCurrentURI(nsIURI* aURI, nsIRequest* aRequest, |
1533 | bool aFireOnLocationChange, |
1534 | bool aIsInitialAboutBlank, |
1535 | uint32_t aLocationFlags) { |
1536 | 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" , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 1536); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mIsBeingDestroyed" ")"); do { *((volatile int*)__null) = 1536; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1537 | |
1538 | 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) |
1539 | ("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) |
1540 | 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); |
1541 | |
1542 | // We don't want to send a location change when we're displaying an error |
1543 | // page, and we don't want to change our idea of "current URI" either |
1544 | if (mLoadType == LOAD_ERROR_PAGE) { |
1545 | return false; |
1546 | } |
1547 | |
1548 | bool uriIsEqual = false; |
1549 | if (!mCurrentURI || !aURI || |
1550 | NS_FAILED(mCurrentURI->Equals(aURI, &uriIsEqual))((bool)(__builtin_expect(!!(NS_FAILED_impl(mCurrentURI->Equals (aURI, &uriIsEqual))), 0))) || !uriIsEqual) { |
1551 | mTitleValidForCurrentURI = false; |
1552 | } |
1553 | |
1554 | SetCurrentURIInternal(aURI); |
1555 | |
1556 | #ifdef DEBUG1 |
1557 | mLastOpenedURI = aURI; |
1558 | #endif |
1559 | |
1560 | if (!NS_IsAboutBlank(mCurrentURI)) { |
1561 | mHasLoadedNonBlankURI = true; |
1562 | } |
1563 | |
1564 | // Don't fire onLocationChange when creating a subframe's initial about:blank |
1565 | // document, as this can happen when it's not safe for us to run script. |
1566 | if (aIsInitialAboutBlank && !mHasLoadedNonBlankURI && |
1567 | !mBrowsingContext->IsTop()) { |
1568 | 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" , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 1568); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aRequest && aLocationFlags == 0" ")"); do { *((volatile int*)__null) = 1568; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1569 | return false; |
1570 | } |
1571 | |
1572 | 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()", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 1572); AnnotateMozCrashReason("MOZ_ASSERT" "(" "nsContentUtils::IsSafeToRunScript()" ")"); do { *((volatile int*)__null) = 1572; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1573 | |
1574 | if (aFireOnLocationChange) { |
1575 | FireOnLocationChange(this, aRequest, aURI, aLocationFlags); |
1576 | } |
1577 | return !aFireOnLocationChange; |
1578 | } |
1579 | |
1580 | void nsDocShell::SetCurrentURIInternal(nsIURI* aURI) { |
1581 | mCurrentURI = aURI; |
1582 | if (mBrowsingContext) { |
1583 | mBrowsingContext->ClearCachedValuesOfLocations(); |
1584 | } |
1585 | } |
1586 | |
1587 | NS_IMETHODIMPnsresult |
1588 | nsDocShell::GetCharset(nsACString& aCharset) { |
1589 | aCharset.Truncate(); |
1590 | |
1591 | PresShell* presShell = GetPresShell(); |
1592 | NS_ENSURE_TRUE(presShell, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(presShell)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "presShell" ") failed", nullptr , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 1592); return NS_ERROR_FAILURE; } } while (false); |
1593 | Document* doc = presShell->GetDocument(); |
1594 | NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(doc)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING , "NS_ENSURE_TRUE(" "doc" ") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 1594); return NS_ERROR_FAILURE; } } while (false); |
1595 | doc->GetDocumentCharacterSet()->Name(aCharset); |
1596 | return NS_OK; |
1597 | } |
1598 | |
1599 | NS_IMETHODIMPnsresult |
1600 | nsDocShell::ForceEncodingDetection() { |
1601 | nsCOMPtr<nsIDocumentViewer> viewer; |
1602 | GetDocViewer(getter_AddRefs(viewer)); |
1603 | if (!viewer) { |
1604 | return NS_OK; |
1605 | } |
1606 | |
1607 | Document* doc = viewer->GetDocument(); |
1608 | if (!doc || doc->WillIgnoreCharsetOverride()) { |
1609 | return NS_OK; |
1610 | } |
1611 | |
1612 | mForcedAutodetection = true; |
1613 | |
1614 | nsIURI* url = doc->GetOriginalURI(); |
1615 | bool isFileURL = url && SchemeIsFile(url); |
1616 | |
1617 | int32_t charsetSource = doc->GetDocumentCharacterSetSource(); |
1618 | auto encoding = doc->GetDocumentCharacterSet(); |
1619 | // AsHTMLDocument is valid, because we called |
1620 | // WillIgnoreCharsetOverride() above. |
1621 | if (doc->AsHTMLDocument()->IsPlainText()) { |
1622 | switch (charsetSource) { |
1623 | case kCharsetFromInitialAutoDetectionASCII: |
1624 | // Deliberately no final version |
1625 | 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); |
1626 | break; |
1627 | case kCharsetFromInitialAutoDetectionWouldNotHaveBeenUTF8Generic: |
1628 | case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8Generic: |
1629 | case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8GenericInitialWasASCII: |
1630 | case kCharsetFromInitialAutoDetectionWouldNotHaveBeenUTF8Content: |
1631 | case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8Content: |
1632 | case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8ContentInitialWasASCII: |
1633 | 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); |
1634 | break; |
1635 | case kCharsetFromInitialAutoDetectionWouldNotHaveBeenUTF8DependedOnTLD: |
1636 | case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8DependedOnTLD: |
1637 | case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8DependedOnTLDInitialWasASCII: |
1638 | 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); |
1639 | break; |
1640 | case kCharsetFromInitialAutoDetectionWouldHaveBeenUTF8: |
1641 | case kCharsetFromFinalAutoDetectionWouldHaveBeenUTF8InitialWasASCII: |
1642 | 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); |
1643 | break; |
1644 | case kCharsetFromChannel: |
1645 | if (encoding == UTF_8_ENCODING) { |
1646 | 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); |
1647 | } else { |
1648 | 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); |
1649 | } |
1650 | break; |
1651 | default: |
1652 | 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); |
1653 | break; |
1654 | } |
1655 | } else { |
1656 | switch (charsetSource) { |
1657 | case kCharsetFromInitialAutoDetectionASCII: |
1658 | // Deliberately no final version |
1659 | 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); |
1660 | break; |
1661 | case kCharsetFromInitialAutoDetectionWouldNotHaveBeenUTF8Generic: |
1662 | case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8Generic: |
1663 | case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8GenericInitialWasASCII: |
1664 | case kCharsetFromInitialAutoDetectionWouldNotHaveBeenUTF8Content: |
1665 | case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8Content: |
1666 | case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8ContentInitialWasASCII: |
1667 | 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); |
1668 | break; |
1669 | case kCharsetFromInitialAutoDetectionWouldNotHaveBeenUTF8DependedOnTLD: |
1670 | case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8DependedOnTLD: |
1671 | case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8DependedOnTLDInitialWasASCII: |
1672 | 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); |
1673 | break; |
1674 | case kCharsetFromInitialAutoDetectionWouldHaveBeenUTF8: |
1675 | case kCharsetFromFinalAutoDetectionWouldHaveBeenUTF8InitialWasASCII: |
1676 | 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); |
1677 | break; |
1678 | case kCharsetFromChannel: |
1679 | if (encoding == UTF_8_ENCODING) { |
1680 | 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); |
1681 | } else { |
1682 | 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); |
1683 | } |
1684 | break; |
1685 | case kCharsetFromXmlDeclaration: |
1686 | case kCharsetFromMetaTag: |
1687 | if (isFileURL) { |
1688 | 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); |
1689 | } else if (encoding == UTF_8_ENCODING) { |
1690 | 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); |
1691 | } else { |
1692 | 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); |
1693 | } |
1694 | break; |
1695 | default: |
1696 | 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); |
1697 | break; |
1698 | } |
1699 | } |
1700 | return NS_OK; |
1701 | } |
1702 | |
1703 | void nsDocShell::SetParentCharset(const Encoding*& aCharset, |
1704 | int32_t aCharsetSource, |
1705 | nsIPrincipal* aPrincipal) { |
1706 | mParentCharset = aCharset; |
1707 | mParentCharsetSource = aCharsetSource; |
1708 | mParentCharsetPrincipal = aPrincipal; |
1709 | } |
1710 | |
1711 | void nsDocShell::GetParentCharset(const Encoding*& aCharset, |
1712 | int32_t* aCharsetSource, |
1713 | nsIPrincipal** aPrincipal) { |
1714 | aCharset = mParentCharset; |
1715 | *aCharsetSource = mParentCharsetSource; |
1716 | NS_IF_ADDREF(*aPrincipal = mParentCharsetPrincipal)ns_if_addref(*aPrincipal = mParentCharsetPrincipal); |
1717 | } |
1718 | |
1719 | NS_IMETHODIMPnsresult |
1720 | nsDocShell::GetHasTrackingContentBlocked(Promise** aPromise) { |
1721 | 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", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 1721); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPromise" ")" ); do { *((volatile int*)__null) = 1721; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1722 | |
1723 | ErrorResult rv; |
1724 | RefPtr<Document> doc(GetDocument()); |
1725 | RefPtr<Promise> retPromise = Promise::Create(doc->GetOwnerGlobal(), rv); |
1726 | if (NS_WARN_IF(rv.Failed())NS_warn_if_impl(rv.Failed(), "rv.Failed()", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 1726)) { |
1727 | return rv.StealNSResult(); |
1728 | } |
1729 | |
1730 | // Retrieve the document's content blocking events from the parent process. |
1731 | RefPtr<Document::GetContentBlockingEventsPromise> promise = |
1732 | doc->GetContentBlockingEvents(); |
1733 | if (promise) { |
1734 | promise->Then( |
1735 | GetCurrentSerialEventTarget(), __func__, |
1736 | [retPromise](const Document::GetContentBlockingEventsPromise:: |
1737 | ResolveOrRejectValue& aValue) { |
1738 | if (aValue.IsResolve()) { |
1739 | bool has = aValue.ResolveValue() & |
1740 | nsIWebProgressListener::STATE_BLOCKED_TRACKING_CONTENT; |
1741 | retPromise->MaybeResolve(has); |
1742 | } else { |
1743 | retPromise->MaybeResolve(false); |
1744 | } |
1745 | }); |
1746 | } else { |
1747 | retPromise->MaybeResolve(false); |
1748 | } |
1749 | |
1750 | retPromise.forget(aPromise); |
1751 | return NS_OK; |
1752 | } |
1753 | |
1754 | NS_IMETHODIMPnsresult |
1755 | nsDocShell::GetCssErrorReportingEnabled(bool* aEnabled) { |
1756 | 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", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 1756); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aEnabled" ")" ); do { *((volatile int*)__null) = 1756; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1757 | *aEnabled = mCSSErrorReportingEnabled; |
1758 | return NS_OK; |
1759 | } |
1760 | |
1761 | NS_IMETHODIMPnsresult |
1762 | nsDocShell::SetCssErrorReportingEnabled(bool aEnabled) { |
1763 | mCSSErrorReportingEnabled = aEnabled; |
1764 | return NS_OK; |
1765 | } |
1766 | |
1767 | NS_IMETHODIMPnsresult |
1768 | nsDocShell::GetUsePrivateBrowsing(bool* aUsePrivateBrowsing) { |
1769 | NS_ENSURE_ARG_POINTER(aUsePrivateBrowsing)do { if ((__builtin_expect(!!(!(aUsePrivateBrowsing)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aUsePrivateBrowsing" ") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 1769); return NS_ERROR_INVALID_POINTER; } } while (false); |
1770 | return mBrowsingContext->GetUsePrivateBrowsing(aUsePrivateBrowsing); |
1771 | } |
1772 | |
1773 | void nsDocShell::NotifyPrivateBrowsingChanged() { |
1774 | 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" , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 1774); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mIsBeingDestroyed" ")"); do { *((volatile int*)__null) = 1774; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1775 | |
1776 | nsTObserverArray<nsWeakPtr>::ForwardIterator iter(mPrivacyObservers); |
1777 | while (iter.HasMore()) { |
1778 | nsWeakPtr ref = iter.GetNext(); |
1779 | nsCOMPtr<nsIPrivacyTransitionObserver> obs = do_QueryReferent(ref); |
1780 | if (!obs) { |
1781 | iter.Remove(); |
1782 | } else { |
1783 | obs->PrivateModeChanged(UsePrivateBrowsing()); |
1784 | } |
1785 | } |
1786 | } |
1787 | |
1788 | NS_IMETHODIMPnsresult |
1789 | nsDocShell::SetUsePrivateBrowsing(bool aUsePrivateBrowsing) { |
1790 | return mBrowsingContext->SetUsePrivateBrowsing(aUsePrivateBrowsing); |
1791 | } |
1792 | |
1793 | NS_IMETHODIMPnsresult |
1794 | nsDocShell::SetPrivateBrowsing(bool aUsePrivateBrowsing) { |
1795 | return mBrowsingContext->SetPrivateBrowsing(aUsePrivateBrowsing); |
1796 | } |
1797 | |
1798 | NS_IMETHODIMPnsresult |
1799 | nsDocShell::GetHasLoadedNonBlankURI(bool* aResult) { |
1800 | NS_ENSURE_ARG_POINTER(aResult)do { if ((__builtin_expect(!!(!(aResult)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aResult" ") failed", nullptr , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 1800); return NS_ERROR_INVALID_POINTER; } } while (false); |
1801 | |
1802 | *aResult = mHasLoadedNonBlankURI; |
1803 | return NS_OK; |
1804 | } |
1805 | |
1806 | NS_IMETHODIMPnsresult |
1807 | nsDocShell::GetUseRemoteTabs(bool* aUseRemoteTabs) { |
1808 | NS_ENSURE_ARG_POINTER(aUseRemoteTabs)do { if ((__builtin_expect(!!(!(aUseRemoteTabs)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aUseRemoteTabs" ") failed" , nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 1808); return NS_ERROR_INVALID_POINTER; } } while (false); |
1809 | return mBrowsingContext->GetUseRemoteTabs(aUseRemoteTabs); |
1810 | } |
1811 | |
1812 | NS_IMETHODIMPnsresult |
1813 | nsDocShell::SetRemoteTabs(bool aUseRemoteTabs) { |
1814 | return mBrowsingContext->SetRemoteTabs(aUseRemoteTabs); |
1815 | } |
1816 | |
1817 | NS_IMETHODIMPnsresult |
1818 | nsDocShell::GetUseRemoteSubframes(bool* aUseRemoteSubframes) { |
1819 | NS_ENSURE_ARG_POINTER(aUseRemoteSubframes)do { if ((__builtin_expect(!!(!(aUseRemoteSubframes)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aUseRemoteSubframes" ") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 1819); return NS_ERROR_INVALID_POINTER; } } while (false); |
1820 | return mBrowsingContext->GetUseRemoteSubframes(aUseRemoteSubframes); |
1821 | } |
1822 | |
1823 | NS_IMETHODIMPnsresult |
1824 | nsDocShell::SetRemoteSubframes(bool aUseRemoteSubframes) { |
1825 | return mBrowsingContext->SetRemoteSubframes(aUseRemoteSubframes); |
1826 | } |
1827 | |
1828 | NS_IMETHODIMPnsresult |
1829 | nsDocShell::AddWeakPrivacyTransitionObserver( |
1830 | nsIPrivacyTransitionObserver* aObserver) { |
1831 | nsWeakPtr weakObs = do_GetWeakReference(aObserver); |
1832 | if (!weakObs) { |
1833 | return NS_ERROR_NOT_AVAILABLE; |
1834 | } |
1835 | mPrivacyObservers.AppendElement(weakObs); |
1836 | return NS_OK; |
1837 | } |
1838 | |
1839 | NS_IMETHODIMPnsresult |
1840 | nsDocShell::AddWeakReflowObserver(nsIReflowObserver* aObserver) { |
1841 | nsWeakPtr weakObs = do_GetWeakReference(aObserver); |
1842 | if (!weakObs) { |
1843 | return NS_ERROR_FAILURE; |
1844 | } |
1845 | mReflowObservers.AppendElement(weakObs); |
1846 | return NS_OK; |
1847 | } |
1848 | |
1849 | NS_IMETHODIMPnsresult |
1850 | nsDocShell::RemoveWeakReflowObserver(nsIReflowObserver* aObserver) { |
1851 | nsWeakPtr obs = do_GetWeakReference(aObserver); |
1852 | return mReflowObservers.RemoveElement(obs) ? NS_OK : NS_ERROR_FAILURE; |
1853 | } |
1854 | |
1855 | NS_IMETHODIMPnsresult |
1856 | nsDocShell::NotifyReflowObservers(bool aInterruptible, |
1857 | DOMHighResTimeStamp aStart, |
1858 | DOMHighResTimeStamp aEnd) { |
1859 | nsTObserverArray<nsWeakPtr>::ForwardIterator iter(mReflowObservers); |
1860 | while (iter.HasMore()) { |
1861 | nsWeakPtr ref = iter.GetNext(); |
1862 | nsCOMPtr<nsIReflowObserver> obs = do_QueryReferent(ref); |
1863 | if (!obs) { |
1864 | iter.Remove(); |
1865 | } else if (aInterruptible) { |
1866 | obs->ReflowInterruptible(aStart, aEnd); |
1867 | } else { |
1868 | obs->Reflow(aStart, aEnd); |
1869 | } |
1870 | } |
1871 | return NS_OK; |
1872 | } |
1873 | |
1874 | NS_IMETHODIMPnsresult |
1875 | nsDocShell::GetAllowMetaRedirects(bool* aReturn) { |
1876 | NS_ENSURE_ARG_POINTER(aReturn)do { if ((__builtin_expect(!!(!(aReturn)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aReturn" ") failed", nullptr , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 1876); return NS_ERROR_INVALID_POINTER; } } while (false); |
1877 | |
1878 | *aReturn = mAllowMetaRedirects; |
1879 | return NS_OK; |
1880 | } |
1881 | |
1882 | NS_IMETHODIMPnsresult |
1883 | nsDocShell::SetAllowMetaRedirects(bool aValue) { |
1884 | mAllowMetaRedirects = aValue; |
1885 | return NS_OK; |
1886 | } |
1887 | |
1888 | NS_IMETHODIMPnsresult |
1889 | nsDocShell::GetAllowSubframes(bool* aAllowSubframes) { |
1890 | NS_ENSURE_ARG_POINTER(aAllowSubframes)do { if ((__builtin_expect(!!(!(aAllowSubframes)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aAllowSubframes" ") failed" , nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 1890); return NS_ERROR_INVALID_POINTER; } } while (false); |
1891 | |
1892 | *aAllowSubframes = mAllowSubframes; |
1893 | return NS_OK; |
1894 | } |
1895 | |
1896 | NS_IMETHODIMPnsresult |
1897 | nsDocShell::SetAllowSubframes(bool aAllowSubframes) { |
1898 | mAllowSubframes = aAllowSubframes; |
1899 | return NS_OK; |
1900 | } |
1901 | |
1902 | NS_IMETHODIMPnsresult |
1903 | nsDocShell::GetAllowImages(bool* aAllowImages) { |
1904 | NS_ENSURE_ARG_POINTER(aAllowImages)do { if ((__builtin_expect(!!(!(aAllowImages)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aAllowImages" ") failed" , nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 1904); return NS_ERROR_INVALID_POINTER; } } while (false); |
1905 | |
1906 | *aAllowImages = mAllowImages; |
1907 | return NS_OK; |
1908 | } |
1909 | |
1910 | NS_IMETHODIMPnsresult |
1911 | nsDocShell::SetAllowImages(bool aAllowImages) { |
1912 | mAllowImages = aAllowImages; |
1913 | return NS_OK; |
1914 | } |
1915 | |
1916 | NS_IMETHODIMPnsresult |
1917 | nsDocShell::GetAllowMedia(bool* aAllowMedia) { |
1918 | *aAllowMedia = mAllowMedia; |
1919 | return NS_OK; |
1920 | } |
1921 | |
1922 | NS_IMETHODIMPnsresult |
1923 | nsDocShell::SetAllowMedia(bool aAllowMedia) { |
1924 | mAllowMedia = aAllowMedia; |
1925 | |
1926 | // Mute or unmute audio contexts attached to the inner window. |
1927 | if (mScriptGlobal) { |
1928 | if (nsPIDOMWindowInner* innerWin = mScriptGlobal->GetCurrentInnerWindow()) { |
1929 | if (aAllowMedia) { |
1930 | innerWin->UnmuteAudioContexts(); |
1931 | } else { |
1932 | innerWin->MuteAudioContexts(); |
1933 | } |
1934 | } |
1935 | } |
1936 | |
1937 | return NS_OK; |
1938 | } |
1939 | |
1940 | NS_IMETHODIMPnsresult |
1941 | nsDocShell::GetAllowDNSPrefetch(bool* aAllowDNSPrefetch) { |
1942 | *aAllowDNSPrefetch = mAllowDNSPrefetch; |
1943 | return NS_OK; |
1944 | } |
1945 | |
1946 | NS_IMETHODIMPnsresult |
1947 | nsDocShell::SetAllowDNSPrefetch(bool aAllowDNSPrefetch) { |
1948 | mAllowDNSPrefetch = aAllowDNSPrefetch; |
1949 | return NS_OK; |
1950 | } |
1951 | |
1952 | NS_IMETHODIMPnsresult |
1953 | nsDocShell::GetAllowWindowControl(bool* aAllowWindowControl) { |
1954 | *aAllowWindowControl = mAllowWindowControl; |
1955 | return NS_OK; |
1956 | } |
1957 | |
1958 | NS_IMETHODIMPnsresult |
1959 | nsDocShell::SetAllowWindowControl(bool aAllowWindowControl) { |
1960 | mAllowWindowControl = aAllowWindowControl; |
1961 | return NS_OK; |
1962 | } |
1963 | |
1964 | NS_IMETHODIMPnsresult |
1965 | nsDocShell::GetAllowContentRetargeting(bool* aAllowContentRetargeting) { |
1966 | *aAllowContentRetargeting = mBrowsingContext->GetAllowContentRetargeting(); |
1967 | return NS_OK; |
1968 | } |
1969 | |
1970 | NS_IMETHODIMPnsresult |
1971 | nsDocShell::SetAllowContentRetargeting(bool aAllowContentRetargeting) { |
1972 | BrowsingContext::Transaction txn; |
1973 | txn.SetAllowContentRetargeting(aAllowContentRetargeting); |
1974 | txn.SetAllowContentRetargetingOnChildren(aAllowContentRetargeting); |
1975 | return txn.Commit(mBrowsingContext); |
1976 | } |
1977 | |
1978 | NS_IMETHODIMPnsresult |
1979 | nsDocShell::GetAllowContentRetargetingOnChildren( |
1980 | bool* aAllowContentRetargetingOnChildren) { |
1981 | *aAllowContentRetargetingOnChildren = |
1982 | mBrowsingContext->GetAllowContentRetargetingOnChildren(); |
1983 | return NS_OK; |
1984 | } |
1985 | |
1986 | NS_IMETHODIMPnsresult |
1987 | nsDocShell::SetAllowContentRetargetingOnChildren( |
1988 | bool aAllowContentRetargetingOnChildren) { |
1989 | return mBrowsingContext->SetAllowContentRetargetingOnChildren( |
1990 | aAllowContentRetargetingOnChildren); |
1991 | } |
1992 | |
1993 | NS_IMETHODIMPnsresult |
1994 | nsDocShell::GetMayEnableCharacterEncodingMenu( |
1995 | bool* aMayEnableCharacterEncodingMenu) { |
1996 | *aMayEnableCharacterEncodingMenu = false; |
1997 | if (!mDocumentViewer) { |
1998 | return NS_OK; |
1999 | } |
2000 | Document* doc = mDocumentViewer->GetDocument(); |
2001 | if (!doc) { |
2002 | return NS_OK; |
2003 | } |
2004 | if (doc->WillIgnoreCharsetOverride()) { |
2005 | return NS_OK; |
2006 | } |
2007 | |
2008 | *aMayEnableCharacterEncodingMenu = true; |
2009 | return NS_OK; |
2010 | } |
2011 | |
2012 | NS_IMETHODIMPnsresult |
2013 | nsDocShell::GetAllDocShellsInSubtree(int32_t aItemType, |
2014 | DocShellEnumeratorDirection aDirection, |
2015 | nsTArray<RefPtr<nsIDocShell>>& aResult) { |
2016 | aResult.Clear(); |
2017 | |
2018 | nsDocShellEnumerator docShellEnum( |
2019 | (aDirection == ENUMERATE_FORWARDS) |
2020 | ? nsDocShellEnumerator::EnumerationDirection::Forwards |
2021 | : nsDocShellEnumerator::EnumerationDirection::Backwards, |
2022 | aItemType, *this); |
2023 | |
2024 | nsresult rv = docShellEnum.BuildDocShellArray(aResult); |
2025 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
2026 | return rv; |
2027 | } |
2028 | |
2029 | return NS_OK; |
2030 | } |
2031 | |
2032 | NS_IMETHODIMPnsresult |
2033 | nsDocShell::GetAppType(AppType* aAppType) { |
2034 | *aAppType = mAppType; |
2035 | return NS_OK; |
2036 | } |
2037 | |
2038 | NS_IMETHODIMPnsresult |
2039 | nsDocShell::SetAppType(AppType aAppType) { |
2040 | mAppType = aAppType; |
2041 | return NS_OK; |
2042 | } |
2043 | |
2044 | NS_IMETHODIMPnsresult |
2045 | nsDocShell::GetAllowAuth(bool* aAllowAuth) { |
2046 | *aAllowAuth = mAllowAuth; |
2047 | return NS_OK; |
2048 | } |
2049 | |
2050 | NS_IMETHODIMPnsresult |
2051 | nsDocShell::SetAllowAuth(bool aAllowAuth) { |
2052 | mAllowAuth = aAllowAuth; |
2053 | return NS_OK; |
2054 | } |
2055 | |
2056 | NS_IMETHODIMPnsresult |
2057 | nsDocShell::GetZoom(float* aZoom) { |
2058 | NS_ENSURE_ARG_POINTER(aZoom)do { if ((__builtin_expect(!!(!(aZoom)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aZoom" ") failed", nullptr , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 2058); return NS_ERROR_INVALID_POINTER; } } while (false); |
2059 | *aZoom = 1.0f; |
2060 | return NS_OK; |
2061 | } |
2062 | |
2063 | NS_IMETHODIMPnsresult |
2064 | nsDocShell::SetZoom(float aZoom) { return NS_ERROR_NOT_IMPLEMENTED; } |
2065 | |
2066 | NS_IMETHODIMPnsresult |
2067 | nsDocShell::GetBusyFlags(BusyFlags* aBusyFlags) { |
2068 | NS_ENSURE_ARG_POINTER(aBusyFlags)do { if ((__builtin_expect(!!(!(aBusyFlags)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aBusyFlags" ") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 2068); return NS_ERROR_INVALID_POINTER; } } while (false); |
2069 | |
2070 | *aBusyFlags = mBusyFlags; |
2071 | return NS_OK; |
2072 | } |
2073 | |
2074 | NS_IMETHODIMPnsresult |
2075 | nsDocShell::GetLoadURIDelegate(nsILoadURIDelegate** aLoadURIDelegate) { |
2076 | nsCOMPtr<nsILoadURIDelegate> delegate = GetLoadURIDelegate(); |
2077 | delegate.forget(aLoadURIDelegate); |
2078 | return NS_OK; |
2079 | } |
2080 | |
2081 | already_AddRefed<nsILoadURIDelegate> nsDocShell::GetLoadURIDelegate() { |
2082 | if (nsCOMPtr<nsILoadURIDelegate> result = |
2083 | do_QueryActor("LoadURIDelegate", GetDocument())) { |
2084 | return result.forget(); |
2085 | } |
2086 | |
2087 | return nullptr; |
2088 | } |
2089 | |
2090 | NS_IMETHODIMPnsresult |
2091 | nsDocShell::GetUseErrorPages(bool* aUseErrorPages) { |
2092 | *aUseErrorPages = mBrowsingContext->GetUseErrorPages(); |
2093 | return NS_OK; |
2094 | } |
2095 | |
2096 | NS_IMETHODIMPnsresult |
2097 | nsDocShell::SetUseErrorPages(bool aUseErrorPages) { |
2098 | return mBrowsingContext->SetUseErrorPages(aUseErrorPages); |
2099 | } |
2100 | |
2101 | NS_IMETHODIMPnsresult |
2102 | nsDocShell::GetPreviousEntryIndex(int32_t* aPreviousEntryIndex) { |
2103 | *aPreviousEntryIndex = mPreviousEntryIndex; |
2104 | return NS_OK; |
2105 | } |
2106 | |
2107 | NS_IMETHODIMPnsresult |
2108 | nsDocShell::GetLoadedEntryIndex(int32_t* aLoadedEntryIndex) { |
2109 | *aLoadedEntryIndex = mLoadedEntryIndex; |
2110 | return NS_OK; |
2111 | } |
2112 | |
2113 | NS_IMETHODIMPnsresult |
2114 | nsDocShell::HistoryPurged(int32_t aNumEntries) { |
2115 | // These indices are used for fastback cache eviction, to determine |
2116 | // which session history entries are candidates for content viewer |
2117 | // eviction. We need to adjust by the number of entries that we |
2118 | // just purged from history, so that we look at the right session history |
2119 | // entries during eviction. |
2120 | mPreviousEntryIndex = std::max(-1, mPreviousEntryIndex - aNumEntries); |
2121 | mLoadedEntryIndex = std::max(0, mLoadedEntryIndex - aNumEntries); |
2122 | |
2123 | for (auto* child : mChildList.ForwardRange()) { |
2124 | nsCOMPtr<nsIDocShell> shell = do_QueryObject(child); |
2125 | if (shell) { |
2126 | shell->HistoryPurged(aNumEntries); |
2127 | } |
2128 | } |
2129 | |
2130 | return NS_OK; |
2131 | } |
2132 | |
2133 | nsresult nsDocShell::HistoryEntryRemoved(int32_t aIndex) { |
2134 | // These indices are used for fastback cache eviction, to determine |
2135 | // which session history entries are candidates for content viewer |
2136 | // eviction. We need to adjust by the number of entries that we |
2137 | // just purged from history, so that we look at the right session history |
2138 | // entries during eviction. |
2139 | if (aIndex == mPreviousEntryIndex) { |
2140 | mPreviousEntryIndex = -1; |
2141 | } else if (aIndex < mPreviousEntryIndex) { |
2142 | --mPreviousEntryIndex; |
2143 | } |
2144 | if (mLoadedEntryIndex == aIndex) { |
2145 | mLoadedEntryIndex = 0; |
2146 | } else if (aIndex < mLoadedEntryIndex) { |
2147 | --mLoadedEntryIndex; |
2148 | } |
2149 | |
2150 | for (auto* child : mChildList.ForwardRange()) { |
2151 | nsCOMPtr<nsIDocShell> shell = do_QueryObject(child); |
2152 | if (shell) { |
2153 | static_cast<nsDocShell*>(shell.get())->HistoryEntryRemoved(aIndex); |
2154 | } |
2155 | } |
2156 | |
2157 | return NS_OK; |
2158 | } |
2159 | |
2160 | nsresult nsDocShell::Now(DOMHighResTimeStamp* aWhen) { |
2161 | *aWhen = (TimeStamp::Now() - TimeStamp::ProcessCreation()).ToMilliseconds(); |
2162 | return NS_OK; |
2163 | } |
2164 | |
2165 | NS_IMETHODIMPnsresult |
2166 | nsDocShell::SetWindowDraggingAllowed(bool aValue) { |
2167 | RefPtr<nsDocShell> parent = GetInProcessParentDocshell(); |
2168 | if (!aValue && mItemType == typeChrome && !parent) { |
2169 | // Window dragging is always allowed for top level |
2170 | // chrome docshells. |
2171 | return NS_ERROR_FAILURE; |
2172 | } |
2173 | mWindowDraggingAllowed = aValue; |
2174 | return NS_OK; |
2175 | } |
2176 | |
2177 | NS_IMETHODIMPnsresult |
2178 | nsDocShell::GetWindowDraggingAllowed(bool* aValue) { |
2179 | // window dragging regions in CSS (-moz-window-drag:drag) |
2180 | // can be slow. Default behavior is to only allow it for |
2181 | // chrome top level windows. |
2182 | RefPtr<nsDocShell> parent = GetInProcessParentDocshell(); |
2183 | if (mItemType == typeChrome && !parent) { |
2184 | // Top level chrome window |
2185 | *aValue = true; |
2186 | } else { |
2187 | *aValue = mWindowDraggingAllowed; |
2188 | } |
2189 | return NS_OK; |
2190 | } |
2191 | |
2192 | NS_IMETHODIMPnsresult |
2193 | nsDocShell::GetCurrentDocumentChannel(nsIChannel** aResult) { |
2194 | NS_IF_ADDREF(*aResult = GetCurrentDocChannel())ns_if_addref(*aResult = GetCurrentDocChannel()); |
2195 | return NS_OK; |
2196 | } |
2197 | |
2198 | nsIChannel* nsDocShell::GetCurrentDocChannel() { |
2199 | if (mDocumentViewer) { |
2200 | Document* doc = mDocumentViewer->GetDocument(); |
2201 | if (doc) { |
2202 | return doc->GetChannel(); |
2203 | } |
2204 | } |
2205 | return nullptr; |
2206 | } |
2207 | |
2208 | NS_IMETHODIMPnsresult |
2209 | nsDocShell::AddWeakScrollObserver(nsIScrollObserver* aObserver) { |
2210 | nsWeakPtr weakObs = do_GetWeakReference(aObserver); |
2211 | if (!weakObs) { |
2212 | return NS_ERROR_FAILURE; |
2213 | } |
2214 | mScrollObservers.AppendElement(weakObs); |
2215 | return NS_OK; |
2216 | } |
2217 | |
2218 | NS_IMETHODIMPnsresult |
2219 | nsDocShell::RemoveWeakScrollObserver(nsIScrollObserver* aObserver) { |
2220 | nsWeakPtr obs = do_GetWeakReference(aObserver); |
2221 | return mScrollObservers.RemoveElement(obs) ? NS_OK : NS_ERROR_FAILURE; |
2222 | } |
2223 | |
2224 | void nsDocShell::NotifyAsyncPanZoomStarted() { |
2225 | nsTObserverArray<nsWeakPtr>::ForwardIterator iter(mScrollObservers); |
2226 | while (iter.HasMore()) { |
2227 | nsWeakPtr ref = iter.GetNext(); |
2228 | nsCOMPtr<nsIScrollObserver> obs = do_QueryReferent(ref); |
2229 | if (obs) { |
2230 | obs->AsyncPanZoomStarted(); |
2231 | } else { |
2232 | iter.Remove(); |
2233 | } |
2234 | } |
2235 | } |
2236 | |
2237 | void nsDocShell::NotifyAsyncPanZoomStopped() { |
2238 | nsTObserverArray<nsWeakPtr>::ForwardIterator iter(mScrollObservers); |
2239 | while (iter.HasMore()) { |
2240 | nsWeakPtr ref = iter.GetNext(); |
2241 | nsCOMPtr<nsIScrollObserver> obs = do_QueryReferent(ref); |
2242 | if (obs) { |
2243 | obs->AsyncPanZoomStopped(); |
2244 | } else { |
2245 | iter.Remove(); |
2246 | } |
2247 | } |
2248 | } |
2249 | |
2250 | NS_IMETHODIMPnsresult |
2251 | nsDocShell::NotifyScrollObservers() { |
2252 | nsTObserverArray<nsWeakPtr>::ForwardIterator iter(mScrollObservers); |
2253 | while (iter.HasMore()) { |
2254 | nsWeakPtr ref = iter.GetNext(); |
2255 | nsCOMPtr<nsIScrollObserver> obs = do_QueryReferent(ref); |
2256 | if (obs) { |
2257 | obs->ScrollPositionChanged(); |
2258 | } else { |
2259 | iter.Remove(); |
2260 | } |
2261 | } |
2262 | return NS_OK; |
2263 | } |
2264 | |
2265 | //***************************************************************************** |
2266 | // nsDocShell::nsIDocShellTreeItem |
2267 | //***************************************************************************** |
2268 | |
2269 | NS_IMETHODIMPnsresult |
2270 | nsDocShell::GetName(nsAString& aName) { |
2271 | aName = mBrowsingContext->Name(); |
2272 | return NS_OK; |
2273 | } |
2274 | |
2275 | NS_IMETHODIMPnsresult |
2276 | nsDocShell::SetName(const nsAString& aName) { |
2277 | return mBrowsingContext->SetName(aName); |
2278 | } |
2279 | |
2280 | NS_IMETHODIMPnsresult |
2281 | nsDocShell::NameEquals(const nsAString& aName, bool* aResult) { |
2282 | NS_ENSURE_ARG_POINTER(aResult)do { if ((__builtin_expect(!!(!(aResult)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aResult" ") failed", nullptr , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 2282); return NS_ERROR_INVALID_POINTER; } } while (false); |
2283 | *aResult = mBrowsingContext->NameEquals(aName); |
2284 | return NS_OK; |
2285 | } |
2286 | |
2287 | NS_IMETHODIMPnsresult |
2288 | nsDocShell::GetCustomUserAgent(nsAString& aCustomUserAgent) { |
2289 | mBrowsingContext->GetCustomUserAgent(aCustomUserAgent); |
2290 | return NS_OK; |
2291 | } |
2292 | |
2293 | NS_IMETHODIMPnsresult |
2294 | nsDocShell::SetCustomUserAgent(const nsAString& aCustomUserAgent) { |
2295 | if (mWillChangeProcess) { |
2296 | NS_WARNING("SetCustomUserAgent: Process is changing. Ignoring set")NS_DebugBreak(NS_DEBUG_WARNING, "SetCustomUserAgent: Process is changing. Ignoring set" , nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 2296); |
2297 | return NS_ERROR_FAILURE; |
2298 | } |
2299 | |
2300 | return mBrowsingContext->SetCustomUserAgent(aCustomUserAgent); |
2301 | } |
2302 | |
2303 | NS_IMETHODIMPnsresult |
2304 | nsDocShell::ClearCachedPlatform() { |
2305 | nsCOMPtr<nsPIDOMWindowInner> win = |
2306 | mScriptGlobal ? mScriptGlobal->GetCurrentInnerWindow() : nullptr; |
2307 | if (win) { |
2308 | Navigator* navigator = win->Navigator(); |
2309 | if (navigator) { |
2310 | navigator->ClearPlatformCache(); |
2311 | } |
2312 | } |
2313 | |
2314 | return NS_OK; |
2315 | } |
2316 | |
2317 | NS_IMETHODIMPnsresult |
2318 | nsDocShell::ClearCachedUserAgent() { |
2319 | nsCOMPtr<nsPIDOMWindowInner> win = |
2320 | mScriptGlobal ? mScriptGlobal->GetCurrentInnerWindow() : nullptr; |
2321 | if (win) { |
2322 | Navigator* navigator = win->Navigator(); |
2323 | if (navigator) { |
2324 | navigator->ClearUserAgentCache(); |
2325 | } |
2326 | } |
2327 | |
2328 | return NS_OK; |
2329 | } |
2330 | |
2331 | /* virtual */ |
2332 | int32_t nsDocShell::ItemType() { return mItemType; } |
2333 | |
2334 | NS_IMETHODIMPnsresult |
2335 | nsDocShell::GetItemType(int32_t* aItemType) { |
2336 | NS_ENSURE_ARG_POINTER(aItemType)do { if ((__builtin_expect(!!(!(aItemType)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aItemType" ") failed", nullptr , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 2336); return NS_ERROR_INVALID_POINTER; } } while (false); |
2337 | |
2338 | 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" , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 2339); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "(mBrowsingContext->IsContent() ? typeContent : typeChrome) == mItemType" ")"); do { *((volatile int*)__null) = 2339; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
2339 | (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" , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 2339); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "(mBrowsingContext->IsContent() ? typeContent : typeChrome) == mItemType" ")"); do { *((volatile int*)__null) = 2339; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2340 | *aItemType = mItemType; |
2341 | return NS_OK; |
2342 | } |
2343 | |
2344 | NS_IMETHODIMPnsresult |
2345 | nsDocShell::GetInProcessParent(nsIDocShellTreeItem** aParent) { |
2346 | if (!mParent) { |
2347 | *aParent = nullptr; |
2348 | } else { |
2349 | CallQueryInterface(mParent, aParent); |
2350 | } |
2351 | // Note that in the case when the parent is not an nsIDocShellTreeItem we |
2352 | // don't want to throw; we just want to return null. |
2353 | return NS_OK; |
2354 | } |
2355 | |
2356 | // With Fission, related nsDocShell objects may exist in a different process. In |
2357 | // that case, this method will return `nullptr`, despite a parent nsDocShell |
2358 | // object existing. |
2359 | // |
2360 | // Prefer using `BrowsingContext::Parent()`, which will succeed even if the |
2361 | // parent entry is not in the current process, and handle the case where the |
2362 | // parent nsDocShell is inaccessible. |
2363 | already_AddRefed<nsDocShell> nsDocShell::GetInProcessParentDocshell() { |
2364 | nsCOMPtr<nsIDocShell> docshell = do_QueryInterface(GetAsSupports(mParent)); |
2365 | return docshell.forget().downcast<nsDocShell>(); |
2366 | } |
2367 | |
2368 | void nsDocShell::MaybeCreateInitialClientSource(nsIPrincipal* aPrincipal) { |
2369 | 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" , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 2369); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mIsBeingDestroyed" ")"); do { *((volatile int*)__null) = 2369; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2370 | |
2371 | // If there is an existing document then there is no need to create |
2372 | // a client for a future initial about:blank document. |
2373 | if (mScriptGlobal && mScriptGlobal->GetCurrentInnerWindow() && |
2374 | mScriptGlobal->GetCurrentInnerWindow()->GetExtantDoc()) { |
2375 | 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()" , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 2376); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "mScriptGlobal->GetCurrentInnerWindow()->GetClientInfo().isSome()" ")"); do { *((volatile int*)__null) = 2376; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
2376 | 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()" , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 2376); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "mScriptGlobal->GetCurrentInnerWindow()->GetClientInfo().isSome()" ")"); do { *((volatile int*)__null) = 2376; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2377 | 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" , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 2377); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "!mInitialClientSource" ")"); do { *((volatile int*)__null) = 2377; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2378 | return; |
2379 | } |
2380 | |
2381 | // Don't recreate the initial client source. We call this multiple times |
2382 | // when DoChannelLoad() is called before CreateAboutBlankDocumentViewer. |
2383 | if (mInitialClientSource) { |
2384 | return; |
2385 | } |
2386 | |
2387 | // Don't pre-allocate the client when we are sandboxed. The inherited |
2388 | // principal does not take sandboxing into account. |
2389 | // TODO: Refactor sandboxing principal code out so we can use it here. |
2390 | if (!aPrincipal && mBrowsingContext->GetSandboxFlags()) { |
2391 | return; |
2392 | } |
2393 | |
2394 | // We cannot get inherited foreign partitioned principal here. Instead, we |
2395 | // directly check which principal we want to inherit for the service worker. |
2396 | nsIPrincipal* principal = |
2397 | aPrincipal |
2398 | ? aPrincipal |
2399 | : GetInheritedPrincipal( |
2400 | false, StoragePrincipalHelper:: |
2401 | ShouldUsePartitionPrincipalForServiceWorker(this)); |
2402 | |
2403 | // Sometimes there is no principal available when we are called from |
2404 | // CreateAboutBlankDocumentViewer. For example, sometimes the principal |
2405 | // is only extracted from the load context after the document is created |
2406 | // in Document::ResetToURI(). Ideally we would do something similar |
2407 | // here, but for now lets just avoid the issue by not preallocating the |
2408 | // client. |
2409 | if (!principal) { |
2410 | return; |
2411 | } |
2412 | |
2413 | nsCOMPtr<nsPIDOMWindowOuter> win = GetWindow(); |
2414 | if (!win) { |
2415 | return; |
2416 | } |
2417 | |
2418 | mInitialClientSource = ClientManager::CreateSource( |
2419 | ClientType::Window, GetMainThreadSerialEventTarget(), principal); |
2420 | 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" , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 2420); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "mInitialClientSource" ")"); do { *((volatile int*)__null) = 2420; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2421 | |
2422 | // Mark the initial client as execution ready, but owned by the docshell. |
2423 | // If the client is actually used this will cause ClientSource to force |
2424 | // the creation of the initial about:blank by calling |
2425 | // nsDocShell::GetDocument(). |
2426 | mInitialClientSource->DocShellExecutionReady(this); |
2427 | |
2428 | // Next, check to see if the parent is controlled. |
2429 | nsCOMPtr<nsIDocShell> parent = GetInProcessParentDocshell(); |
2430 | nsPIDOMWindowOuter* parentOuter = parent ? parent->GetWindow() : nullptr; |
2431 | nsPIDOMWindowInner* parentInner = |
2432 | parentOuter ? parentOuter->GetCurrentInnerWindow() : nullptr; |
2433 | if (!parentInner) { |
2434 | return; |
2435 | } |
2436 | |
2437 | nsCOMPtr<nsIURI> uri; |
2438 | 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 { static_assert( mozilla::detail::AssertionConditionType <decltype(false)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("false" " (" "NS_SUCCEEDED(NS_NewURI(getter_AddRefs(uri), \"about:blank\"_ns))" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 2438); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false" ") (" "NS_SUCCEEDED(NS_NewURI(getter_AddRefs(uri), \"about:blank\"_ns))" ")"); do { *((volatile int*)__null) = 2438; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); |
2439 | |
2440 | // We're done if there is no parent controller or if this docshell |
2441 | // is not permitted to control for some reason. |
2442 | Maybe<ServiceWorkerDescriptor> controller(parentInner->GetController()); |
2443 | if (controller.isNothing() || |
2444 | !ServiceWorkerAllowedToControlWindow(principal, uri)) { |
2445 | return; |
2446 | } |
2447 | |
2448 | mInitialClientSource->InheritController(controller.ref()); |
2449 | } |
2450 | |
2451 | Maybe<ClientInfo> nsDocShell::GetInitialClientInfo() const { |
2452 | if (mInitialClientSource) { |
2453 | Maybe<ClientInfo> result; |
2454 | result.emplace(mInitialClientSource->Info()); |
2455 | return result; |
2456 | } |
2457 | |
2458 | nsPIDOMWindowInner* innerWindow = |
2459 | mScriptGlobal ? mScriptGlobal->GetCurrentInnerWindow() : nullptr; |
2460 | Document* doc = innerWindow ? innerWindow->GetExtantDoc() : nullptr; |
2461 | |
2462 | if (!doc || !doc->IsInitialDocument()) { |
2463 | return Maybe<ClientInfo>(); |
2464 | } |
2465 | |
2466 | return innerWindow->GetClientInfo(); |
2467 | } |
2468 | |
2469 | nsresult nsDocShell::SetDocLoaderParent(nsDocLoader* aParent) { |
2470 | bool wasFrame = IsSubframe(); |
2471 | |
2472 | nsresult rv = nsDocLoader::SetDocLoaderParent(aParent); |
2473 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 2473); return rv; } } while (false); |
2474 | |
2475 | nsCOMPtr<nsISupportsPriority> priorityGroup = do_QueryInterface(mLoadGroup); |
2476 | if (wasFrame != IsSubframe() && priorityGroup) { |
2477 | priorityGroup->AdjustPriority(wasFrame ? -1 : 1); |
2478 | } |
2479 | |
2480 | // Curse ambiguous nsISupports inheritance! |
2481 | nsISupports* parent = GetAsSupports(aParent); |
2482 | |
2483 | // If parent is another docshell, we inherit all their flags for |
2484 | // allowing plugins, scripting etc. |
2485 | bool value; |
2486 | nsCOMPtr<nsIDocShell> parentAsDocShell(do_QueryInterface(parent)); |
2487 | |
2488 | if (parentAsDocShell) { |
2489 | if (mAllowMetaRedirects && |
2490 | NS_SUCCEEDED(parentAsDocShell->GetAllowMetaRedirects(&value))((bool)(__builtin_expect(!!(!NS_FAILED_impl(parentAsDocShell-> GetAllowMetaRedirects(&value))), 1)))) { |
2491 | SetAllowMetaRedirects(value); |
2492 | } |
2493 | if (mAllowSubframes && |
2494 | NS_SUCCEEDED(parentAsDocShell->GetAllowSubframes(&value))((bool)(__builtin_expect(!!(!NS_FAILED_impl(parentAsDocShell-> GetAllowSubframes(&value))), 1)))) { |
2495 | SetAllowSubframes(value); |
2496 | } |
2497 | if (mAllowImages && |
2498 | NS_SUCCEEDED(parentAsDocShell->GetAllowImages(&value))((bool)(__builtin_expect(!!(!NS_FAILED_impl(parentAsDocShell-> GetAllowImages(&value))), 1)))) { |
2499 | SetAllowImages(value); |
2500 | } |
2501 | SetAllowMedia(parentAsDocShell->GetAllowMedia() && mAllowMedia); |
2502 | if (mAllowWindowControl && |
2503 | NS_SUCCEEDED(parentAsDocShell->GetAllowWindowControl(&value))((bool)(__builtin_expect(!!(!NS_FAILED_impl(parentAsDocShell-> GetAllowWindowControl(&value))), 1)))) { |
2504 | SetAllowWindowControl(value); |
2505 | } |
2506 | if (NS_FAILED(parentAsDocShell->GetAllowDNSPrefetch(&value))((bool)(__builtin_expect(!!(NS_FAILED_impl(parentAsDocShell-> GetAllowDNSPrefetch(&value))), 0)))) { |
2507 | value = false; |
2508 | } |
2509 | SetAllowDNSPrefetch(mAllowDNSPrefetch && value); |
2510 | } |
2511 | |
2512 | nsCOMPtr<nsIURIContentListener> parentURIListener(do_GetInterface(parent)); |
2513 | if (parentURIListener) { |
2514 | mContentListener->SetParentContentListener(parentURIListener); |
2515 | } |
2516 | |
2517 | return NS_OK; |
2518 | } |
2519 | |
2520 | void nsDocShell::MaybeRestoreWindowName() { |
2521 | if (!StaticPrefs::privacy_window_name_update_enabled()) { |
2522 | return; |
2523 | } |
2524 | |
2525 | // We only restore window.name for the top-level content. |
2526 | if (!mBrowsingContext->IsTopContent()) { |
2527 | return; |
2528 | } |
2529 | |
2530 | nsAutoString name; |
2531 | |
2532 | // Following implements https://html.spec.whatwg.org/#history-traversal: |
2533 | // Step 4.4. Check if the loading entry has a name. |
2534 | |
2535 | if (mLSHE) { |
2536 | mLSHE->GetName(name); |
2537 | } |
2538 | |
2539 | if (mLoadingEntry) { |
2540 | name = mLoadingEntry->mInfo.GetName(); |
2541 | } |
2542 | |
2543 | if (name.IsEmpty()) { |
2544 | return; |
2545 | } |
2546 | |
2547 | // Step 4.4.1. Set the name to the browsing context. |
2548 | Unused << mBrowsingContext->SetName(name); |
2549 | |
2550 | // Step 4.4.2. Clear the name of all entries that are contiguous and |
2551 | // same-origin with the loading entry. |
2552 | if (mLSHE) { |
2553 | nsSHistory::WalkContiguousEntries( |
2554 | mLSHE, [](nsISHEntry* aEntry) { aEntry->SetName(EmptyString()); }); |
2555 | } |
2556 | |
2557 | if (mLoadingEntry) { |
2558 | // Clear the name of the session entry in the child side. For parent side, |
2559 | // the clearing will be done when we commit the history to the parent. |
2560 | mLoadingEntry->mInfo.SetName(EmptyString()); |
2561 | } |
2562 | } |
2563 | |
2564 | void nsDocShell::StoreWindowNameToSHEntries() { |
2565 | 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()", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 2565); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mBrowsingContext->IsTopContent()" ")"); do { *((volatile int*)__null) = 2565; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2566 | |
2567 | nsAutoString name; |
2568 | mBrowsingContext->GetName(name); |
2569 | |
2570 | if (mOSHE) { |
2571 | nsSHistory::WalkContiguousEntries( |
2572 | mOSHE, [&](nsISHEntry* aEntry) { aEntry->SetName(name); }); |
2573 | } |
2574 | |
2575 | if (mozilla::SessionHistoryInParent()) { |
2576 | if (XRE_IsParentProcess()) { |
2577 | SessionHistoryEntry* entry = |
2578 | mBrowsingContext->Canonical()->GetActiveSessionHistoryEntry(); |
2579 | if (entry) { |
2580 | nsSHistory::WalkContiguousEntries( |
2581 | entry, [&](nsISHEntry* aEntry) { aEntry->SetName(name); }); |
2582 | } |
2583 | } else { |
2584 | // Ask parent process to store the name in entries. |
2585 | mozilla::Unused |
2586 | << ContentChild::GetSingleton() |
2587 | ->SendSessionHistoryEntryStoreWindowNameInContiguousEntries( |
2588 | mBrowsingContext, name); |
2589 | } |
2590 | } |
2591 | } |
2592 | |
2593 | NS_IMETHODIMPnsresult |
2594 | nsDocShell::GetInProcessSameTypeParent(nsIDocShellTreeItem** aParent) { |
2595 | if (BrowsingContext* parentBC = mBrowsingContext->GetParent()) { |
2596 | *aParent = do_AddRef(parentBC->GetDocShell()).take(); |
2597 | } |
2598 | return NS_OK; |
2599 | } |
2600 | |
2601 | NS_IMETHODIMPnsresult |
2602 | nsDocShell::GetInProcessRootTreeItem(nsIDocShellTreeItem** aRootTreeItem) { |
2603 | NS_ENSURE_ARG_POINTER(aRootTreeItem)do { if ((__builtin_expect(!!(!(aRootTreeItem)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aRootTreeItem" ") failed" , nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 2603); return NS_ERROR_INVALID_POINTER; } } while (false); |
2604 | |
2605 | RefPtr<nsDocShell> root = this; |
2606 | RefPtr<nsDocShell> parent = root->GetInProcessParentDocshell(); |
2607 | while (parent) { |
2608 | root = parent; |
2609 | parent = root->GetInProcessParentDocshell(); |
2610 | } |
2611 | |
2612 | root.forget(aRootTreeItem); |
2613 | return NS_OK; |
2614 | } |
2615 | |
2616 | NS_IMETHODIMPnsresult |
2617 | nsDocShell::GetInProcessSameTypeRootTreeItem( |
2618 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 2619); return NS_ERROR_INVALID_POINTER; } } while (false); |
2620 | *aRootTreeItem = static_cast<nsIDocShellTreeItem*>(this); |
2621 | |
2622 | nsCOMPtr<nsIDocShellTreeItem> parent; |
2623 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 2624); return NS_ERROR_FAILURE; } } while (false) |
2624 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 2624); return NS_ERROR_FAILURE; } } while (false); |
2625 | while (parent) { |
2626 | *aRootTreeItem = parent; |
2627 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 2629); return NS_ERROR_FAILURE; } } while (false) |
2628 | (*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, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 2629); return NS_ERROR_FAILURE; } } while (false) |
2629 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 2629); return NS_ERROR_FAILURE; } } while (false); |
2630 | } |
2631 | NS_ADDREF(*aRootTreeItem)(*aRootTreeItem)->AddRef(); |
2632 | return NS_OK; |
2633 | } |
2634 | |
2635 | NS_IMETHODIMPnsresult |
2636 | nsDocShell::GetTreeOwner(nsIDocShellTreeOwner** aTreeOwner) { |
2637 | NS_ENSURE_ARG_POINTER(aTreeOwner)do { if ((__builtin_expect(!!(!(aTreeOwner)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aTreeOwner" ") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 2637); return NS_ERROR_INVALID_POINTER; } } while (false); |
2638 | |
2639 | *aTreeOwner = mTreeOwner; |
2640 | NS_IF_ADDREF(*aTreeOwner)ns_if_addref(*aTreeOwner); |
2641 | return NS_OK; |
2642 | } |
2643 | |
2644 | NS_IMETHODIMPnsresult |
2645 | nsDocShell::SetTreeOwner(nsIDocShellTreeOwner* aTreeOwner) { |
2646 | if (mIsBeingDestroyed && aTreeOwner) { |
2647 | return NS_ERROR_FAILURE; |
2648 | } |
2649 | |
2650 | // Don't automatically set the progress based on the tree owner for frames |
2651 | if (!IsSubframe()) { |
2652 | nsCOMPtr<nsIWebProgress> webProgress = |
2653 | do_QueryInterface(GetAsSupports(this)); |
2654 | |
2655 | if (webProgress) { |
2656 | nsCOMPtr<nsIWebProgressListener> oldListener = |
2657 | do_QueryInterface(mTreeOwner); |
2658 | nsCOMPtr<nsIWebProgressListener> newListener = |
2659 | do_QueryInterface(aTreeOwner); |
2660 | |
2661 | if (oldListener) { |
2662 | webProgress->RemoveProgressListener(oldListener); |
2663 | } |
2664 | |
2665 | if (newListener) { |
2666 | webProgress->AddProgressListener(newListener, |
2667 | nsIWebProgress::NOTIFY_ALL); |
2668 | } |
2669 | } |
2670 | } |
2671 | |
2672 | mTreeOwner = aTreeOwner; // Weak reference per API |
2673 | |
2674 | for (auto* childDocLoader : mChildList.ForwardRange()) { |
2675 | nsCOMPtr<nsIDocShellTreeItem> child = do_QueryObject(childDocLoader); |
2676 | NS_ENSURE_TRUE(child, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(child)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "child" ") failed", nullptr , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 2676); return NS_ERROR_FAILURE; } } while (false); |
2677 | |
2678 | if (child->ItemType() == mItemType) { |
2679 | child->SetTreeOwner(aTreeOwner); |
2680 | } |
2681 | } |
2682 | |
2683 | // If we're in the content process and have had a TreeOwner set on us, extract |
2684 | // our BrowserChild actor. If we've already had our BrowserChild set, assert |
2685 | // that it hasn't changed. |
2686 | if (mTreeOwner && XRE_IsContentProcess()) { |
2687 | nsCOMPtr<nsIBrowserChild> newBrowserChild = do_GetInterface(mTreeOwner); |
2688 | 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!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 2689); AnnotateMozCrashReason("MOZ_ASSERT" "(" "newBrowserChild" ") (" "No BrowserChild actor for tree owner in Content!" ")" ); do { *((volatile int*)__null) = 2689; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
2689 | "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!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 2689); AnnotateMozCrashReason("MOZ_ASSERT" "(" "newBrowserChild" ") (" "No BrowserChild actor for tree owner in Content!" ")" ); do { *((volatile int*)__null) = 2689; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2690 | |
2691 | if (mBrowserChild) { |
2692 | nsCOMPtr<nsIBrowserChild> oldBrowserChild = |
2693 | do_QueryReferent(mBrowserChild); |
2694 | 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!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 2696); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "oldBrowserChild == newBrowserChild" ") (" "Cannot change BrowserChild during nsDocShell lifetime!" ")"); do { *((volatile int*)__null) = 2696; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
2695 | 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!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 2696); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "oldBrowserChild == newBrowserChild" ") (" "Cannot change BrowserChild during nsDocShell lifetime!" ")"); do { *((volatile int*)__null) = 2696; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
2696 | "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!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 2696); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "oldBrowserChild == newBrowserChild" ") (" "Cannot change BrowserChild during nsDocShell lifetime!" ")"); do { *((volatile int*)__null) = 2696; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2697 | } else { |
2698 | mBrowserChild = do_GetWeakReference(newBrowserChild); |
2699 | } |
2700 | } |
2701 | |
2702 | return NS_OK; |
2703 | } |
2704 | |
2705 | NS_IMETHODIMPnsresult |
2706 | nsDocShell::GetHistoryID(nsID& aID) { |
2707 | aID = mBrowsingContext->GetHistoryID(); |
2708 | return NS_OK; |
2709 | } |
2710 | |
2711 | const nsID& nsDocShell::HistoryID() { return mBrowsingContext->GetHistoryID(); } |
2712 | |
2713 | NS_IMETHODIMPnsresult |
2714 | nsDocShell::GetIsInUnload(bool* aIsInUnload) { |
2715 | *aIsInUnload = mFiredUnloadEvent; |
2716 | return NS_OK; |
2717 | } |
2718 | |
2719 | NS_IMETHODIMPnsresult |
2720 | nsDocShell::GetInProcessChildCount(int32_t* aChildCount) { |
2721 | NS_ENSURE_ARG_POINTER(aChildCount)do { if ((__builtin_expect(!!(!(aChildCount)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aChildCount" ") failed" , nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 2721); return NS_ERROR_INVALID_POINTER; } } while (false); |
2722 | *aChildCount = mChildList.Length(); |
2723 | return NS_OK; |
2724 | } |
2725 | |
2726 | NS_IMETHODIMPnsresult |
2727 | nsDocShell::AddChild(nsIDocShellTreeItem* aChild) { |
2728 | NS_ENSURE_ARG_POINTER(aChild)do { if ((__builtin_expect(!!(!(aChild)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aChild" ") failed", nullptr , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 2728); return NS_ERROR_INVALID_POINTER; } } while (false); |
2729 | |
2730 | RefPtr<nsDocLoader> childAsDocLoader = GetAsDocLoader(aChild); |
2731 | NS_ENSURE_TRUE(childAsDocLoader, NS_ERROR_UNEXPECTED)do { if ((__builtin_expect(!!(!(childAsDocLoader)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "childAsDocLoader" ") failed" , nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 2731); return NS_ERROR_UNEXPECTED; } } while (false); |
2732 | |
2733 | // Make sure we're not creating a loop in the docshell tree |
2734 | nsDocLoader* ancestor = this; |
2735 | do { |
2736 | if (childAsDocLoader == ancestor) { |
2737 | return NS_ERROR_ILLEGAL_VALUE; |
2738 | } |
2739 | ancestor = ancestor->GetParent(); |
2740 | } while (ancestor); |
2741 | |
2742 | // Make sure to remove the child from its current parent. |
2743 | nsDocLoader* childsParent = childAsDocLoader->GetParent(); |
2744 | if (childsParent) { |
2745 | nsresult rv = childsParent->RemoveChildLoader(childAsDocLoader); |
2746 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 2746); return rv; } } while (false); |
2747 | } |
2748 | |
2749 | // Make sure to clear the treeowner in case this child is a different type |
2750 | // from us. |
2751 | aChild->SetTreeOwner(nullptr); |
2752 | |
2753 | nsresult res = AddChildLoader(childAsDocLoader); |
2754 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 2754); return res; } } while (false); |
2755 | 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()" , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 2756); MOZ_PretendNoReturn(); } } while (0) |
2756 | "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()" , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 2756); MOZ_PretendNoReturn(); } } while (0); |
2757 | |
2758 | /* Set the child's global history if the parent has one */ |
2759 | if (mBrowsingContext->GetUseGlobalHistory()) { |
2760 | // childDocShell->SetUseGlobalHistory(true); |
2761 | // this should be set through BC inherit |
2762 | 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()", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 2762); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aChild->GetBrowsingContext()->GetUseGlobalHistory()" ")"); do { *((volatile int*)__null) = 2762; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2763 | } |
2764 | |
2765 | if (aChild->ItemType() != mItemType) { |
2766 | return NS_OK; |
2767 | } |
2768 | |
2769 | aChild->SetTreeOwner(mTreeOwner); |
2770 | |
2771 | nsCOMPtr<nsIDocShell> childAsDocShell(do_QueryInterface(aChild)); |
2772 | if (!childAsDocShell) { |
2773 | return NS_OK; |
2774 | } |
2775 | |
2776 | // charset, style-disabling, and zoom will be inherited in SetupNewViewer() |
2777 | |
2778 | // Now take this document's charset and set the child's parentCharset field |
2779 | // to it. We'll later use that field, in the loading process, for the |
2780 | // charset choosing algorithm. |
2781 | // If we fail, at any point, we just return NS_OK. |
2782 | // This code has some performance impact. But this will be reduced when |
2783 | // the current charset will finally be stored as an Atom, avoiding the |
2784 | // alias resolution extra look-up. |
2785 | |
2786 | // we are NOT going to propagate the charset is this Chrome's docshell |
2787 | if (mItemType == nsIDocShellTreeItem::typeChrome) { |
2788 | return NS_OK; |
2789 | } |
2790 | |
2791 | // get the parent's current charset |
2792 | if (!mDocumentViewer) { |
2793 | return NS_OK; |
2794 | } |
2795 | Document* doc = mDocumentViewer->GetDocument(); |
2796 | if (!doc) { |
2797 | return NS_OK; |
2798 | } |
2799 | |
2800 | const Encoding* parentCS = doc->GetDocumentCharacterSet(); |
2801 | int32_t charsetSource = doc->GetDocumentCharacterSetSource(); |
2802 | // set the child's parentCharset |
2803 | childAsDocShell->SetParentCharset(parentCS, charsetSource, |
2804 | doc->NodePrincipal()); |
2805 | |
2806 | // printf("### 1 >>> Adding child. Parent CS = %s. ItemType = %d.\n", |
2807 | // NS_LossyConvertUTF16toASCII(parentCS).get(), mItemType); |
2808 | |
2809 | return NS_OK; |
2810 | } |
2811 | |
2812 | NS_IMETHODIMPnsresult |
2813 | nsDocShell::RemoveChild(nsIDocShellTreeItem* aChild) { |
2814 | NS_ENSURE_ARG_POINTER(aChild)do { if ((__builtin_expect(!!(!(aChild)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aChild" ") failed", nullptr , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 2814); return NS_ERROR_INVALID_POINTER; } } while (false); |
2815 | |
2816 | RefPtr<nsDocLoader> childAsDocLoader = GetAsDocLoader(aChild); |
2817 | NS_ENSURE_TRUE(childAsDocLoader, NS_ERROR_UNEXPECTED)do { if ((__builtin_expect(!!(!(childAsDocLoader)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "childAsDocLoader" ") failed" , nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 2817); return NS_ERROR_UNEXPECTED; } } while (false); |
2818 | |
2819 | nsresult rv = RemoveChildLoader(childAsDocLoader); |
2820 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 2820); return rv; } } while (false); |
2821 | |
2822 | aChild->SetTreeOwner(nullptr); |
2823 | |
2824 | return nsDocLoader::AddDocLoaderAsChildOfRoot(childAsDocLoader); |
2825 | } |
2826 | |
2827 | NS_IMETHODIMPnsresult |
2828 | nsDocShell::GetInProcessChildAt(int32_t aIndex, nsIDocShellTreeItem** aChild) { |
2829 | NS_ENSURE_ARG_POINTER(aChild)do { if ((__builtin_expect(!!(!(aChild)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aChild" ") failed", nullptr , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 2829); return NS_ERROR_INVALID_POINTER; } } while (false); |
2830 | |
2831 | RefPtr<nsDocShell> child = GetInProcessChildAt(aIndex); |
2832 | NS_ENSURE_TRUE(child, NS_ERROR_UNEXPECTED)do { if ((__builtin_expect(!!(!(child)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "child" ") failed", nullptr , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 2832); return NS_ERROR_UNEXPECTED; } } while (false); |
2833 | |
2834 | child.forget(aChild); |
2835 | |
2836 | return NS_OK; |
2837 | } |
2838 | |
2839 | nsDocShell* nsDocShell::GetInProcessChildAt(int32_t aIndex) { |
2840 | #ifdef DEBUG1 |
2841 | if (aIndex < 0) { |
2842 | NS_WARNING("Negative index passed to GetChildAt")NS_DebugBreak(NS_DEBUG_WARNING, "Negative index passed to GetChildAt" , nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 2842); |
2843 | } else if (static_cast<uint32_t>(aIndex) >= mChildList.Length()) { |
2844 | NS_WARNING("Too large an index passed to GetChildAt")NS_DebugBreak(NS_DEBUG_WARNING, "Too large an index passed to GetChildAt" , nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 2844); |
2845 | } |
2846 | #endif |
2847 | |
2848 | nsIDocumentLoader* child = ChildAt(aIndex); |
2849 | |
2850 | // child may be nullptr here. |
2851 | return static_cast<nsDocShell*>(child); |
2852 | } |
2853 | |
2854 | nsresult nsDocShell::AddChildSHEntry(nsISHEntry* aCloneRef, |
2855 | nsISHEntry* aNewEntry, |
2856 | int32_t aChildOffset, uint32_t aLoadType, |
2857 | bool aCloneChildren) { |
2858 | 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()", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 2858); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()" ")"); do { *((volatile int*)__null) = 2858; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2859 | nsresult rv = NS_OK; |
2860 | |
2861 | if (mLSHE && aLoadType != LOAD_PUSHSTATE) { |
2862 | /* You get here if you are currently building a |
2863 | * hierarchy ie.,you just visited a frameset page |
2864 | */ |
2865 | if (NS_FAILED(mLSHE->ReplaceChild(aNewEntry))((bool)(__builtin_expect(!!(NS_FAILED_impl(mLSHE->ReplaceChild (aNewEntry))), 0)))) { |
2866 | rv = mLSHE->AddChild(aNewEntry, aChildOffset); |
2867 | } |
2868 | } else if (!aCloneRef) { |
2869 | /* This is an initial load in some subframe. Just append it if we can */ |
2870 | if (mOSHE) { |
2871 | rv = mOSHE->AddChild(aNewEntry, aChildOffset, UseRemoteSubframes()); |
2872 | } |
2873 | } else { |
2874 | RefPtr<ChildSHistory> shistory = GetRootSessionHistory(); |
2875 | if (shistory) { |
2876 | rv = shistory->LegacySHistory()->AddChildSHEntryHelper( |
2877 | aCloneRef, aNewEntry, mBrowsingContext->Top(), aCloneChildren); |
2878 | } |
2879 | } |
2880 | return rv; |
2881 | } |
2882 | |
2883 | nsresult nsDocShell::AddChildSHEntryToParent(nsISHEntry* aNewEntry, |
2884 | int32_t aChildOffset, |
2885 | bool aCloneChildren) { |
2886 | 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()", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 2886); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()" ")"); do { *((volatile int*)__null) = 2886; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2887 | /* You will get here when you are in a subframe and |
2888 | * a new url has been loaded on you. |
2889 | * The mOSHE in this subframe will be the previous url's |
2890 | * mOSHE. This mOSHE will be used as the identification |
2891 | * for this subframe in the CloneAndReplace function. |
2892 | */ |
2893 | |
2894 | // In this case, we will end up calling AddEntry, which increases the |
2895 | // current index by 1 |
2896 | RefPtr<ChildSHistory> rootSH = GetRootSessionHistory(); |
2897 | if (rootSH) { |
2898 | mPreviousEntryIndex = rootSH->Index(); |
2899 | } |
2900 | |
2901 | nsresult rv; |
2902 | // XXX(farre): this is not Fission safe, expect errors. This never |
2903 | // get's executed once session history in the parent is enabled. |
2904 | nsCOMPtr<nsIDocShell> parent = do_QueryInterface(GetAsSupports(mParent), &rv); |
2905 | 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()" , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 2908); } } while (false) |
2906 | 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()" , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 2908); } } while (false) |
2907 | "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()" , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 2908); } } while (false) |
2908 | "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()" , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 2908); } } while (false); |
2909 | if (parent) { |
2910 | rv = nsDocShell::Cast(parent)->AddChildSHEntry( |
2911 | mOSHE, aNewEntry, aChildOffset, mLoadType, aCloneChildren); |
2912 | } |
2913 | |
2914 | if (rootSH) { |
2915 | mLoadedEntryIndex = rootSH->Index(); |
2916 | |
2917 | if (MOZ_UNLIKELY(MOZ_LOG_TEST(gPageCacheLog, LogLevel::Verbose))(__builtin_expect(!!((__builtin_expect(!!(mozilla::detail::log_test (gPageCacheLog, LogLevel::Verbose)), 0))), 0))) { |
2918 | 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) |
2919 | ("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) |
2920 | 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); |
2921 | } |
2922 | } |
2923 | |
2924 | return rv; |
2925 | } |
2926 | |
2927 | NS_IMETHODIMPnsresult |
2928 | nsDocShell::GetCurrentSHEntry(nsISHEntry** aEntry, bool* aOSHE) { |
2929 | *aOSHE = false; |
2930 | *aEntry = nullptr; |
2931 | if (mLSHE) { |
2932 | NS_ADDREF(*aEntry = mLSHE)(*aEntry = mLSHE)->AddRef(); |
2933 | } else if (mOSHE) { |
2934 | NS_ADDREF(*aEntry = mOSHE)(*aEntry = mOSHE)->AddRef(); |
2935 | *aOSHE = true; |
2936 | } |
2937 | return NS_OK; |
2938 | } |
2939 | |
2940 | NS_IMETHODIMPnsresult nsDocShell::SynchronizeLayoutHistoryState() { |
2941 | if (mActiveEntry && mActiveEntry->GetLayoutHistoryState() && |
2942 | mBrowsingContext) { |
2943 | if (XRE_IsContentProcess()) { |
2944 | dom::ContentChild* contentChild = dom::ContentChild::GetSingleton(); |
2945 | if (contentChild) { |
2946 | contentChild->SendSynchronizeLayoutHistoryState( |
2947 | mBrowsingContext, mActiveEntry->GetLayoutHistoryState()); |
2948 | } |
2949 | } else { |
2950 | SessionHistoryEntry* entry = |
2951 | mBrowsingContext->Canonical()->GetActiveSessionHistoryEntry(); |
2952 | if (entry) { |
2953 | entry->SetLayoutHistoryState(mActiveEntry->GetLayoutHistoryState()); |
2954 | } |
2955 | } |
2956 | if (mLoadingEntry && |
2957 | mLoadingEntry->mInfo.SharedId() == mActiveEntry->SharedId()) { |
2958 | mLoadingEntry->mInfo.SetLayoutHistoryState( |
2959 | mActiveEntry->GetLayoutHistoryState()); |
2960 | } |
2961 | } |
2962 | |
2963 | return NS_OK; |
2964 | } |
2965 | |
2966 | void nsDocShell::SetLoadGroupDefaultLoadFlags(nsLoadFlags aLoadFlags) { |
2967 | if (mLoadGroup) { |
2968 | mLoadGroup->SetDefaultLoadFlags(aLoadFlags); |
2969 | } else { |
2970 | NS_WARNING(NS_DebugBreak(NS_DEBUG_WARNING, "nsDocShell::SetLoadGroupDefaultLoadFlags has no loadGroup to " "propagate the mode to", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 2972) |
2971 | "nsDocShell::SetLoadGroupDefaultLoadFlags has no loadGroup to "NS_DebugBreak(NS_DEBUG_WARNING, "nsDocShell::SetLoadGroupDefaultLoadFlags has no loadGroup to " "propagate the mode to", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 2972) |
2972 | "propagate the mode to")NS_DebugBreak(NS_DEBUG_WARNING, "nsDocShell::SetLoadGroupDefaultLoadFlags has no loadGroup to " "propagate the mode to", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 2972); |
2973 | } |
2974 | } |
2975 | |
2976 | nsIScriptGlobalObject* nsDocShell::GetScriptGlobalObject() { |
2977 | 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 , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 2977); return nullptr; } } while (false); |
2978 | return mScriptGlobal; |
2979 | } |
2980 | |
2981 | Document* nsDocShell::GetDocument() { |
2982 | 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 , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 2982); return nullptr; } } while (false); |
2983 | return mDocumentViewer->GetDocument(); |
2984 | } |
2985 | |
2986 | Document* nsDocShell::GetExtantDocument() { |
2987 | return mDocumentViewer ? mDocumentViewer->GetDocument() : nullptr; |
2988 | } |
2989 | |
2990 | nsPIDOMWindowOuter* nsDocShell::GetWindow() { |
2991 | if (NS_FAILED(EnsureScriptEnvironment())((bool)(__builtin_expect(!!(NS_FAILED_impl(EnsureScriptEnvironment ())), 0)))) { |
2992 | return nullptr; |
2993 | } |
2994 | return mScriptGlobal; |
2995 | } |
2996 | |
2997 | NS_IMETHODIMPnsresult |
2998 | nsDocShell::GetDomWindow(mozIDOMWindowProxy** aWindow) { |
2999 | NS_ENSURE_ARG_POINTER(aWindow)do { if ((__builtin_expect(!!(!(aWindow)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aWindow" ") failed", nullptr , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 2999); return NS_ERROR_INVALID_POINTER; } } while (false); |
3000 | |
3001 | nsresult rv = EnsureScriptEnvironment(); |
3002 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 3002); return rv; } } while (false); |
3003 | |
3004 | RefPtr<nsGlobalWindowOuter> window = mScriptGlobal; |
3005 | window.forget(aWindow); |
3006 | return NS_OK; |
3007 | } |
3008 | |
3009 | NS_IMETHODIMPnsresult |
3010 | nsDocShell::GetMessageManager(ContentFrameMessageManager** aMessageManager) { |
3011 | RefPtr<ContentFrameMessageManager> mm; |
3012 | if (RefPtr<BrowserChild> browserChild = BrowserChild::GetFrom(this)) { |
3013 | mm = browserChild->GetMessageManager(); |
3014 | } else if (nsPIDOMWindowOuter* win = GetWindow()) { |
3015 | mm = win->GetMessageManager(); |
3016 | } |
3017 | mm.forget(aMessageManager); |
3018 | return NS_OK; |
3019 | } |
3020 | |
3021 | NS_IMETHODIMPnsresult |
3022 | nsDocShell::GetIsNavigating(bool* aOut) { |
3023 | *aOut = mIsNavigating; |
3024 | return NS_OK; |
3025 | } |
3026 | |
3027 | void nsDocShell::ClearFrameHistory(nsISHEntry* aEntry) { |
3028 | 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()", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 3028); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()" ")"); do { *((volatile int*)__null) = 3028; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3029 | RefPtr<ChildSHistory> rootSH = GetRootSessionHistory(); |
3030 | if (!rootSH || !aEntry) { |
3031 | return; |
3032 | } |
3033 | |
3034 | rootSH->LegacySHistory()->RemoveFrameEntries(aEntry); |
3035 | } |
3036 | |
3037 | //------------------------------------- |
3038 | //-- Helper Method for Print discovery |
3039 | //------------------------------------- |
3040 | bool nsDocShell::NavigationBlockedByPrinting(bool aDisplayErrorDialog) { |
3041 | if (!mBrowsingContext->Top()->GetIsPrinting()) { |
3042 | return false; |
3043 | } |
3044 | if (aDisplayErrorDialog) { |
3045 | DisplayLoadError(NS_ERROR_DOCUMENT_IS_PRINTMODE, nullptr, nullptr, nullptr); |
3046 | } |
3047 | return true; |
3048 | } |
3049 | |
3050 | bool nsDocShell::IsNavigationAllowed(bool aDisplayPrintErrorDialog, |
3051 | bool aCheckIfUnloadFired) { |
3052 | bool isAllowed = !NavigationBlockedByPrinting(aDisplayPrintErrorDialog) && |
3053 | (!aCheckIfUnloadFired || !mFiredUnloadEvent); |
3054 | if (!isAllowed) { |
3055 | return false; |
3056 | } |
3057 | if (!mDocumentViewer) { |
3058 | return true; |
3059 | } |
3060 | bool firingBeforeUnload; |
3061 | mDocumentViewer->GetBeforeUnloadFiring(&firingBeforeUnload); |
3062 | return !firingBeforeUnload; |
3063 | } |
3064 | |
3065 | //***************************************************************************** |
3066 | // nsDocShell::nsIWebNavigation |
3067 | //***************************************************************************** |
3068 | |
3069 | NS_IMETHODIMPnsresult |
3070 | nsDocShell::GetCanGoBack(bool* aCanGoBack) { |
3071 | *aCanGoBack = false; |
3072 | if (!IsNavigationAllowed(false)) { |
3073 | return NS_OK; // JS may not handle returning of an error code |
3074 | } |
3075 | RefPtr<ChildSHistory> rootSH = GetRootSessionHistory(); |
3076 | if (rootSH) { |
3077 | *aCanGoBack = rootSH->CanGo(-1); |
3078 | 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) |
3079 | ("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); |
3080 | |
3081 | return NS_OK; |
3082 | } |
3083 | return NS_ERROR_FAILURE; |
3084 | } |
3085 | |
3086 | NS_IMETHODIMPnsresult |
3087 | nsDocShell::GetCanGoForward(bool* aCanGoForward) { |
3088 | *aCanGoForward = false; |
3089 | if (!IsNavigationAllowed(false)) { |
3090 | return NS_OK; // JS may not handle returning of an error code |
3091 | } |
3092 | RefPtr<ChildSHistory> rootSH = GetRootSessionHistory(); |
3093 | if (rootSH) { |
3094 | *aCanGoForward = rootSH->CanGo(1); |
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 CanGoForward()->%d", this , *aCanGoForward); } } while (0) |
3096 | ("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); |
3097 | return NS_OK; |
3098 | } |
3099 | return NS_ERROR_FAILURE; |
3100 | } |
3101 | |
3102 | NS_IMETHODIMPnsresult |
3103 | nsDocShell::GoBack(bool aRequireUserInteraction, bool aUserActivation) { |
3104 | if (!IsNavigationAllowed()) { |
3105 | return NS_OK; // JS may not handle returning of an error code |
3106 | } |
3107 | |
3108 | auto cleanupIsNavigating = MakeScopeExit([&]() { mIsNavigating = false; }); |
3109 | mIsNavigating = true; |
3110 | |
3111 | RefPtr<ChildSHistory> rootSH = GetRootSessionHistory(); |
3112 | NS_ENSURE_TRUE(rootSH, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(rootSH)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "rootSH" ") failed", nullptr , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 3112); return NS_ERROR_FAILURE; } } while (false); |
3113 | ErrorResult rv; |
3114 | rootSH->Go(-1, aRequireUserInteraction, aUserActivation, rv); |
3115 | return rv.StealNSResult(); |
3116 | } |
3117 | |
3118 | NS_IMETHODIMPnsresult |
3119 | nsDocShell::GoForward(bool aRequireUserInteraction, bool aUserActivation) { |
3120 | if (!IsNavigationAllowed()) { |
3121 | return NS_OK; // JS may not handle returning of an error code |
3122 | } |
3123 | |
3124 | auto cleanupIsNavigating = MakeScopeExit([&]() { mIsNavigating = false; }); |
3125 | mIsNavigating = true; |
3126 | |
3127 | RefPtr<ChildSHistory> rootSH = GetRootSessionHistory(); |
3128 | NS_ENSURE_TRUE(rootSH, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(rootSH)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "rootSH" ") failed", nullptr , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 3128); return NS_ERROR_FAILURE; } } while (false); |
3129 | ErrorResult rv; |
3130 | rootSH->Go(1, aRequireUserInteraction, aUserActivation, rv); |
3131 | return rv.StealNSResult(); |
3132 | } |
3133 | |
3134 | // XXX(nika): We may want to stop exposing this API in the child process? Going |
3135 | // to a specific index from multiple different processes could definitely race. |
3136 | NS_IMETHODIMPnsresult |
3137 | nsDocShell::GotoIndex(int32_t aIndex, bool aUserActivation) { |
3138 | if (!IsNavigationAllowed()) { |
3139 | return NS_OK; // JS may not handle returning of an error code |
3140 | } |
3141 | |
3142 | auto cleanupIsNavigating = MakeScopeExit([&]() { mIsNavigating = false; }); |
3143 | mIsNavigating = true; |
3144 | |
3145 | RefPtr<ChildSHistory> rootSH = GetRootSessionHistory(); |
3146 | NS_ENSURE_TRUE(rootSH, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(rootSH)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "rootSH" ") failed", nullptr , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 3146); return NS_ERROR_FAILURE; } } while (false); |
3147 | |
3148 | ErrorResult rv; |
3149 | rootSH->GotoIndex(aIndex, aIndex - rootSH->Index(), false, aUserActivation, |
3150 | rv); |
3151 | return rv.StealNSResult(); |
3152 | } |
3153 | |
3154 | nsresult nsDocShell::LoadURI(nsIURI* aURI, |
3155 | const LoadURIOptions& aLoadURIOptions) { |
3156 | if (!IsNavigationAllowed()) { |
3157 | return NS_OK; // JS may not handle returning of an error code |
3158 | } |
3159 | RefPtr<nsDocShellLoadState> loadState; |
3160 | nsresult rv = nsDocShellLoadState::CreateFromLoadURIOptions( |
3161 | mBrowsingContext, aURI, aLoadURIOptions, getter_AddRefs(loadState)); |
3162 | 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", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 3162); AnnotateMozCrashReason("MOZ_ASSERT" "(" "rv != NS_ERROR_MALFORMED_URI" ")"); do { *((volatile int*)__null) = 3162; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3163 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || !loadState) { |
3164 | return NS_ERROR_FAILURE; |
3165 | } |
3166 | |
3167 | return LoadURI(loadState, true); |
3168 | } |
3169 | |
3170 | NS_IMETHODIMPnsresult |
3171 | nsDocShell::LoadURIFromScript(nsIURI* aURI, |
3172 | JS::Handle<JS::Value> aLoadURIOptions, |
3173 | JSContext* aCx) { |
3174 | // generate dictionary for aLoadURIOptions and forward call |
3175 | LoadURIOptions loadURIOptions; |
3176 | if (!loadURIOptions.Init(aCx, aLoadURIOptions)) { |
3177 | return NS_ERROR_INVALID_ARG; |
3178 | } |
3179 | return LoadURI(aURI, loadURIOptions); |
3180 | } |
3181 | |
3182 | nsresult nsDocShell::FixupAndLoadURIString( |
3183 | const nsAString& aURIString, const LoadURIOptions& aLoadURIOptions) { |
3184 | if (!IsNavigationAllowed()) { |
3185 | return NS_OK; // JS may not handle returning of an error code |
3186 | } |
3187 | |
3188 | RefPtr<nsDocShellLoadState> loadState; |
3189 | nsresult rv = nsDocShellLoadState::CreateFromLoadURIOptions( |
3190 | mBrowsingContext, aURIString, aLoadURIOptions, getter_AddRefs(loadState)); |
3191 | |
3192 | uint32_t loadFlags = aLoadURIOptions.mLoadFlags; |
3193 | if (NS_ERROR_MALFORMED_URI == rv) { |
3194 | 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) |
3195 | ("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) |
3196 | "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) |
3197 | 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); |
3198 | |
3199 | // We need to store a session history entry. We don't have a valid URI, so |
3200 | // we use about:blank instead. |
3201 | nsCOMPtr<nsIURI> uri; |
3202 | 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 { static_assert( mozilla::detail::AssertionConditionType <decltype(false)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("false" " (" "NS_SUCCEEDED(NS_NewURI(getter_AddRefs(uri), \"about:blank\"_ns))" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 3202); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false" ") (" "NS_SUCCEEDED(NS_NewURI(getter_AddRefs(uri), \"about:blank\"_ns))" ")"); do { *((volatile int*)__null) = 3202; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); |
3203 | nsCOMPtr<nsIPrincipal> triggeringPrincipal; |
3204 | if (aLoadURIOptions.mTriggeringPrincipal) { |
3205 | triggeringPrincipal = aLoadURIOptions.mTriggeringPrincipal; |
3206 | } else { |
3207 | triggeringPrincipal = nsContentUtils::GetSystemPrincipal(); |
3208 | } |
3209 | if (mozilla::SessionHistoryInParent()) { |
3210 | mActiveEntry = MakeUnique<SessionHistoryInfo>( |
3211 | uri, triggeringPrincipal, nullptr, nullptr, nullptr, |
3212 | nsLiteralCString("text/html")); |
3213 | mBrowsingContext->SetActiveSessionHistoryEntry( |
3214 | Nothing(), mActiveEntry.get(), MAKE_LOAD_TYPE(LOAD_NORMAL, loadFlags)((LOAD_NORMAL) | ((loadFlags) << 16)), |
3215 | /* aUpdatedCacheKey = */ 0); |
3216 | } |
3217 | if (DisplayLoadError(rv, nullptr, PromiseFlatStringTPromiseFlatString<char16_t>(aURIString).get(), |
3218 | nullptr) && |
3219 | (loadFlags & LOAD_FLAGS_ERROR_LOAD_CHANGES_RV) != 0) { |
3220 | return NS_ERROR_LOAD_SHOWED_ERRORPAGE; |
3221 | } |
3222 | } |
3223 | |
3224 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || !loadState) { |
3225 | return NS_ERROR_FAILURE; |
3226 | } |
3227 | |
3228 | return LoadURI(loadState, true); |
3229 | } |
3230 | |
3231 | NS_IMETHODIMPnsresult |
3232 | nsDocShell::FixupAndLoadURIStringFromScript( |
3233 | const nsAString& aURIString, JS::Handle<JS::Value> aLoadURIOptions, |
3234 | JSContext* aCx) { |
3235 | // generate dictionary for aLoadURIOptions and forward call |
3236 | LoadURIOptions loadURIOptions; |
3237 | if (!loadURIOptions.Init(aCx, aLoadURIOptions)) { |
3238 | return NS_ERROR_INVALID_ARG; |
3239 | } |
3240 | return FixupAndLoadURIString(aURIString, loadURIOptions); |
3241 | } |
3242 | |
3243 | void nsDocShell::UnblockEmbedderLoadEventForFailure(bool aFireFrameErrorEvent) { |
3244 | // If we're not in a content frame, or are at a BrowsingContext tree boundary, |
3245 | // such as the content-chrome boundary, don't fire the error event. |
3246 | if (mBrowsingContext->IsTopContent() || mBrowsingContext->IsChrome()) { |
3247 | return; |
3248 | } |
3249 | |
3250 | // If embedder is same-process, then unblocking the load event is already |
3251 | // handled by nsDocLoader. Fire the error event on our embedder element if |
3252 | // requested. |
3253 | // |
3254 | // XXX: Bug 1440212 is looking into potentially changing this behaviour to act |
3255 | // more like the remote case when in-process. |
3256 | RefPtr<Element> element = mBrowsingContext->GetEmbedderElement(); |
3257 | if (element) { |
3258 | if (aFireFrameErrorEvent) { |
3259 | if (RefPtr<nsFrameLoaderOwner> flo = do_QueryObject(element)) { |
3260 | if (RefPtr<nsFrameLoader> fl = flo->GetFrameLoader()) { |
3261 | fl->FireErrorEvent(); |
3262 | } |
3263 | } |
3264 | } |
3265 | return; |
3266 | } |
3267 | |
3268 | // If we have a cross-process parent document, we must notify it that we no |
3269 | // longer block its load event. This is necessary for OOP sub-documents |
3270 | // because error documents do not result in a call to |
3271 | // SendMaybeFireEmbedderLoadEvents via any of the normal call paths. |
3272 | // (Obviously, we must do this before any of the returns below.) |
3273 | RefPtr<BrowserChild> browserChild = BrowserChild::GetFrom(this); |
3274 | if (browserChild && |
3275 | !mBrowsingContext->GetParentWindowContext()->IsInProcess()) { |
3276 | mozilla::Unused << browserChild->SendMaybeFireEmbedderLoadEvents( |
3277 | aFireFrameErrorEvent ? EmbedderElementEventType::ErrorEvent |
3278 | : EmbedderElementEventType::NoEvent); |
3279 | } |
3280 | } |
3281 | |
3282 | NS_IMETHODIMPnsresult |
3283 | nsDocShell::DisplayLoadError(nsresult aError, nsIURI* aURI, |
3284 | const char16_t* aURL, nsIChannel* aFailedChannel, |
3285 | bool* aDisplayedErrorPage) { |
3286 | 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 ) |
3287 | ("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 ) |
3288 | 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 ); |
3289 | |
3290 | *aDisplayedErrorPage = false; |
3291 | // Get prompt and string bundle services |
3292 | nsCOMPtr<nsIPrompt> prompter; |
3293 | nsCOMPtr<nsIStringBundle> stringBundle; |
3294 | GetPromptAndStringBundle(getter_AddRefs(prompter), |
3295 | getter_AddRefs(stringBundle)); |
3296 | |
3297 | NS_ENSURE_TRUE(stringBundle, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(stringBundle)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "stringBundle" ") failed" , nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 3297); return NS_ERROR_FAILURE; } } while (false); |
3298 | NS_ENSURE_TRUE(prompter, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(prompter)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "prompter" ") failed", nullptr , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 3298); return NS_ERROR_FAILURE; } } while (false); |
3299 | |
3300 | const char* error = nullptr; |
3301 | // The key used to select the appropriate error message from the properties |
3302 | // file. |
3303 | const char* errorDescriptionID = nullptr; |
3304 | AutoTArray<nsString, 3> formatStrs; |
3305 | bool addHostPort = false; |
3306 | bool isBadStsCertError = false; |
3307 | nsresult rv = NS_OK; |
3308 | nsAutoString messageStr; |
3309 | nsAutoCString cssClass; |
3310 | nsAutoCString errorPage; |
3311 | |
3312 | errorPage.AssignLiteral("neterror"); |
3313 | |
3314 | // Turn the error code into a human readable error message. |
3315 | if (NS_ERROR_UNKNOWN_PROTOCOL == aError) { |
3316 | NS_ENSURE_ARG_POINTER(aURI)do { if ((__builtin_expect(!!(!(aURI)), 0))) { NS_DebugBreak( NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aURI" ") failed", nullptr , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 3316); return NS_ERROR_INVALID_POINTER; } } while (false); |
3317 | |
3318 | // Extract the schemes into a comma delimited list. |
3319 | nsAutoCString scheme; |
3320 | aURI->GetScheme(scheme); |
3321 | CopyASCIItoUTF16(scheme, *formatStrs.AppendElement()); |
3322 | nsCOMPtr<nsINestedURI> nestedURI = do_QueryInterface(aURI); |
3323 | while (nestedURI) { |
3324 | nsCOMPtr<nsIURI> tempURI; |
3325 | nsresult rv2; |
3326 | rv2 = nestedURI->GetInnerURI(getter_AddRefs(tempURI)); |
3327 | if (NS_SUCCEEDED(rv2)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv2)), 1))) && tempURI) { |
3328 | tempURI->GetScheme(scheme); |
3329 | formatStrs[0].AppendLiteral(", "); |
3330 | AppendASCIItoUTF16(scheme, formatStrs[0]); |
3331 | } |
3332 | nestedURI = do_QueryInterface(tempURI); |
3333 | } |
3334 | error = "unknownProtocolFound"; |
3335 | } else if (NS_ERROR_NET_ERROR_RESPONSE == aError) { |
3336 | NS_ENSURE_ARG_POINTER(aURI)do { if ((__builtin_expect(!!(!(aURI)), 0))) { NS_DebugBreak( NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aURI" ") failed", nullptr , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 3336); return NS_ERROR_INVALID_POINTER; } } while (false); |
3337 | error = "serverError"; |
3338 | } else if (NS_ERROR_FILE_NOT_FOUND == aError) { |
3339 | NS_ENSURE_ARG_POINTER(aURI)do { if ((__builtin_expect(!!(!(aURI)), 0))) { NS_DebugBreak( NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aURI" ") failed", nullptr , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 3339); return NS_ERROR_INVALID_POINTER; } } while (false); |
3340 | error = "fileNotFound"; |
3341 | } else if (NS_ERROR_FILE_ACCESS_DENIED == aError) { |
3342 | NS_ENSURE_ARG_POINTER(aURI)do { if ((__builtin_expect(!!(!(aURI)), 0))) { NS_DebugBreak( NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aURI" ") failed", nullptr , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 3342); return NS_ERROR_INVALID_POINTER; } } while (false); |
3343 | error = "fileAccessDenied"; |
3344 | } else if (NS_ERROR_UNKNOWN_HOST == aError) { |
3345 | NS_ENSURE_ARG_POINTER(aURI)do { if ((__builtin_expect(!!(!(aURI)), 0))) { NS_DebugBreak( NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aURI" ") failed", nullptr , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 3345); return NS_ERROR_INVALID_POINTER; } } while (false); |
3346 | // Get the host |
3347 | nsAutoCString host; |
3348 | nsCOMPtr<nsIURI> innermostURI = NS_GetInnermostURI(aURI); |
3349 | innermostURI->GetHost(host); |
3350 | CopyUTF8toUTF16(host, *formatStrs.AppendElement()); |
3351 | errorDescriptionID = "dnsNotFound2"; |
3352 | error = "dnsNotFound"; |
3353 | } else if (NS_ERROR_CONNECTION_REFUSED == aError || |
3354 | NS_ERROR_PROXY_BAD_GATEWAY == aError) { |
3355 | NS_ENSURE_ARG_POINTER(aURI)do { if ((__builtin_expect(!!(!(aURI)), 0))) { NS_DebugBreak( NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aURI" ") failed", nullptr , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 3355); return NS_ERROR_INVALID_POINTER; } } while (false); |
3356 | addHostPort = true; |
3357 | error = "connectionFailure"; |
3358 | } else if (NS_ERROR_NET_INTERRUPT == aError) { |
3359 | NS_ENSURE_ARG_POINTER(aURI)do { if ((__builtin_expect(!!(!(aURI)), 0))) { NS_DebugBreak( NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aURI" ") failed", nullptr , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 3359); return NS_ERROR_INVALID_POINTER; } } while (false); |
3360 | addHostPort = true; |
3361 | error = "netInterrupt"; |
3362 | } else if (NS_ERROR_NET_TIMEOUT == aError || |
3363 | NS_ERROR_PROXY_GATEWAY_TIMEOUT == aError || |
3364 | NS_ERROR_NET_TIMEOUT_EXTERNAL == aError) { |
3365 | NS_ENSURE_ARG_POINTER(aURI)do { if ((__builtin_expect(!!(!(aURI)), 0))) { NS_DebugBreak( NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aURI" ") failed", nullptr , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 3365); return NS_ERROR_INVALID_POINTER; } } while (false); |
3366 | // Get the host |
3367 | nsAutoCString host; |
3368 | aURI->GetHost(host); |
3369 | CopyUTF8toUTF16(host, *formatStrs.AppendElement()); |
3370 | error = "netTimeout"; |
3371 | } else if (NS_ERROR_CSP_FRAME_ANCESTOR_VIOLATION == aError || |
3372 | NS_ERROR_CSP_FORM_ACTION_VIOLATION == aError) { |
3373 | // CSP error |
3374 | cssClass.AssignLiteral("neterror"); |
3375 | error = "cspBlocked"; |
3376 | } else if (NS_ERROR_XFO_VIOLATION == aError) { |
3377 | // XFO error |
3378 | cssClass.AssignLiteral("neterror"); |
3379 | error = "xfoBlocked"; |
3380 | } else if (NS_ERROR_GET_MODULE(aError) == NS_ERROR_MODULE_SECURITY21) { |
3381 | nsCOMPtr<nsINSSErrorsService> nsserr = |
3382 | do_GetService(NS_NSS_ERRORS_SERVICE_CONTRACTID"@mozilla.org/nss_errors_service;1"); |
3383 | |
3384 | uint32_t errorClass; |
3385 | if (!nsserr || NS_FAILED(nsserr->GetErrorClass(aError, &errorClass))((bool)(__builtin_expect(!!(NS_FAILED_impl(nsserr->GetErrorClass (aError, &errorClass))), 0)))) { |
3386 | errorClass = nsINSSErrorsService::ERROR_CLASS_SSL_PROTOCOL; |
3387 | } |
3388 | |
3389 | nsCOMPtr<nsITransportSecurityInfo> tsi; |
3390 | if (aFailedChannel) { |
3391 | aFailedChannel->GetSecurityInfo(getter_AddRefs(tsi)); |
3392 | } |
3393 | if (tsi) { |
3394 | uint32_t securityState; |
3395 | tsi->GetSecurityState(&securityState); |
3396 | if (securityState & nsIWebProgressListener::STATE_USES_SSL_3) { |
3397 | error = "sslv3Used"; |
Value stored to 'error' is never read | |
3398 | addHostPort = true; |
3399 | } else if (securityState & |
3400 | nsIWebProgressListener::STATE_USES_WEAK_CRYPTO) { |
3401 | error = "weakCryptoUsed"; |
3402 | addHostPort = true; |
3403 | } |
3404 | } else { |
3405 | // No channel, let's obtain the generic error message |
3406 | if (nsserr) { |
3407 | nsserr->GetErrorMessage(aError, messageStr); |
3408 | } |
3409 | } |
3410 | // We don't have a message string here anymore but DisplayLoadError |
3411 | // requires a non-empty messageStr. |
3412 | messageStr.Truncate(); |
3413 | messageStr.AssignLiteral(u" "); |
3414 | if (errorClass == nsINSSErrorsService::ERROR_CLASS_BAD_CERT) { |
3415 | error = "nssBadCert"; |
3416 | |
3417 | // If this is an HTTP Strict Transport Security host or a pinned host |
3418 | // and the certificate is bad, don't allow overrides (RFC 6797 section |
3419 | // 12.1). |
3420 | bool isStsHost = false; |
3421 | bool isPinnedHost = false; |
3422 | OriginAttributes attrsForHSTS; |
3423 | if (aFailedChannel) { |
3424 | StoragePrincipalHelper::GetOriginAttributesForHSTS(aFailedChannel, |
3425 | attrsForHSTS); |
3426 | } else { |
3427 | attrsForHSTS = GetOriginAttributes(); |
3428 | } |
3429 | |
3430 | if (XRE_IsParentProcess()) { |
3431 | nsCOMPtr<nsISiteSecurityService> sss = |
3432 | do_GetService(NS_SSSERVICE_CONTRACTID"@mozilla.org/ssservice;1", &rv); |
3433 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 3433); return rv; } } while (false); |
3434 | rv = sss->IsSecureURI(aURI, attrsForHSTS, &isStsHost); |
3435 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 3435); return rv; } } while (false); |
3436 | } else { |
3437 | mozilla::dom::ContentChild* cc = |
3438 | mozilla::dom::ContentChild::GetSingleton(); |
3439 | cc->SendIsSecureURI(aURI, attrsForHSTS, &isStsHost); |
3440 | } |
3441 | nsCOMPtr<nsIPublicKeyPinningService> pkps = |
3442 | do_GetService(NS_PKPSERVICE_CONTRACTID"@mozilla.org/security/publickeypinningservice;1", &rv); |
3443 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 3443); return rv; } } while (false); |
3444 | rv = pkps->HostHasPins(aURI, &isPinnedHost); |
3445 | |
3446 | if (Preferences::GetBool("browser.xul.error_pages.expert_bad_cert", |
3447 | false)) { |
3448 | cssClass.AssignLiteral("expertBadCert"); |
3449 | } |
3450 | |
3451 | // HSTS/pinning takes precedence over the expert bad cert pref. We |
3452 | // never want to show the "Add Exception" button for these sites. |
3453 | // In the future we should differentiate between an HSTS host and a |
3454 | // pinned host and display a more informative message to the user. |
3455 | if (isStsHost || isPinnedHost) { |
3456 | isBadStsCertError = true; |
3457 | cssClass.AssignLiteral("badStsCert"); |
3458 | } |
3459 | |
3460 | errorPage.Assign("certerror"); |
3461 | } else { |
3462 | error = "nssFailure2"; |
3463 | } |
3464 | } else if (NS_ERROR_PHISHING_URI == aError || |
3465 | NS_ERROR_MALWARE_URI == aError || |
3466 | NS_ERROR_UNWANTED_URI == aError || |
3467 | NS_ERROR_HARMFUL_URI == aError) { |
3468 | nsAutoCString host; |
3469 | aURI->GetHost(host); |
3470 | CopyUTF8toUTF16(host, *formatStrs.AppendElement()); |
3471 | |
3472 | // Malware and phishing detectors may want to use an alternate error |
3473 | // page, but if the pref's not set, we'll fall back on the standard page |
3474 | nsAutoCString alternateErrorPage; |
3475 | nsresult rv = Preferences::GetCString("urlclassifier.alternate_error_page", |
3476 | alternateErrorPage); |
3477 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) { |
3478 | errorPage.Assign(alternateErrorPage); |
3479 | } |
3480 | |
3481 | if (NS_ERROR_PHISHING_URI == aError) { |
3482 | error = "deceptiveBlocked"; |
3483 | } else if (NS_ERROR_MALWARE_URI == aError) { |
3484 | error = "malwareBlocked"; |
3485 | } else if (NS_ERROR_UNWANTED_URI == aError) { |
3486 | error = "unwantedBlocked"; |
3487 | } else if (NS_ERROR_HARMFUL_URI == aError) { |
3488 | error = "harmfulBlocked"; |
3489 | } |
3490 | |
3491 | cssClass.AssignLiteral("blacklist"); |
3492 | } else if (NS_ERROR_CONTENT_CRASHED == aError) { |
3493 | errorPage.AssignLiteral("tabcrashed"); |
3494 | error = "tabcrashed"; |
3495 | |
3496 | RefPtr<EventTarget> handler = mChromeEventHandler; |
3497 | if (handler) { |
3498 | nsCOMPtr<Element> element = do_QueryInterface(handler); |
3499 | element->GetAttribute(u"crashedPageTitle"_ns, messageStr); |
3500 | } |
3501 | |
3502 | // DisplayLoadError requires a non-empty messageStr to proceed and call |
3503 | // LoadErrorPage. If the page doesn't have a title, we will use a blank |
3504 | // space which will be trimmed and thus treated as empty by the front-end. |
3505 | if (messageStr.IsEmpty()) { |
3506 | messageStr.AssignLiteral(u" "); |
3507 | } |
3508 | } else if (NS_ERROR_FRAME_CRASHED == aError) { |
3509 | errorPage.AssignLiteral("framecrashed"); |
3510 | error = "framecrashed"; |
3511 | messageStr.AssignLiteral(u" "); |
3512 | } else if (NS_ERROR_BUILDID_MISMATCH == aError) { |
3513 | errorPage.AssignLiteral("restartrequired"); |
3514 | error = "restartrequired"; |
3515 | |
3516 | // DisplayLoadError requires a non-empty messageStr to proceed and call |
3517 | // LoadErrorPage. If the page doesn't have a title, we will use a blank |
3518 | // space which will be trimmed and thus treated as empty by the front-end. |
3519 | if (messageStr.IsEmpty()) { |
3520 | messageStr.AssignLiteral(u" "); |
3521 | } |
3522 | } else { |
3523 | // Errors requiring simple formatting |
3524 | switch (aError) { |
3525 | case NS_ERROR_MALFORMED_URI: |
3526 | // URI is malformed |
3527 | error = "malformedURI"; |
3528 | errorDescriptionID = "malformedURI2"; |
3529 | break; |
3530 | case NS_ERROR_REDIRECT_LOOP: |
3531 | // Doc failed to load because the server generated too many redirects |
3532 | error = "redirectLoop"; |
3533 | break; |
3534 | case NS_ERROR_UNKNOWN_SOCKET_TYPE: |
3535 | // Doc failed to load because PSM is not installed |
3536 | error = "unknownSocketType"; |
3537 | break; |
3538 | case NS_ERROR_NET_RESET: |
3539 | // Doc failed to load because the server kept reseting the connection |
3540 | // before we could read any data from it |
3541 | error = "netReset"; |
3542 | break; |
3543 | case NS_ERROR_DOCUMENT_NOT_CACHED: |
3544 | // Doc failed to load because the cache does not contain a copy of |
3545 | // the document. |
3546 | error = "notCached"; |
3547 | break; |
3548 | case NS_ERROR_OFFLINE: |
3549 | // Doc failed to load because we are offline. |
3550 | error = "netOffline"; |
3551 | break; |
3552 | case NS_ERROR_DOCUMENT_IS_PRINTMODE: |
3553 | // Doc navigation attempted while Printing or Print Preview |
3554 | error = "isprinting"; |
3555 | break; |
3556 | case NS_ERROR_PORT_ACCESS_NOT_ALLOWED: |
3557 | // Port blocked for security reasons |
3558 | addHostPort = true; |
3559 | error = "deniedPortAccess"; |
3560 | break; |
3561 | case NS_ERROR_UNKNOWN_PROXY_HOST: |
3562 | // Proxy hostname could not be resolved. |
3563 | error = "proxyResolveFailure"; |
3564 | break; |
3565 | case NS_ERROR_PROXY_CONNECTION_REFUSED: |
3566 | case NS_ERROR_PROXY_FORBIDDEN: |
3567 | case NS_ERROR_PROXY_NOT_IMPLEMENTED: |
3568 | case NS_ERROR_PROXY_AUTHENTICATION_FAILED: |
3569 | case NS_ERROR_PROXY_TOO_MANY_REQUESTS: |
3570 | // Proxy connection was refused. |
3571 | error = "proxyConnectFailure"; |
3572 | break; |
3573 | case NS_ERROR_INVALID_CONTENT_ENCODING: |
3574 | // Bad Content Encoding. |
3575 | error = "contentEncodingError"; |
3576 | break; |
3577 | case NS_ERROR_UNSAFE_CONTENT_TYPE: |
3578 | // Channel refused to load from an unrecognized content type. |
3579 | error = "unsafeContentType"; |
3580 | break; |
3581 | case NS_ERROR_CORRUPTED_CONTENT: |
3582 | // Broken Content Detected. e.g. Content-MD5 check failure. |
3583 | error = "corruptedContentErrorv2"; |
3584 | break; |
3585 | case NS_ERROR_INTERCEPTION_FAILED: |
3586 | // ServiceWorker intercepted request, but something went wrong. |
3587 | error = "corruptedContentErrorv2"; |
3588 | break; |
3589 | case NS_ERROR_NET_INADEQUATE_SECURITY: |
3590 | // Server negotiated bad TLS for HTTP/2. |
3591 | error = "inadequateSecurityError"; |
3592 | addHostPort = true; |
3593 | break; |
3594 | case NS_ERROR_BLOCKED_BY_POLICY: |
3595 | case NS_ERROR_DOM_COOP_FAILED: |
3596 | case NS_ERROR_DOM_COEP_FAILED: |
3597 | // Page blocked by policy |
3598 | error = "blockedByPolicy"; |
3599 | break; |
3600 | case NS_ERROR_NET_HTTP2_SENT_GOAWAY: |
3601 | case NS_ERROR_NET_HTTP3_PROTOCOL_ERROR: |
3602 | // HTTP/2 or HTTP/3 stack detected a protocol error |
3603 | error = "networkProtocolError"; |
3604 | break; |
3605 | |
3606 | default: |
3607 | break; |
3608 | } |
3609 | } |
3610 | |
3611 | nsresult delegateErrorCode = aError; |
3612 | // If the HTTPS-Only Mode upgraded this request and the upgrade might have |
3613 | // caused this error, we replace the error-page with about:httpsonlyerror |
3614 | if (nsHTTPSOnlyUtils::CouldBeHttpsOnlyError(aFailedChannel, aError)) { |
3615 | errorPage.AssignLiteral("httpsonlyerror"); |
3616 | delegateErrorCode = NS_ERROR_HTTPS_ONLY; |
3617 | } else if (isBadStsCertError) { |
3618 | delegateErrorCode = NS_ERROR_BAD_HSTS_CERT; |
3619 | } |
3620 | |
3621 | if (nsCOMPtr<nsILoadURIDelegate> loadURIDelegate = GetLoadURIDelegate()) { |
3622 | nsCOMPtr<nsIURI> errorPageURI; |
3623 | rv = loadURIDelegate->HandleLoadError( |
3624 | aURI, delegateErrorCode, NS_ERROR_GET_MODULE(delegateErrorCode), |
3625 | getter_AddRefs(errorPageURI)); |
3626 | // If the docshell is going away there's no point in showing an error page. |
3627 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || mIsBeingDestroyed) { |
3628 | *aDisplayedErrorPage = false; |
3629 | return NS_OK; |
3630 | } |
3631 | |
3632 | if (errorPageURI) { |
3633 | *aDisplayedErrorPage = |
3634 | NS_SUCCEEDED(LoadErrorPage(errorPageURI, aURI, aFailedChannel))((bool)(__builtin_expect(!!(!NS_FAILED_impl(LoadErrorPage(errorPageURI , aURI, aFailedChannel))), 1))); |
3635 | return NS_OK; |
3636 | } |
3637 | } |
3638 | |
3639 | // Test if the error should be displayed |
3640 | if (!error) { |
3641 | return NS_OK; |
3642 | } |
3643 | |
3644 | if (!errorDescriptionID) { |
3645 | errorDescriptionID = error; |
3646 | } |
3647 | |
3648 | Telemetry::AccumulateCategoricalKeyed( |
3649 | IsSubframe() ? "frame"_ns : "top"_ns, |
3650 | mozilla::dom::LoadErrorToTelemetryLabel(aError)); |
3651 | |
3652 | // Test if the error needs to be formatted |
3653 | if (!messageStr.IsEmpty()) { |
3654 | // already obtained message |
3655 | } else { |
3656 | if (addHostPort) { |
3657 | // Build up the host:port string. |
3658 | nsAutoCString hostport; |
3659 | if (aURI) { |
3660 | aURI->GetHostPort(hostport); |
3661 | } else { |
3662 | hostport.Assign('?'); |
3663 | } |
3664 | CopyUTF8toUTF16(hostport, *formatStrs.AppendElement()); |
3665 | } |
3666 | |
3667 | nsAutoCString spec; |
3668 | rv = NS_ERROR_NOT_AVAILABLE; |
3669 | auto& nextFormatStr = *formatStrs.AppendElement(); |
3670 | if (aURI) { |
3671 | // displaying "file://" is aesthetically unpleasing and could even be |
3672 | // confusing to the user |
3673 | if (SchemeIsFile(aURI)) { |
3674 | aURI->GetPathQueryRef(spec); |
3675 | } else { |
3676 | aURI->GetSpec(spec); |
3677 | } |
3678 | |
3679 | nsCOMPtr<nsITextToSubURI> textToSubURI( |
3680 | do_GetService(NS_ITEXTTOSUBURI_CONTRACTID"@mozilla.org/intl/texttosuburi;1", &rv)); |
3681 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) { |
3682 | rv = textToSubURI->UnEscapeURIForUI(spec, nextFormatStr); |
3683 | } |
3684 | } else { |
3685 | spec.Assign('?'); |
3686 | } |
3687 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
3688 | CopyUTF8toUTF16(spec, nextFormatStr); |
3689 | } |
3690 | rv = NS_OK; |
3691 | |
3692 | nsAutoString str; |
3693 | rv = |
3694 | stringBundle->FormatStringFromName(errorDescriptionID, formatStrs, str); |
3695 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 3695); return rv; } } while (false); |
3696 | messageStr.Assign(str); |
3697 | } |
3698 | |
3699 | // Display the error as a page or an alert prompt |
3700 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 3700); return NS_ERROR_FAILURE; } } while (false); |
3701 | |
3702 | if ((NS_ERROR_NET_INTERRUPT == aError || NS_ERROR_NET_RESET == aError) && |
3703 | SchemeIsHTTPS(aURI)) { |
3704 | // Maybe TLS intolerant. Treat this as an SSL error. |
3705 | error = "nssFailure2"; |
3706 | } |
3707 | |
3708 | if (mBrowsingContext->GetUseErrorPages()) { |
3709 | // Display an error page |
3710 | nsresult loadedPage = |
3711 | LoadErrorPage(aURI, aURL, errorPage.get(), error, messageStr.get(), |
3712 | cssClass.get(), aFailedChannel); |
3713 | *aDisplayedErrorPage = NS_SUCCEEDED(loadedPage)((bool)(__builtin_expect(!!(!NS_FAILED_impl(loadedPage)), 1)) ); |
3714 | } else { |
3715 | // The prompter reqires that our private window has a document (or it |
3716 | // asserts). Satisfy that assertion now since GetDoc will force |
3717 | // creation of one if it hasn't already been created. |
3718 | if (mScriptGlobal) { |
3719 | Unused << mScriptGlobal->GetDoc(); |
3720 | } |
3721 | |
3722 | // Display a message box |
3723 | prompter->Alert(nullptr, messageStr.get()); |
3724 | } |
3725 | |
3726 | return NS_OK; |
3727 | } |
3728 | |
3729 | #define PREF_SAFEBROWSING_ALLOWOVERRIDE"browser.safebrowsing.allowOverride" "browser.safebrowsing.allowOverride" |
3730 | |
3731 | nsresult nsDocShell::LoadErrorPage(nsIURI* aURI, const char16_t* aURL, |
3732 | const char* aErrorPage, |
3733 | const char* aErrorType, |
3734 | const char16_t* aDescription, |
3735 | const char* aCSSClass, |
3736 | nsIChannel* aFailedChannel) { |
3737 | if (mIsBeingDestroyed) { |
3738 | return NS_ERROR_NOT_AVAILABLE; |
3739 | } |
3740 | |
3741 | #if defined(DEBUG1) |
3742 | if (MOZ_LOG_TEST(gDocShellLog, LogLevel::Debug)(__builtin_expect(!!(mozilla::detail::log_test(gDocShellLog, LogLevel ::Debug)), 0))) { |
3743 | nsAutoCString chanName; |
3744 | if (aFailedChannel) { |
3745 | aFailedChannel->GetName(chanName); |
3746 | } else { |
3747 | chanName.AssignLiteral("<no channel>"); |
3748 | } |
3749 | |
3750 | 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) |
3751 | ("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) |
3752 | 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) |
3753 | 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); |
3754 | } |
3755 | #endif |
3756 | |
3757 | nsAutoCString url; |
3758 | if (aURI) { |
3759 | nsresult rv = aURI->GetSpec(url); |
3760 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 3760); return rv; } } while (false); |
3761 | } else if (aURL) { |
3762 | CopyUTF16toUTF8(MakeStringSpan(aURL), url); |
3763 | } else { |
3764 | return NS_ERROR_INVALID_POINTER; |
3765 | } |
3766 | |
3767 | // Create a URL to pass all the error information through to the page. |
3768 | |
3769 | #undef SAFE_ESCAPE |
3770 | #define SAFE_ESCAPE(output, input, params)if (NS_warn_if_impl(!NS_Escape(input, output, params), "!NS_Escape(input, output, params)" , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 3770)) { return NS_ERROR_OUT_OF_MEMORY; } \ |
3771 | if (NS_WARN_IF(!NS_Escape(input, output, params))NS_warn_if_impl(!NS_Escape(input, output, params), "!NS_Escape(input, output, params)" , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 3771)) { \ |
3772 | return NS_ERROR_OUT_OF_MEMORY; \ |
3773 | } |
3774 | |
3775 | nsCString escapedUrl, escapedError, escapedDescription, escapedCSSClass; |
3776 | SAFE_ESCAPE(escapedUrl, url, url_Path)if (NS_warn_if_impl(!NS_Escape(url, escapedUrl, url_Path), "!NS_Escape(url, escapedUrl, url_Path)" , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 3776)) { return NS_ERROR_OUT_OF_MEMORY; }; |
3777 | 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)" , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 3777)) { return NS_ERROR_OUT_OF_MEMORY; }; |
3778 | 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)" , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 3779)) { return NS_ERROR_OUT_OF_MEMORY; } |
3779 | url_Path)if (NS_warn_if_impl(!NS_Escape(NS_ConvertUTF16toUTF8(aDescription ), escapedDescription, url_Path), "!NS_Escape(NS_ConvertUTF16toUTF8(aDescription), escapedDescription, url_Path)" , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 3779)) { return NS_ERROR_OUT_OF_MEMORY; }; |
3780 | if (aCSSClass) { |
3781 | nsCString cssClass(aCSSClass); |
3782 | SAFE_ESCAPE(escapedCSSClass, cssClass, url_Path)if (NS_warn_if_impl(!NS_Escape(cssClass, escapedCSSClass, url_Path ), "!NS_Escape(cssClass, escapedCSSClass, url_Path)", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 3782)) { return NS_ERROR_OUT_OF_MEMORY; }; |
3783 | } |
3784 | nsCString errorPageUrl("about:"); |
3785 | errorPageUrl.AppendASCII(aErrorPage); |
3786 | errorPageUrl.AppendLiteral("?e="); |
3787 | |
3788 | errorPageUrl.AppendASCII(escapedError.get()); |
3789 | errorPageUrl.AppendLiteral("&u="); |
3790 | errorPageUrl.AppendASCII(escapedUrl.get()); |
3791 | if ((strcmp(aErrorPage, "blocked") == 0) && |
3792 | Preferences::GetBool(PREF_SAFEBROWSING_ALLOWOVERRIDE"browser.safebrowsing.allowOverride", true)) { |
3793 | errorPageUrl.AppendLiteral("&o=1"); |
3794 | } |
3795 | if (!escapedCSSClass.IsEmpty()) { |
3796 | errorPageUrl.AppendLiteral("&s="); |
3797 | errorPageUrl.AppendASCII(escapedCSSClass.get()); |
3798 | } |
3799 | errorPageUrl.AppendLiteral("&c=UTF-8"); |
3800 | |
3801 | nsCOMPtr<nsICaptivePortalService> cps = do_GetService(NS_CAPTIVEPORTAL_CID{ 0xbdbe0555, 0xfc3d, 0x4f7b, { 0x92, 0x05, 0xc3, 0x09, 0xce, 0xb2, 0xd6, 0x41 } }); |
3802 | int32_t cpsState; |
3803 | if (cps && NS_SUCCEEDED(cps->GetState(&cpsState))((bool)(__builtin_expect(!!(!NS_FAILED_impl(cps->GetState( &cpsState))), 1))) && |
3804 | cpsState == nsICaptivePortalService::LOCKED_PORTAL) { |
3805 | errorPageUrl.AppendLiteral("&captive=true"); |
3806 | } |
3807 | |
3808 | errorPageUrl.AppendLiteral("&d="); |
3809 | errorPageUrl.AppendASCII(escapedDescription.get()); |
3810 | |
3811 | nsCOMPtr<nsIURI> errorPageURI; |
3812 | nsresult rv = NS_NewURI(getter_AddRefs(errorPageURI), errorPageUrl); |
3813 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 3813); return rv; } } while (false); |
3814 | |
3815 | return LoadErrorPage(errorPageURI, aURI, aFailedChannel); |
3816 | } |
3817 | |
3818 | nsresult nsDocShell::LoadErrorPage(nsIURI* aErrorURI, nsIURI* aFailedURI, |
3819 | nsIChannel* aFailedChannel) { |
3820 | mFailedChannel = aFailedChannel; |
3821 | mFailedURI = aFailedURI; |
3822 | mFailedLoadType = mLoadType; |
3823 | |
3824 | if (mLSHE) { |
3825 | // Abandon mLSHE's BFCache entry and create a new one. This way, if |
3826 | // we go back or forward to another SHEntry with the same doc |
3827 | // identifier, the error page won't persist. |
3828 | mLSHE->AbandonBFCacheEntry(); |
3829 | } |
3830 | |
3831 | RefPtr<nsDocShellLoadState> loadState = new nsDocShellLoadState(aErrorURI); |
3832 | loadState->SetTriggeringPrincipal(nsContentUtils::GetSystemPrincipal()); |
3833 | if (mBrowsingContext) { |
3834 | loadState->SetTriggeringSandboxFlags(mBrowsingContext->GetSandboxFlags()); |
3835 | loadState->SetTriggeringWindowId( |
3836 | mBrowsingContext->GetCurrentInnerWindowId()); |
3837 | nsPIDOMWindowInner* innerWin = mScriptGlobal->GetCurrentInnerWindow(); |
3838 | if (innerWin) { |
3839 | loadState->SetTriggeringStorageAccess(innerWin->UsingStorageAccess()); |
3840 | } |
3841 | } |
3842 | loadState->SetLoadType(LOAD_ERROR_PAGE); |
3843 | loadState->SetFirstParty(true); |
3844 | loadState->SetSourceBrowsingContext(mBrowsingContext); |
3845 | if (mozilla::SessionHistoryInParent() && mLoadingEntry) { |
3846 | // We keep the loading entry for the load that failed here. If the user |
3847 | // reloads we want to try to reload the original load, not the error page. |
3848 | loadState->SetLoadingSessionHistoryInfo( |
3849 | MakeUnique<LoadingSessionHistoryInfo>(*mLoadingEntry)); |
3850 | } |
3851 | return InternalLoad(loadState); |
3852 | } |
3853 | |
3854 | NS_IMETHODIMPnsresult |
3855 | nsDocShell::Reload(uint32_t aReloadFlags) { |
3856 | if (!IsNavigationAllowed()) { |
3857 | return NS_OK; // JS may not handle returning of an error code |
3858 | } |
3859 | |
3860 | 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)" , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 3861); MOZ_PretendNoReturn(); } } while (0) |
3861 | "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)" , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 3861); MOZ_PretendNoReturn(); } } while (0); |
3862 | 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" , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 3863); MOZ_PretendNoReturn(); } } while (0) |
3863 | "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" , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 3863); MOZ_PretendNoReturn(); } } while (0); |
3864 | |
3865 | uint32_t loadType = MAKE_LOAD_TYPE(LOAD_RELOAD_NORMAL, aReloadFlags)((LOAD_RELOAD_NORMAL) | ((aReloadFlags) << 16)); |
3866 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 3866); return NS_ERROR_INVALID_ARG; } } while (false); |
3867 | |
3868 | // Send notifications to the HistoryListener if any, about the impending |
3869 | // reload |
3870 | RefPtr<ChildSHistory> rootSH = GetRootSessionHistory(); |
3871 | if (mozilla::SessionHistoryInParent()) { |
3872 | 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); |
3873 | bool forceReload = IsForceReloadType(loadType); |
3874 | if (!XRE_IsParentProcess()) { |
3875 | ++mPendingReloadCount; |
3876 | RefPtr<nsDocShell> docShell(this); |
3877 | nsCOMPtr<nsIDocumentViewer> viewer(mDocumentViewer); |
3878 | NS_ENSURE_STATE(viewer)do { if ((__builtin_expect(!!(!(viewer)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "viewer" ") failed", nullptr , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 3878); return NS_ERROR_UNEXPECTED; } } while (false); |
3879 | |
3880 | bool okToUnload = true; |
3881 | MOZ_TRY(viewer->PermitUnload(&okToUnload))do { auto mozTryTempResult_ = ::mozilla::ToResult(viewer-> PermitUnload(&okToUnload)); if ((__builtin_expect(!!(mozTryTempResult_ .isErr()), 0))) { return mozTryTempResult_.propagateErr(); } } while (0); |
3882 | if (!okToUnload) { |
3883 | return NS_OK; |
3884 | } |
3885 | |
3886 | RefPtr<Document> doc(GetDocument()); |
3887 | RefPtr<BrowsingContext> browsingContext(mBrowsingContext); |
3888 | nsCOMPtr<nsIURI> currentURI(mCurrentURI); |
3889 | nsCOMPtr<nsIReferrerInfo> referrerInfo(mReferrerInfo); |
3890 | RefPtr<StopDetector> stopDetector = new StopDetector(); |
3891 | nsCOMPtr<nsILoadGroup> loadGroup; |
3892 | GetLoadGroup(getter_AddRefs(loadGroup)); |
3893 | if (loadGroup) { |
3894 | // loadGroup may be null in theory. In that case stopDetector just |
3895 | // doesn't do anything. |
3896 | loadGroup->AddRequest(stopDetector, nullptr); |
3897 | } |
3898 | |
3899 | ContentChild::GetSingleton()->SendNotifyOnHistoryReload( |
3900 | mBrowsingContext, forceReload, |
3901 | [docShell, doc, loadType, browsingContext, currentURI, referrerInfo, |
3902 | loadGroup, stopDetector]( |
3903 | std::tuple<bool, Maybe<NotNull<RefPtr<nsDocShellLoadState>>>, |
3904 | Maybe<bool>>&& aResult) { |
3905 | auto scopeExit = MakeScopeExit([loadGroup, stopDetector]() { |
3906 | if (loadGroup) { |
3907 | loadGroup->RemoveRequest(stopDetector, nullptr, NS_OK); |
3908 | } |
3909 | }); |
3910 | |
3911 | // Decrease mPendingReloadCount before any other early returns! |
3912 | if (--(docShell->mPendingReloadCount) > 0) { |
3913 | return; |
3914 | } |
3915 | |
3916 | if (stopDetector->Canceled()) { |
3917 | return; |
3918 | } |
3919 | bool canReload; |
3920 | Maybe<NotNull<RefPtr<nsDocShellLoadState>>> loadState; |
3921 | Maybe<bool> reloadingActiveEntry; |
3922 | |
3923 | std::tie(canReload, loadState, reloadingActiveEntry) = aResult; |
3924 | |
3925 | if (!canReload) { |
3926 | return; |
3927 | } |
3928 | |
3929 | if (loadState.isSome()) { |
3930 | 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) |
3931 | 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) |
3932 | ("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); |
3933 | loadState.ref()->SetNotifiedBeforeUnloadListeners(true); |
3934 | docShell->LoadHistoryEntry(loadState.ref(), loadType, |
3935 | reloadingActiveEntry.ref()); |
3936 | } else { |
3937 | 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) |
3938 | ("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); |
3939 | ReloadDocument(docShell, doc, loadType, browsingContext, |
3940 | currentURI, referrerInfo, |
3941 | /* aNotifiedBeforeUnloadListeners */ true); |
3942 | } |
3943 | }, |
3944 | [](mozilla::ipc::ResponseRejectReason) {}); |
3945 | } else { |
3946 | // Parent process |
3947 | bool canReload = false; |
3948 | Maybe<NotNull<RefPtr<nsDocShellLoadState>>> loadState; |
3949 | Maybe<bool> reloadingActiveEntry; |
3950 | if (!mBrowsingContext->IsDiscarded()) { |
3951 | mBrowsingContext->Canonical()->NotifyOnHistoryReload( |
3952 | forceReload, canReload, loadState, reloadingActiveEntry); |
3953 | } |
3954 | if (canReload) { |
3955 | if (loadState.isSome()) { |
3956 | 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) |
3957 | ("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); |
3958 | LoadHistoryEntry(loadState.ref(), loadType, |
3959 | reloadingActiveEntry.ref()); |
3960 | } else { |
3961 | 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) |
3962 | ("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); |
3963 | RefPtr<Document> doc = GetDocument(); |
3964 | RefPtr<BrowsingContext> bc = mBrowsingContext; |
3965 | nsCOMPtr<nsIURI> currentURI = mCurrentURI; |
3966 | nsCOMPtr<nsIReferrerInfo> referrerInfo = mReferrerInfo; |
3967 | ReloadDocument(this, doc, loadType, bc, currentURI, referrerInfo); |
3968 | } |
3969 | } |
3970 | } |
3971 | return NS_OK; |
3972 | } |
3973 | |
3974 | bool canReload = true; |
3975 | if (rootSH) { |
3976 | rootSH->LegacySHistory()->NotifyOnHistoryReload(&canReload); |
3977 | } |
3978 | |
3979 | if (!canReload) { |
3980 | return NS_OK; |
3981 | } |
3982 | |
3983 | /* If you change this part of code, make sure bug 45297 does not re-occur */ |
3984 | if (mOSHE) { |
3985 | nsCOMPtr<nsISHEntry> oshe = mOSHE; |
3986 | return LoadHistoryEntry( |
3987 | oshe, loadType, |
3988 | aReloadFlags & nsIWebNavigation::LOAD_FLAGS_USER_ACTIVATION); |
3989 | } |
3990 | |
3991 | if (mLSHE) { // In case a reload happened before the current load is done |
3992 | nsCOMPtr<nsISHEntry> lshe = mLSHE; |
3993 | return LoadHistoryEntry( |
3994 | lshe, loadType, |
3995 | aReloadFlags & nsIWebNavigation::LOAD_FLAGS_USER_ACTIVATION); |
3996 | } |
3997 | |
3998 | RefPtr<Document> doc = GetDocument(); |
3999 | RefPtr<BrowsingContext> bc = mBrowsingContext; |
4000 | nsCOMPtr<nsIURI> currentURI = mCurrentURI; |
4001 | nsCOMPtr<nsIReferrerInfo> referrerInfo = mReferrerInfo; |
4002 | return ReloadDocument(this, doc, loadType, bc, currentURI, referrerInfo); |
4003 | } |
4004 | |
4005 | /* static */ |
4006 | nsresult nsDocShell::ReloadDocument(nsDocShell* aDocShell, Document* aDocument, |
4007 | uint32_t aLoadType, |
4008 | BrowsingContext* aBrowsingContext, |
4009 | nsIURI* aCurrentURI, |
4010 | nsIReferrerInfo* aReferrerInfo, |
4011 | bool aNotifiedBeforeUnloadListeners) { |
4012 | if (!aDocument) { |
4013 | return NS_OK; |
4014 | } |
4015 | |
4016 | // Do not inherit owner from document |
4017 | uint32_t flags = INTERNAL_LOAD_FLAGS_NONE; |
4018 | nsAutoString srcdoc; |
4019 | nsIURI* baseURI = nullptr; |
4020 | nsCOMPtr<nsIURI> originalURI; |
4021 | nsCOMPtr<nsIURI> resultPrincipalURI; |
4022 | bool loadReplace = false; |
4023 | |
4024 | nsIPrincipal* triggeringPrincipal = aDocument->NodePrincipal(); |
4025 | nsCOMPtr<nsIContentSecurityPolicy> csp = aDocument->GetCsp(); |
4026 | uint32_t triggeringSandboxFlags = aDocument->GetSandboxFlags(); |
4027 | uint64_t triggeringWindowId = aDocument->InnerWindowID(); |
4028 | bool triggeringStorageAccess = aDocument->UsingStorageAccess(); |
4029 | |
4030 | nsAutoString contentTypeHint; |
4031 | aDocument->GetContentType(contentTypeHint); |
4032 | |
4033 | if (aDocument->IsSrcdocDocument()) { |
4034 | aDocument->GetSrcdocData(srcdoc); |
4035 | flags |= INTERNAL_LOAD_FLAGS_IS_SRCDOC; |
4036 | baseURI = aDocument->GetBaseURI(); |
4037 | } else { |
4038 | srcdoc = VoidString(); |
4039 | } |
4040 | nsCOMPtr<nsIChannel> chan = aDocument->GetChannel(); |
4041 | if (chan) { |
4042 | uint32_t loadFlags; |
4043 | chan->GetLoadFlags(&loadFlags); |
4044 | loadReplace = loadFlags & nsIChannel::LOAD_REPLACE; |
4045 | nsCOMPtr<nsIHttpChannel> httpChan(do_QueryInterface(chan)); |
4046 | if (httpChan) { |
4047 | httpChan->GetOriginalURI(getter_AddRefs(originalURI)); |
4048 | } |
4049 | |
4050 | nsCOMPtr<nsILoadInfo> loadInfo = chan->LoadInfo(); |
4051 | loadInfo->GetResultPrincipalURI(getter_AddRefs(resultPrincipalURI)); |
4052 | } |
4053 | |
4054 | if (!triggeringPrincipal) { |
4055 | 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 4055); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "Reload needs a valid triggeringPrincipal" ")"); do { *((volatile int*)__null) = 4055; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
4056 | return NS_ERROR_FAILURE; |
4057 | } |
4058 | |
4059 | // Stack variables to ensure changes to the member variables don't affect to |
4060 | // the call. |
4061 | nsCOMPtr<nsIURI> currentURI = aCurrentURI; |
4062 | |
4063 | // Reload always rewrites result principal URI. |
4064 | Maybe<nsCOMPtr<nsIURI>> emplacedResultPrincipalURI; |
4065 | emplacedResultPrincipalURI.emplace(std::move(resultPrincipalURI)); |
4066 | |
4067 | RefPtr<WindowContext> context = aBrowsingContext->GetCurrentWindowContext(); |
4068 | RefPtr<nsDocShellLoadState> loadState = new nsDocShellLoadState(currentURI); |
4069 | loadState->SetReferrerInfo(aReferrerInfo); |
4070 | loadState->SetOriginalURI(originalURI); |
4071 | loadState->SetMaybeResultPrincipalURI(emplacedResultPrincipalURI); |
4072 | loadState->SetLoadReplace(loadReplace); |
4073 | loadState->SetTriggeringPrincipal(triggeringPrincipal); |
4074 | loadState->SetTriggeringSandboxFlags(triggeringSandboxFlags); |
4075 | loadState->SetTriggeringWindowId(triggeringWindowId); |
4076 | loadState->SetTriggeringStorageAccess(triggeringStorageAccess); |
4077 | loadState->SetPrincipalToInherit(triggeringPrincipal); |
4078 | loadState->SetCsp(csp); |
4079 | loadState->SetInternalLoadFlags(flags); |
4080 | loadState->SetTypeHint(NS_ConvertUTF16toUTF8(contentTypeHint)); |
4081 | loadState->SetLoadType(aLoadType); |
4082 | loadState->SetFirstParty(true); |
4083 | loadState->SetSrcdocData(srcdoc); |
4084 | loadState->SetSourceBrowsingContext(aBrowsingContext); |
4085 | loadState->SetBaseURI(baseURI); |
4086 | loadState->SetHasValidUserGestureActivation( |
4087 | context && context->HasValidTransientUserGestureActivation()); |
4088 | |
4089 | loadState->SetTextDirectiveUserActivation( |
4090 | aDocument->ConsumeTextDirectiveUserActivation() || |
4091 | loadState->HasValidUserGestureActivation()); |
4092 | |
4093 | loadState->SetNotifiedBeforeUnloadListeners(aNotifiedBeforeUnloadListeners); |
4094 | return aDocShell->InternalLoad(loadState); |
4095 | } |
4096 | |
4097 | NS_IMETHODIMPnsresult |
4098 | nsDocShell::Stop(uint32_t aStopFlags) { |
4099 | // Revoke any pending event related to content viewer restoration |
4100 | mRestorePresentationEvent.Revoke(); |
4101 | |
4102 | if (mLoadType == LOAD_ERROR_PAGE) { |
4103 | if (mLSHE) { |
4104 | // Since error page loads never unset mLSHE, do so now |
4105 | SetHistoryEntryAndUpdateBC(Some(nullptr), Some<nsISHEntry*>(mLSHE)); |
4106 | } |
4107 | mActiveEntryIsLoadingFromSessionHistory = false; |
4108 | |
4109 | mFailedChannel = nullptr; |
4110 | mFailedURI = nullptr; |
4111 | } |
4112 | |
4113 | if (nsIWebNavigation::STOP_CONTENT & aStopFlags) { |
4114 | // Stop the document loading and animations |
4115 | if (mDocumentViewer) { |
4116 | nsCOMPtr<nsIDocumentViewer> viewer = mDocumentViewer; |
4117 | viewer->Stop(); |
4118 | } |
4119 | } else if (nsIWebNavigation::STOP_NETWORK & aStopFlags) { |
4120 | // Stop the document loading only |
4121 | if (mDocumentViewer) { |
4122 | RefPtr<Document> doc = mDocumentViewer->GetDocument(); |
4123 | if (doc) { |
4124 | doc->StopDocumentLoad(); |
4125 | } |
4126 | } |
4127 | } |
4128 | |
4129 | if (nsIWebNavigation::STOP_NETWORK & aStopFlags) { |
4130 | // Suspend any timers that were set for this loader. We'll clear |
4131 | // them out for good in CreateDocumentViewer. |
4132 | if (mRefreshURIList) { |
4133 | SuspendRefreshURIs(); |
4134 | mSavedRefreshURIList.swap(mRefreshURIList); |
4135 | mRefreshURIList = nullptr; |
4136 | } |
4137 | |
4138 | // XXXbz We could also pass |this| to nsIURILoader::Stop. That will |
4139 | // just call Stop() on us as an nsIDocumentLoader... We need fewer |
4140 | // redundant apis! |
4141 | Stop(); |
4142 | |
4143 | // Clear out mChannelToDisconnectOnPageHide. This page won't go in the |
4144 | // BFCache now, and the Stop above will have removed the DocumentChannel |
4145 | // from the loadgroup. |
4146 | mChannelToDisconnectOnPageHide = 0; |
4147 | } |
4148 | |
4149 | for (auto* child : mChildList.ForwardRange()) { |
4150 | nsCOMPtr<nsIWebNavigation> shellAsNav(do_QueryObject(child)); |
4151 | if (shellAsNav) { |
4152 | shellAsNav->Stop(aStopFlags); |
4153 | } |
4154 | } |
4155 | |
4156 | return NS_OK; |
4157 | } |
4158 | |
4159 | NS_IMETHODIMPnsresult |
4160 | nsDocShell::GetDocument(Document** aDocument) { |
4161 | NS_ENSURE_ARG_POINTER(aDocument)do { if ((__builtin_expect(!!(!(aDocument)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aDocument" ") failed", nullptr , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 4161); return NS_ERROR_INVALID_POINTER; } } while (false); |
4162 | 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 , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 4162); return NS_ERROR_FAILURE; } } while (false); |
4163 | |
4164 | RefPtr<Document> doc = mDocumentViewer->GetDocument(); |
4165 | if (!doc) { |
4166 | return NS_ERROR_NOT_AVAILABLE; |
4167 | } |
4168 | |
4169 | doc.forget(aDocument); |
4170 | return NS_OK; |
4171 | } |
4172 | |
4173 | NS_IMETHODIMPnsresult |
4174 | nsDocShell::GetCurrentURI(nsIURI** aURI) { |
4175 | NS_ENSURE_ARG_POINTER(aURI)do { if ((__builtin_expect(!!(!(aURI)), 0))) { NS_DebugBreak( NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aURI" ") failed", nullptr , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 4175); return NS_ERROR_INVALID_POINTER; } } while (false); |
4176 | |
4177 | nsCOMPtr<nsIURI> uri = mCurrentURI; |
4178 | uri.forget(aURI); |
4179 | return NS_OK; |
4180 | } |
4181 | |
4182 | NS_IMETHODIMPnsresult |
4183 | nsDocShell::GetSessionHistoryXPCOM(nsISupports** aSessionHistory) { |
4184 | NS_ENSURE_ARG_POINTER(aSessionHistory)do { if ((__builtin_expect(!!(!(aSessionHistory)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aSessionHistory" ") failed" , nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 4184); return NS_ERROR_INVALID_POINTER; } } while (false); |
4185 | RefPtr<ChildSHistory> shistory = GetSessionHistory(); |
4186 | shistory.forget(aSessionHistory); |
4187 | return NS_OK; |
4188 | } |
4189 | |
4190 | //***************************************************************************** |
4191 | // nsDocShell::nsIWebPageDescriptor |
4192 | //***************************************************************************** |
4193 | |
4194 | NS_IMETHODIMPnsresult |
4195 | nsDocShell::LoadPageAsViewSource(nsIDocShell* aOtherDocShell, |
4196 | const nsAString& aURI) { |
4197 | if (!aOtherDocShell) { |
4198 | return NS_ERROR_INVALID_POINTER; |
4199 | } |
4200 | nsCOMPtr<nsIURI> newURI; |
4201 | nsresult rv = NS_NewURI(getter_AddRefs(newURI), aURI); |
4202 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
4203 | return rv; |
4204 | } |
4205 | |
4206 | RefPtr<nsDocShellLoadState> loadState; |
4207 | uint32_t cacheKey; |
4208 | auto* otherDocShell = nsDocShell::Cast(aOtherDocShell); |
4209 | if (mozilla::SessionHistoryInParent()) { |
4210 | loadState = new nsDocShellLoadState(newURI); |
4211 | if (!otherDocShell->FillLoadStateFromCurrentEntry(*loadState)) { |
4212 | return NS_ERROR_INVALID_POINTER; |
4213 | } |
4214 | cacheKey = otherDocShell->GetCacheKeyFromCurrentEntry().valueOr(0); |
4215 | } else { |
4216 | nsCOMPtr<nsISHEntry> entry; |
4217 | bool isOriginalSHE; |
4218 | otherDocShell->GetCurrentSHEntry(getter_AddRefs(entry), &isOriginalSHE); |
4219 | if (!entry) { |
4220 | return NS_ERROR_INVALID_POINTER; |
4221 | } |
4222 | rv = entry->CreateLoadInfo(getter_AddRefs(loadState)); |
4223 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 4223); return rv; } } while (false); |
4224 | entry->GetCacheKey(&cacheKey); |
4225 | loadState->SetURI(newURI); |
4226 | loadState->SetSHEntry(nullptr); |
4227 | } |
4228 | |
4229 | // We're doing a load of the page, via an API that |
4230 | // is only exposed to system code. The triggering principal for this load |
4231 | // should be the system principal. |
4232 | loadState->SetTriggeringPrincipal(nsContentUtils::GetSystemPrincipal()); |
4233 | loadState->SetOriginalURI(nullptr); |
4234 | loadState->SetResultPrincipalURI(nullptr); |
4235 | |
4236 | return InternalLoad(loadState, Some(cacheKey)); |
4237 | } |
4238 | |
4239 | NS_IMETHODIMPnsresult |
4240 | nsDocShell::GetCurrentDescriptor(nsISupports** aPageDescriptor) { |
4241 | 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?" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 4241); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPageDescriptor" ") (" "Null out param?" ")"); do { *((volatile int*)__null) = 4241; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
4242 | |
4243 | *aPageDescriptor = nullptr; |
4244 | |
4245 | nsISHEntry* src = mOSHE ? mOSHE : mLSHE; |
4246 | if (src) { |
4247 | nsCOMPtr<nsISHEntry> dest; |
4248 | |
4249 | nsresult rv = src->Clone(getter_AddRefs(dest)); |
4250 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
4251 | return rv; |
4252 | } |
4253 | |
4254 | // null out inappropriate cloned attributes... |
4255 | dest->SetParent(nullptr); |
4256 | dest->SetIsSubFrame(false); |
4257 | |
4258 | return CallQueryInterface(dest, aPageDescriptor); |
4259 | } |
4260 | |
4261 | return NS_ERROR_NOT_AVAILABLE; |
4262 | } |
4263 | |
4264 | already_AddRefed<nsIInputStream> nsDocShell::GetPostDataFromCurrentEntry() |
4265 | const { |
4266 | nsCOMPtr<nsIInputStream> postData; |
4267 | if (mozilla::SessionHistoryInParent()) { |
4268 | if (mActiveEntry) { |
4269 | postData = mActiveEntry->GetPostData(); |
4270 | } else if (mLoadingEntry) { |
4271 | postData = mLoadingEntry->mInfo.GetPostData(); |
4272 | } |
4273 | } else { |
4274 | if (mOSHE) { |
4275 | postData = mOSHE->GetPostData(); |
4276 | } else if (mLSHE) { |
4277 | postData = mLSHE->GetPostData(); |
4278 | } |
4279 | } |
4280 | |
4281 | return postData.forget(); |
4282 | } |
4283 | |
4284 | Maybe<uint32_t> nsDocShell::GetCacheKeyFromCurrentEntry() const { |
4285 | if (mozilla::SessionHistoryInParent()) { |
4286 | if (mActiveEntry) { |
4287 | return Some(mActiveEntry->GetCacheKey()); |
4288 | } |
4289 | |
4290 | if (mLoadingEntry) { |
4291 | return Some(mLoadingEntry->mInfo.GetCacheKey()); |
4292 | } |
4293 | } else { |
4294 | if (mOSHE) { |
4295 | return Some(mOSHE->GetCacheKey()); |
4296 | } |
4297 | |
4298 | if (mLSHE) { |
4299 | return Some(mLSHE->GetCacheKey()); |
4300 | } |
4301 | } |
4302 | |
4303 | return Nothing(); |
4304 | } |
4305 | |
4306 | bool nsDocShell::FillLoadStateFromCurrentEntry( |
4307 | nsDocShellLoadState& aLoadState) { |
4308 | if (mLoadingEntry) { |
4309 | mLoadingEntry->mInfo.FillLoadInfo(aLoadState); |
4310 | return true; |
4311 | } |
4312 | if (mActiveEntry) { |
4313 | mActiveEntry->FillLoadInfo(aLoadState); |
4314 | return true; |
4315 | } |
4316 | return false; |
4317 | } |
4318 | |
4319 | //***************************************************************************** |
4320 | // nsDocShell::nsIBaseWindow |
4321 | //***************************************************************************** |
4322 | |
4323 | NS_IMETHODIMPnsresult |
4324 | nsDocShell::InitWindow(nativeWindow aParentNativeWindow, |
4325 | nsIWidget* aParentWidget, int32_t aX, int32_t aY, |
4326 | int32_t aWidth, int32_t aHeight) { |
4327 | SetParentWidget(aParentWidget); |
4328 | SetPositionAndSize(aX, aY, aWidth, aHeight, 0); |
4329 | NS_ENSURE_TRUE(Initialize(), NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(Initialize())), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "Initialize()" ") failed" , nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 4329); return NS_ERROR_FAILURE; } } while (false); |
4330 | |
4331 | return NS_OK; |
4332 | } |
4333 | |
4334 | NS_IMETHODIMPnsresult |
4335 | nsDocShell::Destroy() { |
4336 | // XXX: We allow this function to be called just once. If you are going to |
4337 | // reset new variables in this function, please make sure the variables will |
4338 | // never be re-initialized. Adding assertions to check |mIsBeingDestroyed| |
4339 | // in the setter functions for the variables would be enough. |
4340 | if (mIsBeingDestroyed) { |
4341 | return NS_ERROR_DOCSHELL_DYING; |
4342 | } |
4343 | |
4344 | 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", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 4345); MOZ_PretendNoReturn(); } } while (0) |
4345 | "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", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 4345); MOZ_PretendNoReturn(); } } while (0); |
4346 | |
4347 | nsCOMPtr<nsIObserverService> serv = services::GetObserverService(); |
4348 | if (serv) { |
4349 | const char* msg = mItemType == typeContent |
4350 | ? NS_WEBNAVIGATION_DESTROY"webnavigation-destroy" |
4351 | : NS_CHROME_WEBNAVIGATION_DESTROY"chrome-webnavigation-destroy"; |
4352 | serv->NotifyObservers(GetAsSupports(this), msg, nullptr); |
4353 | } |
4354 | |
4355 | mIsBeingDestroyed = true; |
4356 | |
4357 | // Brak the cycle with the initial client, if present. |
4358 | mInitialClientSource.reset(); |
4359 | |
4360 | // Make sure to blow away our mLoadingURI just in case. No loads |
4361 | // from inside this pagehide. |
4362 | mLoadingURI = nullptr; |
4363 | |
4364 | // Fire unload event before we blow anything away. |
4365 | (void)FirePageHideNotification(true); |
4366 | |
4367 | // Clear pointers to any detached nsEditorData that's lying |
4368 | // around in shistory entries. Breaks cycle. See bug 430921. |
4369 | if (mOSHE) { |
4370 | mOSHE->SetEditorData(nullptr); |
4371 | } |
4372 | if (mLSHE) { |
4373 | mLSHE->SetEditorData(nullptr); |
4374 | } |
4375 | |
4376 | // Note: mContentListener can be null if Init() failed and we're being |
4377 | // called from the destructor. |
4378 | if (mContentListener) { |
4379 | mContentListener->DropDocShellReference(); |
4380 | mContentListener->SetParentContentListener(nullptr); |
4381 | // Note that we do NOT set mContentListener to null here; that |
4382 | // way if someone tries to do a load in us after this point |
4383 | // the nsDSURIContentListener will block it. All of which |
4384 | // means that we should do this before calling Stop(), of |
4385 | // course. |
4386 | } |
4387 | |
4388 | // Stop any URLs that are currently being loaded... |
4389 | Stop(nsIWebNavigation::STOP_ALL); |
4390 | |
4391 | mEditorData = nullptr; |
4392 | |
4393 | // Save the state of the current document, before destroying the window. |
4394 | // This is needed to capture the state of a frameset when the new document |
4395 | // causes the frameset to be destroyed... |
4396 | PersistLayoutHistoryState(); |
4397 | |
4398 | // Remove this docshell from its parent's child list |
4399 | nsCOMPtr<nsIDocShellTreeItem> docShellParentAsItem = |
4400 | do_QueryInterface(GetAsSupports(mParent)); |
4401 | if (docShellParentAsItem) { |
4402 | docShellParentAsItem->RemoveChild(this); |
4403 | } |
4404 | |
4405 | if (mDocumentViewer) { |
4406 | mDocumentViewer->Close(nullptr); |
4407 | mDocumentViewer->Destroy(); |
4408 | mDocumentViewer = nullptr; |
4409 | } |
4410 | |
4411 | nsDocLoader::Destroy(); |
4412 | |
4413 | mParentWidget = nullptr; |
4414 | SetCurrentURIInternal(nullptr); |
4415 | |
4416 | if (mScriptGlobal) { |
4417 | mScriptGlobal->DetachFromDocShell(!mWillChangeProcess); |
4418 | mScriptGlobal = nullptr; |
4419 | } |
4420 | |
4421 | if (GetSessionHistory()) { |
4422 | // We want to destroy these content viewers now rather than |
4423 | // letting their destruction wait for the session history |
4424 | // entries to get garbage collected. (Bug 488394) |
4425 | GetSessionHistory()->EvictLocalDocumentViewers(); |
4426 | } |
4427 | |
4428 | if (mWillChangeProcess && !mBrowsingContext->IsDiscarded()) { |
4429 | mBrowsingContext->PrepareForProcessChange(); |
4430 | } |
4431 | |
4432 | SetTreeOwner(nullptr); |
4433 | |
4434 | mBrowserChild = nullptr; |
4435 | |
4436 | mChromeEventHandler = nullptr; |
4437 | |
4438 | // Cancel any timers that were set for this docshell; this is needed |
4439 | // to break the cycle between us and the timers. |
4440 | CancelRefreshURITimers(); |
4441 | |
4442 | return NS_OK; |
4443 | } |
4444 | |
4445 | double nsDocShell::GetWidgetCSSToDeviceScale() { |
4446 | if (mParentWidget) { |
4447 | return mParentWidget->GetDefaultScale().scale; |
4448 | } |
4449 | if (nsCOMPtr<nsIBaseWindow> ownerWindow = do_QueryInterface(mTreeOwner)) { |
4450 | return ownerWindow->GetWidgetCSSToDeviceScale(); |
4451 | } |
4452 | return 1.0; |
4453 | } |
4454 | |
4455 | NS_IMETHODIMPnsresult |
4456 | nsDocShell::GetDevicePixelsPerDesktopPixel(double* aScale) { |
4457 | if (mParentWidget) { |
4458 | *aScale = mParentWidget->GetDesktopToDeviceScale().scale; |
4459 | return NS_OK; |
4460 | } |
4461 | |
4462 | nsCOMPtr<nsIBaseWindow> ownerWindow(do_QueryInterface(mTreeOwner)); |
4463 | if (ownerWindow) { |
4464 | return ownerWindow->GetDevicePixelsPerDesktopPixel(aScale); |
4465 | } |
4466 | |
4467 | *aScale = 1.0; |
4468 | return NS_OK; |
4469 | } |
4470 | |
4471 | NS_IMETHODIMPnsresult |
4472 | nsDocShell::SetPosition(int32_t aX, int32_t aY) { |
4473 | mBounds.MoveTo(aX, aY); |
4474 | |
4475 | if (mDocumentViewer) { |
4476 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 4476); return NS_ERROR_FAILURE; } } while (false); |
4477 | } |
4478 | |
4479 | return NS_OK; |
4480 | } |
4481 | |
4482 | NS_IMETHODIMPnsresult |
4483 | nsDocShell::SetPositionDesktopPix(int32_t aX, int32_t aY) { |
4484 | nsCOMPtr<nsIBaseWindow> ownerWindow(do_QueryInterface(mTreeOwner)); |
4485 | if (ownerWindow) { |
4486 | return ownerWindow->SetPositionDesktopPix(aX, aY); |
4487 | } |
4488 | |
4489 | double scale = 1.0; |
4490 | GetDevicePixelsPerDesktopPixel(&scale); |
4491 | return SetPosition(NSToIntRound(aX * scale), NSToIntRound(aY * scale)); |
4492 | } |
4493 | |
4494 | NS_IMETHODIMPnsresult |
4495 | nsDocShell::GetPosition(int32_t* aX, int32_t* aY) { |
4496 | return GetPositionAndSize(aX, aY, nullptr, nullptr); |
4497 | } |
4498 | |
4499 | NS_IMETHODIMPnsresult |
4500 | nsDocShell::SetSize(int32_t aWidth, int32_t aHeight, bool aRepaint) { |
4501 | int32_t x = 0, y = 0; |
4502 | GetPosition(&x, &y); |
4503 | return SetPositionAndSize(x, y, aWidth, aHeight, |
4504 | aRepaint ? nsIBaseWindow::eRepaint : 0); |
4505 | } |
4506 | |
4507 | NS_IMETHODIMPnsresult |
4508 | nsDocShell::GetSize(int32_t* aWidth, int32_t* aHeight) { |
4509 | return GetPositionAndSize(nullptr, nullptr, aWidth, aHeight); |
4510 | } |
4511 | |
4512 | NS_IMETHODIMPnsresult |
4513 | nsDocShell::SetPositionAndSize(int32_t aX, int32_t aY, int32_t aWidth, |
4514 | int32_t aHeight, uint32_t aFlags) { |
4515 | mBounds.SetRect(aX, aY, aWidth, aHeight); |
4516 | |
4517 | // Hold strong ref, since SetBounds can make us null out mDocumentViewer |
4518 | nsCOMPtr<nsIDocumentViewer> viewer = mDocumentViewer; |
4519 | if (viewer) { |
4520 | uint32_t cvflags = (aFlags & nsIBaseWindow::eDelayResize) |
4521 | ? nsIDocumentViewer::eDelayResize |
4522 | : 0; |
4523 | // XXX Border figured in here or is that handled elsewhere? |
4524 | nsresult rv = viewer->SetBoundsWithFlags(mBounds, cvflags); |
4525 | 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 , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 4525); return NS_ERROR_FAILURE; } } while (false); |
4526 | } |
4527 | |
4528 | return NS_OK; |
4529 | } |
4530 | |
4531 | NS_IMETHODIMPnsresult |
4532 | nsDocShell::GetPositionAndSize(int32_t* aX, int32_t* aY, int32_t* aWidth, |
4533 | int32_t* aHeight) { |
4534 | if (mParentWidget) { |
4535 | // ensure size is up-to-date if window has changed resolution |
4536 | LayoutDeviceIntRect r = mParentWidget->GetClientBounds(); |
4537 | SetPositionAndSize(mBounds.X(), mBounds.Y(), r.Width(), r.Height(), 0); |
4538 | } |
4539 | |
4540 | // We should really consider just getting this information from |
4541 | // our window instead of duplicating the storage and code... |
4542 | if (aWidth || aHeight) { |
4543 | // Caller wants to know our size; make sure to give them up to |
4544 | // date information. |
4545 | RefPtr<Document> doc(do_GetInterface(GetAsSupports(mParent))); |
4546 | if (doc) { |
4547 | doc->FlushPendingNotifications(FlushType::Layout); |
4548 | } |
4549 | } |
4550 | |
4551 | DoGetPositionAndSize(aX, aY, aWidth, aHeight); |
4552 | return NS_OK; |
4553 | } |
4554 | |
4555 | void nsDocShell::DoGetPositionAndSize(int32_t* aX, int32_t* aY, int32_t* aWidth, |
4556 | int32_t* aHeight) { |
4557 | if (aX) { |
4558 | *aX = mBounds.X(); |
4559 | } |
4560 | if (aY) { |
4561 | *aY = mBounds.Y(); |
4562 | } |
4563 | if (aWidth) { |
4564 | *aWidth = mBounds.Width(); |
4565 | } |
4566 | if (aHeight) { |
4567 | *aHeight = mBounds.Height(); |
4568 | } |
4569 | } |
4570 | |
4571 | NS_IMETHODIMPnsresult |
4572 | nsDocShell::SetDimensions(DimensionRequest&& aRequest) { |
4573 | return NS_ERROR_NOT_IMPLEMENTED; |
4574 | } |
4575 | |
4576 | NS_IMETHODIMPnsresult |
4577 | nsDocShell::GetDimensions(DimensionKind aDimensionKind, int32_t* aX, |
4578 | int32_t* aY, int32_t* aCX, int32_t* aCY) { |
4579 | return NS_ERROR_NOT_IMPLEMENTED; |
4580 | } |
4581 | |
4582 | NS_IMETHODIMPnsresult |
4583 | nsDocShell::Repaint(bool aForce) { |
4584 | PresShell* presShell = GetPresShell(); |
4585 | NS_ENSURE_TRUE(presShell, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(presShell)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "presShell" ") failed", nullptr , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 4585); return NS_ERROR_FAILURE; } } while (false); |
4586 | |
4587 | RefPtr<nsViewManager> viewManager = presShell->GetViewManager(); |
4588 | NS_ENSURE_TRUE(viewManager, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(viewManager)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "viewManager" ") failed" , nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 4588); return NS_ERROR_FAILURE; } } while (false); |
4589 | |
4590 | viewManager->InvalidateAllViews(); |
4591 | return NS_OK; |
4592 | } |
4593 | |
4594 | NS_IMETHODIMPnsresult |
4595 | nsDocShell::GetParentWidget(nsIWidget** aParentWidget) { |
4596 | NS_ENSURE_ARG_POINTER(aParentWidget)do { if ((__builtin_expect(!!(!(aParentWidget)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aParentWidget" ") failed" , nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 4596); return NS_ERROR_INVALID_POINTER; } } while (false); |
4597 | |
4598 | *aParentWidget = mParentWidget; |
4599 | NS_IF_ADDREF(*aParentWidget)ns_if_addref(*aParentWidget); |
4600 | |
4601 | return NS_OK; |
4602 | } |
4603 | |
4604 | NS_IMETHODIMPnsresult |
4605 | nsDocShell::SetParentWidget(nsIWidget* aParentWidget) { |
4606 | 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" , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 4606); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mIsBeingDestroyed" ")"); do { *((volatile int*)__null) = 4606; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
4607 | mParentWidget = aParentWidget; |
4608 | |
4609 | return NS_OK; |
4610 | } |
4611 | |
4612 | NS_IMETHODIMPnsresult |
4613 | nsDocShell::GetParentNativeWindow(nativeWindow* aParentNativeWindow) { |
4614 | NS_ENSURE_ARG_POINTER(aParentNativeWindow)do { if ((__builtin_expect(!!(!(aParentNativeWindow)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aParentNativeWindow" ") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 4614); return NS_ERROR_INVALID_POINTER; } } while (false); |
4615 | |
4616 | if (mParentWidget) { |
4617 | *aParentNativeWindow = mParentWidget->GetNativeData(NS_NATIVE_WIDGET3); |
4618 | } else { |
4619 | *aParentNativeWindow = nullptr; |
4620 | } |
4621 | |
4622 | return NS_OK; |
4623 | } |
4624 | |
4625 | NS_IMETHODIMPnsresult |
4626 | nsDocShell::SetParentNativeWindow(nativeWindow aParentNativeWindow) { |
4627 | return NS_ERROR_NOT_IMPLEMENTED; |
4628 | } |
4629 | |
4630 | NS_IMETHODIMPnsresult |
4631 | nsDocShell::GetNativeHandle(nsAString& aNativeHandle) { |
4632 | // the nativeHandle should be accessed from nsIAppWindow |
4633 | return NS_ERROR_NOT_IMPLEMENTED; |
4634 | } |
4635 | |
4636 | NS_IMETHODIMPnsresult |
4637 | nsDocShell::GetVisibility(bool* aVisibility) { |
4638 | NS_ENSURE_ARG_POINTER(aVisibility)do { if ((__builtin_expect(!!(!(aVisibility)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aVisibility" ") failed" , nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 4638); return NS_ERROR_INVALID_POINTER; } } while (false); |
4639 | |
4640 | *aVisibility = false; |
4641 | |
4642 | if (!mDocumentViewer) { |
4643 | return NS_OK; |
4644 | } |
4645 | |
4646 | PresShell* presShell = GetPresShell(); |
4647 | if (!presShell) { |
4648 | return NS_OK; |
4649 | } |
4650 | |
4651 | // get the view manager |
4652 | nsViewManager* vm = presShell->GetViewManager(); |
4653 | NS_ENSURE_TRUE(vm, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(vm)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING , "NS_ENSURE_TRUE(" "vm" ") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 4653); return NS_ERROR_FAILURE; } } while (false); |
4654 | |
4655 | // get the root view |
4656 | nsView* view = vm->GetRootView(); // views are not ref counted |
4657 | NS_ENSURE_TRUE(view, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(view)), 0))) { NS_DebugBreak( NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "view" ") failed", nullptr , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 4657); return NS_ERROR_FAILURE; } } while (false); |
4658 | |
4659 | // if our root view is hidden, we are not visible |
4660 | if (view->GetVisibility() == ViewVisibility::Hide) { |
4661 | return NS_OK; |
4662 | } |
4663 | |
4664 | // otherwise, we must walk up the document and view trees checking |
4665 | // for a hidden view, unless we're an off screen browser, which |
4666 | // would make this test meaningless. |
4667 | |
4668 | RefPtr<nsDocShell> docShell = this; |
4669 | RefPtr<nsDocShell> parentItem = docShell->GetInProcessParentDocshell(); |
4670 | while (parentItem) { |
4671 | // Null-check for crash in bug 267804 |
4672 | if (!parentItem->GetPresShell()) { |
4673 | 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 4673); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: " "parent docshell has null pres shell" ")"); do { *((volatile int*)__null) = 4673; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
4674 | return NS_OK; |
4675 | } |
4676 | |
4677 | vm = docShell->GetPresShell()->GetViewManager(); |
4678 | if (vm) { |
4679 | view = vm->GetRootView(); |
4680 | } |
4681 | |
4682 | if (view) { |
4683 | view = view->GetParent(); // anonymous inner view |
4684 | if (view) { |
4685 | view = view->GetParent(); // subdocumentframe's view |
4686 | } |
4687 | } |
4688 | |
4689 | nsIFrame* frame = view ? view->GetFrame() : nullptr; |
4690 | if (frame && !frame->IsVisibleConsideringAncestors( |
4691 | nsIFrame::VISIBILITY_CROSS_CHROME_CONTENT_BOUNDARY)) { |
4692 | return NS_OK; |
4693 | } |
4694 | |
4695 | docShell = parentItem; |
4696 | parentItem = docShell->GetInProcessParentDocshell(); |
4697 | } |
4698 | |
4699 | nsCOMPtr<nsIBaseWindow> treeOwnerAsWin(do_QueryInterface(mTreeOwner)); |
4700 | if (!treeOwnerAsWin) { |
4701 | *aVisibility = true; |
4702 | return NS_OK; |
4703 | } |
4704 | |
4705 | // Check with the tree owner as well to give embedders a chance to |
4706 | // expose visibility as well. |
4707 | nsresult rv = treeOwnerAsWin->GetVisibility(aVisibility); |
4708 | if (rv == NS_ERROR_NOT_IMPLEMENTED) { |
4709 | // The tree owner had no opinion on our visibility. |
4710 | *aVisibility = true; |
4711 | return NS_OK; |
4712 | } |
4713 | return rv; |
4714 | } |
4715 | |
4716 | void nsDocShell::ActivenessMaybeChanged() { |
4717 | const bool isActive = mBrowsingContext->IsActive(); |
4718 | if (RefPtr<PresShell> presShell = GetPresShell()) { |
4719 | presShell->ActivenessMaybeChanged(); |
4720 | } |
4721 | |
4722 | // Tell the window about it |
4723 | if (mScriptGlobal) { |
4724 | mScriptGlobal->SetIsBackground(!isActive); |
4725 | if (RefPtr<Document> doc = mScriptGlobal->GetExtantDoc()) { |
4726 | // Update orientation when the top-level browsing context becomes active. |
4727 | if (isActive && mBrowsingContext->IsTop()) { |
4728 | // We only care about the top-level browsing context. |
4729 | auto orientation = mBrowsingContext->GetOrientationLock(); |
4730 | ScreenOrientation::UpdateActiveOrientationLock(orientation); |
4731 | } |
4732 | |
4733 | doc->PostVisibilityUpdateEvent(); |
4734 | } |
4735 | } |
4736 | |
4737 | // Tell the nsDOMNavigationTiming about it |
4738 | RefPtr<nsDOMNavigationTiming> timing = mTiming; |
4739 | if (!timing && mDocumentViewer) { |
4740 | if (Document* doc = mDocumentViewer->GetDocument()) { |
4741 | timing = doc->GetNavigationTiming(); |
4742 | } |
4743 | } |
4744 | if (timing) { |
4745 | timing->NotifyDocShellStateChanged( |
4746 | isActive ? nsDOMNavigationTiming::DocShellState::eActive |
4747 | : nsDOMNavigationTiming::DocShellState::eInactive); |
4748 | } |
4749 | |
4750 | // Restart or stop meta refresh timers if necessary |
4751 | if (mDisableMetaRefreshWhenInactive) { |
4752 | if (isActive) { |
4753 | ResumeRefreshURIs(); |
4754 | } else { |
4755 | SuspendRefreshURIs(); |
4756 | } |
4757 | } |
4758 | |
4759 | if (InputTaskManager::CanSuspendInputEvent()) { |
4760 | mBrowsingContext->Group()->UpdateInputTaskManagerIfNeeded(isActive); |
4761 | } |
4762 | } |
4763 | |
4764 | NS_IMETHODIMPnsresult |
4765 | nsDocShell::SetDefaultLoadFlags(uint32_t aDefaultLoadFlags) { |
4766 | if (!mWillChangeProcess) { |
4767 | // Intentionally ignoring handling discarded browsing contexts. |
4768 | Unused << mBrowsingContext->SetDefaultLoadFlags(aDefaultLoadFlags); |
4769 | } else { |
4770 | // Bug 1623565: DevTools tries to clean up defaultLoadFlags on |
4771 | // shutdown. Sorry DevTools, your DocShell is in another process. |
4772 | NS_WARNING("nsDocShell::SetDefaultLoadFlags called on Zombie DocShell")NS_DebugBreak(NS_DEBUG_WARNING, "nsDocShell::SetDefaultLoadFlags called on Zombie DocShell" , nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 4772); |
4773 | } |
4774 | return NS_OK; |
4775 | } |
4776 | |
4777 | NS_IMETHODIMPnsresult |
4778 | nsDocShell::GetDefaultLoadFlags(uint32_t* aDefaultLoadFlags) { |
4779 | *aDefaultLoadFlags = mBrowsingContext->GetDefaultLoadFlags(); |
4780 | return NS_OK; |
4781 | } |
4782 | |
4783 | NS_IMETHODIMPnsresult |
4784 | nsDocShell::GetFailedChannel(nsIChannel** aFailedChannel) { |
4785 | NS_ENSURE_ARG_POINTER(aFailedChannel)do { if ((__builtin_expect(!!(!(aFailedChannel)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aFailedChannel" ") failed" , nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 4785); return NS_ERROR_INVALID_POINTER; } } while (false); |
4786 | Document* doc = GetDocument(); |
4787 | if (!doc) { |
4788 | *aFailedChannel = nullptr; |
4789 | return NS_OK; |
4790 | } |
4791 | NS_IF_ADDREF(*aFailedChannel = doc->GetFailedChannel())ns_if_addref(*aFailedChannel = doc->GetFailedChannel()); |
4792 | return NS_OK; |
4793 | } |
4794 | |
4795 | NS_IMETHODIMPnsresult |
4796 | nsDocShell::SetVisibility(bool aVisibility) { |
4797 | // Show()/Hide() may change mDocumentViewer. |
4798 | nsCOMPtr<nsIDocumentViewer> viewer = mDocumentViewer; |
4799 | if (!viewer) { |
4800 | return NS_OK; |
4801 | } |
4802 | if (aVisibility) { |
4803 | viewer->Show(); |
4804 | } else { |
4805 | viewer->Hide(); |
4806 | } |
4807 | |
4808 | return NS_OK; |
4809 | } |
4810 | |
4811 | NS_IMETHODIMPnsresult |
4812 | nsDocShell::GetEnabled(bool* aEnabled) { |
4813 | NS_ENSURE_ARG_POINTER(aEnabled)do { if ((__builtin_expect(!!(!(aEnabled)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aEnabled" ") failed", nullptr , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 4813); return NS_ERROR_INVALID_POINTER; } } while (false); |
4814 | *aEnabled = true; |
4815 | return NS_ERROR_NOT_IMPLEMENTED; |
4816 | } |
4817 | |
4818 | NS_IMETHODIMPnsresult |
4819 | nsDocShell::SetEnabled(bool aEnabled) { return NS_ERROR_NOT_IMPLEMENTED; } |
4820 | |
4821 | NS_IMETHODIMPnsresult |
4822 | nsDocShell::GetMainWidget(nsIWidget** aMainWidget) { |
4823 | // We don't create our own widget, so simply return the parent one. |
4824 | return GetParentWidget(aMainWidget); |
4825 | } |
4826 | |
4827 | NS_IMETHODIMPnsresult |
4828 | nsDocShell::GetTitle(nsAString& aTitle) { |
4829 | aTitle = mTitle; |
4830 | return NS_OK; |
4831 | } |
4832 | |
4833 | NS_IMETHODIMPnsresult |
4834 | nsDocShell::SetTitle(const nsAString& aTitle) { |
4835 | // Avoid unnecessary updates of the title if the URI and the title haven't |
4836 | // changed. |
4837 | if (mTitleValidForCurrentURI && mTitle == aTitle) { |
4838 | return NS_OK; |
4839 | } |
4840 | |
4841 | // Store local title |
4842 | mTitle = aTitle; |
4843 | mTitleValidForCurrentURI = true; |
4844 | |
4845 | // When title is set on the top object it should then be passed to the |
4846 | // tree owner. |
4847 | if (mBrowsingContext->IsTop()) { |
4848 | nsCOMPtr<nsIBaseWindow> treeOwnerAsWin(do_QueryInterface(mTreeOwner)); |
4849 | if (treeOwnerAsWin) { |
4850 | treeOwnerAsWin->SetTitle(aTitle); |
4851 | } |
4852 | } |
4853 | |
4854 | if (mCurrentURI && mLoadType != LOAD_ERROR_PAGE) { |
4855 | UpdateGlobalHistoryTitle(mCurrentURI); |
4856 | } |
4857 | |
4858 | // Update SessionHistory with the document's title. |
4859 | if (mLoadType != LOAD_BYPASS_HISTORY && mLoadType != LOAD_ERROR_PAGE) { |
4860 | SetTitleOnHistoryEntry(true); |
4861 | } |
4862 | |
4863 | return NS_OK; |
4864 | } |
4865 | |
4866 | void nsDocShell::SetTitleOnHistoryEntry(bool aUpdateEntryInSessionHistory) { |
4867 | if (mOSHE) { |
4868 | mOSHE->SetTitle(mTitle); |
4869 | } |
4870 | |
4871 | if (mActiveEntry && mBrowsingContext) { |
4872 | mActiveEntry->SetTitle(mTitle); |
4873 | if (aUpdateEntryInSessionHistory) { |
4874 | if (XRE_IsParentProcess()) { |
4875 | SessionHistoryEntry* entry = |
4876 | mBrowsingContext->Canonical()->GetActiveSessionHistoryEntry(); |
4877 | if (entry) { |
4878 | entry->SetTitle(mTitle); |
4879 | } |
4880 | } else { |
4881 | mozilla::Unused |
4882 | << ContentChild::GetSingleton()->SendSessionHistoryEntryTitle( |
4883 | mBrowsingContext, mTitle); |
4884 | } |
4885 | } |
4886 | } |
4887 | } |
4888 | |
4889 | nsPoint nsDocShell::GetCurScrollPos() { |
4890 | nsPoint scrollPos; |
4891 | if (ScrollContainerFrame* sf = GetRootScrollContainerFrame()) { |
4892 | scrollPos = sf->GetVisualViewportOffset(); |
4893 | } |
4894 | return scrollPos; |
4895 | } |
4896 | |
4897 | nsresult nsDocShell::SetCurScrollPosEx(int32_t aCurHorizontalPos, |
4898 | int32_t aCurVerticalPos) { |
4899 | ScrollContainerFrame* sf = GetRootScrollContainerFrame(); |
4900 | NS_ENSURE_TRUE(sf, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(sf)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING , "NS_ENSURE_TRUE(" "sf" ") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 4900); return NS_ERROR_FAILURE; } } while (false); |
4901 | |
4902 | ScrollMode scrollMode = |
4903 | sf->IsSmoothScroll() ? ScrollMode::SmoothMsd : ScrollMode::Instant; |
4904 | |
4905 | nsPoint targetPos(aCurHorizontalPos, aCurVerticalPos); |
4906 | sf->ScrollTo(targetPos, scrollMode); |
4907 | |
4908 | // Set the visual viewport offset as well. |
4909 | |
4910 | RefPtr<PresShell> presShell = GetPresShell(); |
4911 | NS_ENSURE_TRUE(presShell, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(presShell)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "presShell" ") failed", nullptr , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 4911); return NS_ERROR_FAILURE; } } while (false); |
4912 | |
4913 | nsPresContext* presContext = presShell->GetPresContext(); |
4914 | NS_ENSURE_TRUE(presContext, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(presContext)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "presContext" ") failed" , nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 4914); return NS_ERROR_FAILURE; } } while (false); |
4915 | |
4916 | // Only the root content document can have a distinct visual viewport offset. |
4917 | if (!presContext->IsRootContentDocumentCrossProcess()) { |
4918 | return NS_OK; |
4919 | } |
4920 | |
4921 | // Not on a platform with a distinct visual viewport - don't bother setting |
4922 | // the visual viewport offset. |
4923 | if (!presShell->IsVisualViewportSizeSet()) { |
4924 | return NS_OK; |
4925 | } |
4926 | |
4927 | presShell->ScrollToVisual(targetPos, layers::FrameMetrics::eMainThread, |
4928 | scrollMode); |
4929 | |
4930 | return NS_OK; |
4931 | } |
4932 | |
4933 | void nsDocShell::SetScrollbarPreference(mozilla::ScrollbarPreference aPref) { |
4934 | if (mScrollbarPref == aPref) { |
4935 | return; |
4936 | } |
4937 | mScrollbarPref = aPref; |
4938 | auto* ps = GetPresShell(); |
4939 | if (!ps) { |
4940 | return; |
4941 | } |
4942 | nsIFrame* rootScrollContainerFrame = ps->GetRootScrollContainerFrame(); |
4943 | if (!rootScrollContainerFrame) { |
4944 | return; |
4945 | } |
4946 | ps->FrameNeedsReflow(rootScrollContainerFrame, |
4947 | IntrinsicDirty::FrameAncestorsAndDescendants, |
4948 | NS_FRAME_IS_DIRTY); |
4949 | } |
4950 | |
4951 | //***************************************************************************** |
4952 | // nsDocShell::nsIRefreshURI |
4953 | //***************************************************************************** |
4954 | |
4955 | NS_IMETHODIMPnsresult |
4956 | nsDocShell::RefreshURI(nsIURI* aURI, nsIPrincipal* aPrincipal, |
4957 | uint32_t aDelay) { |
4958 | 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" , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 4958); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mIsBeingDestroyed" ")"); do { *((volatile int*)__null) = 4958; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
4959 | |
4960 | NS_ENSURE_ARG(aURI)do { if ((__builtin_expect(!!(!(aURI)), 0))) { NS_DebugBreak( NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aURI" ") failed", nullptr , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 4960); return NS_ERROR_INVALID_ARG; } } while (false); |
4961 | |
4962 | /* Check if Meta refresh/redirects are permitted. Some |
4963 | * embedded applications may not want to do this. |
4964 | * Must do this before sending out NOTIFY_REFRESH events |
4965 | * because listeners may have side effects (e.g. displaying a |
4966 | * button to manually trigger the refresh later). |
4967 | */ |
4968 | bool allowRedirects = true; |
4969 | GetAllowMetaRedirects(&allowRedirects); |
4970 | if (!allowRedirects) { |
4971 | return NS_OK; |
4972 | } |
4973 | |
4974 | // If any web progress listeners are listening for NOTIFY_REFRESH events, |
4975 | // give them a chance to block this refresh. |
4976 | bool sameURI; |
4977 | nsresult rv = aURI->Equals(mCurrentURI, &sameURI); |
4978 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
4979 | sameURI = false; |
4980 | } |
4981 | if (!RefreshAttempted(this, aURI, aDelay, sameURI)) { |
4982 | return NS_OK; |
4983 | } |
4984 | |
4985 | nsCOMPtr<nsITimerCallback> refreshTimer = |
4986 | new nsRefreshTimer(this, aURI, aPrincipal, aDelay); |
4987 | |
4988 | BusyFlags busyFlags = GetBusyFlags(); |
4989 | |
4990 | if (!mRefreshURIList) { |
4991 | mRefreshURIList = nsArray::Create(); |
4992 | } |
4993 | |
4994 | if (busyFlags & BUSY_FLAGS_BUSY || |
4995 | (!mBrowsingContext->IsActive() && mDisableMetaRefreshWhenInactive)) { |
4996 | // We don't want to create the timer right now. Instead queue up the |
4997 | // request and trigger the timer in EndPageLoad() or whenever we become |
4998 | // active. |
4999 | mRefreshURIList->AppendElement(refreshTimer); |
5000 | } else { |
5001 | // There is no page loading going on right now. Create the |
5002 | // timer and fire it right away. |
5003 | nsCOMPtr<nsPIDOMWindowOuter> win = GetWindow(); |
5004 | NS_ENSURE_TRUE(win, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(win)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING , "NS_ENSURE_TRUE(" "win" ") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 5004); return NS_ERROR_FAILURE; } } while (false); |
5005 | |
5006 | nsCOMPtr<nsITimer> timer; |
5007 | MOZ_TRY_VAR(timer, NS_NewTimerWithCallback(refreshTimer, aDelay,do { auto mozTryVarTempResult_ = (NS_NewTimerWithCallback(refreshTimer , aDelay, nsITimer::TYPE_ONE_SHOT)); if ((__builtin_expect(!! (mozTryVarTempResult_.isErr()), 0))) { return mozTryVarTempResult_ .propagateErr(); } (timer) = mozTryVarTempResult_.unwrap(); } while (0) |
5008 | nsITimer::TYPE_ONE_SHOT))do { auto mozTryVarTempResult_ = (NS_NewTimerWithCallback(refreshTimer , aDelay, nsITimer::TYPE_ONE_SHOT)); if ((__builtin_expect(!! (mozTryVarTempResult_.isErr()), 0))) { return mozTryVarTempResult_ .propagateErr(); } (timer) = mozTryVarTempResult_.unwrap(); } while (0); |
5009 | |
5010 | mRefreshURIList->AppendElement(timer); // owning timer ref |
5011 | } |
5012 | return NS_OK; |
5013 | } |
5014 | |
5015 | nsresult nsDocShell::ForceRefreshURIFromTimer(nsIURI* aURI, |
5016 | nsIPrincipal* aPrincipal, |
5017 | uint32_t aDelay, |
5018 | nsITimer* aTimer) { |
5019 | 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 5019); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aTimer" ") (" "Must have a timer here" ")"); do { *((volatile int*)__null) = 5019; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
5020 | |
5021 | // Remove aTimer from mRefreshURIList if needed |
5022 | if (mRefreshURIList) { |
5023 | uint32_t n = 0; |
5024 | mRefreshURIList->GetLength(&n); |
5025 | |
5026 | for (uint32_t i = 0; i < n; ++i) { |
5027 | nsCOMPtr<nsITimer> timer = do_QueryElementAt(mRefreshURIList, i); |
5028 | if (timer == aTimer) { |
5029 | mRefreshURIList->RemoveElementAt(i); |
5030 | break; |
5031 | } |
5032 | } |
5033 | } |
5034 | |
5035 | return ForceRefreshURI(aURI, aPrincipal, aDelay); |
5036 | } |
5037 | |
5038 | NS_IMETHODIMPnsresult |
5039 | nsDocShell::ForceRefreshURI(nsIURI* aURI, nsIPrincipal* aPrincipal, |
5040 | uint32_t aDelay) { |
5041 | NS_ENSURE_ARG(aURI)do { if ((__builtin_expect(!!(!(aURI)), 0))) { NS_DebugBreak( NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aURI" ") failed", nullptr , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 5041); return NS_ERROR_INVALID_ARG; } } while (false); |
5042 | |
5043 | RefPtr<nsDocShellLoadState> loadState = new nsDocShellLoadState(aURI); |
5044 | loadState->SetOriginalURI(mCurrentURI); |
5045 | loadState->SetResultPrincipalURI(aURI); |
5046 | loadState->SetResultPrincipalURIIsSome(true); |
5047 | loadState->SetKeepResultPrincipalURIIfSet(true); |
5048 | loadState->SetIsMetaRefresh(true); |
5049 | |
5050 | // Set the triggering pricipal to aPrincipal if available, or current |
5051 | // document's principal otherwise. |
5052 | nsCOMPtr<nsIPrincipal> principal = aPrincipal; |
5053 | RefPtr<Document> doc = GetDocument(); |
5054 | if (!principal) { |
5055 | if (!doc) { |
5056 | return NS_ERROR_FAILURE; |
5057 | } |
5058 | principal = doc->NodePrincipal(); |
5059 | } |
5060 | loadState->SetTriggeringPrincipal(principal); |
5061 | if (doc) { |
5062 | loadState->SetCsp(doc->GetCsp()); |
5063 | loadState->SetHasValidUserGestureActivation( |
5064 | doc->HasValidTransientUserGestureActivation()); |
5065 | |
5066 | loadState->SetTextDirectiveUserActivation( |
5067 | doc->ConsumeTextDirectiveUserActivation() || |
5068 | loadState->HasValidUserGestureActivation()); |
5069 | loadState->SetTriggeringSandboxFlags(doc->GetSandboxFlags()); |
5070 | loadState->SetTriggeringWindowId(doc->InnerWindowID()); |
5071 | loadState->SetTriggeringStorageAccess(doc->UsingStorageAccess()); |
5072 | } |
5073 | |
5074 | loadState->SetPrincipalIsExplicit(true); |
5075 | |
5076 | /* Check if this META refresh causes a redirection |
5077 | * to another site. |
5078 | */ |
5079 | bool equalUri = false; |
5080 | nsresult rv = aURI->Equals(mCurrentURI, &equalUri); |
5081 | |
5082 | nsCOMPtr<nsIReferrerInfo> referrerInfo; |
5083 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && !equalUri && aDelay <= REFRESH_REDIRECT_TIMER15000) { |
5084 | /* It is a META refresh based redirection within the threshold time |
5085 | * we have in mind (15000 ms as defined by REFRESH_REDIRECT_TIMER). |
5086 | * Pass a REPLACE flag to LoadURI(). |
5087 | */ |
5088 | loadState->SetLoadType(LOAD_REFRESH_REPLACE); |
5089 | |
5090 | /* For redirects we mimic HTTP, which passes the |
5091 | * original referrer. |
5092 | * We will pass in referrer but will not send to server |
5093 | */ |
5094 | if (mReferrerInfo) { |
5095 | referrerInfo = static_cast<ReferrerInfo*>(mReferrerInfo.get()) |
5096 | ->CloneWithNewSendReferrer(false); |
5097 | } |
5098 | } else { |
5099 | loadState->SetLoadType(LOAD_REFRESH); |
5100 | /* We do need to pass in a referrer, but we don't want it to |
5101 | * be sent to the server. |
5102 | * For most refreshes the current URI is an appropriate |
5103 | * internal referrer. |
5104 | */ |
5105 | referrerInfo = new ReferrerInfo(mCurrentURI, ReferrerPolicy::_empty, false); |
5106 | } |
5107 | |
5108 | loadState->SetReferrerInfo(referrerInfo); |
5109 | loadState->SetLoadFlags( |
5110 | nsIWebNavigation::LOAD_FLAGS_DISALLOW_INHERIT_PRINCIPAL); |
5111 | loadState->SetFirstParty(true); |
5112 | |
5113 | /* |
5114 | * LoadURI(...) will cancel all refresh timers... This causes the |
5115 | * Timer and its refreshData instance to be released... |
5116 | */ |
5117 | LoadURI(loadState, false); |
5118 | |
5119 | return NS_OK; |
5120 | } |
5121 | |
5122 | static const char16_t* SkipASCIIWhitespace(const char16_t* aStart, |
5123 | const char16_t* aEnd) { |
5124 | const char16_t* iter = aStart; |
5125 | while (iter != aEnd && mozilla::IsAsciiWhitespace(*iter)) { |
5126 | ++iter; |
5127 | } |
5128 | return iter; |
5129 | } |
5130 | |
5131 | static std::tuple<const char16_t*, const char16_t*> ExtractURLString( |
5132 | const char16_t* aPosition, const char16_t* aEnd) { |
5133 | 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" , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 5133); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPosition != aEnd" ")"); do { *((volatile int*)__null) = 5133; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
5134 | |
5135 | // 1. Let urlString be the substring of input from the code point at |
5136 | // position to the end of the string. |
5137 | const char16_t* urlStart = aPosition; |
5138 | const char16_t* urlEnd = aEnd; |
5139 | |
5140 | // 2. If the code point in input pointed to by position is U+0055 (U) or |
5141 | // U+0075 (u), then advance position to the next code point. |
5142 | // Otherwise, jump to the step labeled skip quotes. |
5143 | if (*aPosition == 'U' || *aPosition == 'u') { |
5144 | ++aPosition; |
5145 | |
5146 | // 3. If the code point in input pointed to by position is U+0052 (R) or |
5147 | // U+0072 (r), then advance position to the next code point. |
5148 | // Otherwise, jump to the step labeled parse. |
5149 | if (aPosition == aEnd || (*aPosition != 'R' && *aPosition != 'r')) { |
5150 | return std::make_tuple(urlStart, urlEnd); |
5151 | } |
5152 | |
5153 | ++aPosition; |
5154 | |
5155 | // 4. If the code point in input pointed to by position is U+004C (L) or |
5156 | // U+006C (l), then advance position to the next code point. |
5157 | // Otherwise, jump to the step labeled parse. |
5158 | if (aPosition == aEnd || (*aPosition != 'L' && *aPosition != 'l')) { |
5159 | return std::make_tuple(urlStart, urlEnd); |
5160 | } |
5161 | |
5162 | ++aPosition; |
5163 | |
5164 | // 5. Skip ASCII whitespace within input given position. |
5165 | aPosition = SkipASCIIWhitespace(aPosition, aEnd); |
5166 | |
5167 | // 6. If the code point in input pointed to by position is U+003D (=), |
5168 | // then advance position to the next code point. Otherwise, jump to |
5169 | // the step labeled parse. |
5170 | if (aPosition == aEnd || *aPosition != '=') { |
5171 | return std::make_tuple(urlStart, urlEnd); |
5172 | } |
5173 | |
5174 | ++aPosition; |
5175 | |
5176 | // 7. Skip ASCII whitespace within input given position. |
5177 | aPosition = SkipASCIIWhitespace(aPosition, aEnd); |
5178 | } |
5179 | |
5180 | // 8. Skip quotes: If the code point in input pointed to by position is |
5181 | // U+0027 (') or U+0022 ("), then let quote be that code point, and |
5182 | // advance position to the next code point. Otherwise, let quote be |
5183 | // the empty string. |
5184 | Maybe<char> quote; |
5185 | if (aPosition != aEnd && (*aPosition == '\'' || *aPosition == '"')) { |
5186 | quote.emplace(*aPosition); |
5187 | ++aPosition; |
5188 | } |
5189 | |
5190 | // 9. Set urlString to the substring of input from the code point at |
5191 | // position to the end of the string. |
5192 | urlStart = aPosition; |
5193 | urlEnd = aEnd; |
5194 | |
5195 | // 10. If quote is not the empty string, and there is a code point in |
5196 | // urlString equal to quote, then truncate urlString at that code |
5197 | // point, so that it and all subsequent code points are removed. |
5198 | const char16_t* quotePos; |
5199 | if (quote.isSome() && |
5200 | (quotePos = nsCharTraits<char16_t>::find( |
5201 | urlStart, std::distance(urlStart, aEnd), quote.value()))) { |
5202 | urlEnd = quotePos; |
5203 | } |
5204 | |
5205 | return std::make_tuple(urlStart, urlEnd); |
5206 | } |
5207 | |
5208 | void nsDocShell::SetupRefreshURIFromHeader(Document* aDocument, |
5209 | const nsAString& aHeader) { |
5210 | if (mIsBeingDestroyed) { |
5211 | return; |
5212 | } |
5213 | |
5214 | const char16_t* position = aHeader.BeginReading(); |
5215 | const char16_t* end = aHeader.EndReading(); |
5216 | |
5217 | // See |
5218 | // https://html.spec.whatwg.org/#pragma-directives:shared-declarative-refresh-steps. |
5219 | |
5220 | // 3. Skip ASCII whitespace |
5221 | position = SkipASCIIWhitespace(position, end); |
5222 | |
5223 | // 4. Let time be 0. |
5224 | CheckedInt<uint32_t> milliSeconds; |
5225 | |
5226 | // 5. Collect a sequence of code points that are ASCII digits |
5227 | const char16_t* digitsStart = position; |
5228 | while (position != end && mozilla::IsAsciiDigit(*position)) { |
5229 | ++position; |
5230 | } |
5231 | |
5232 | if (position == digitsStart) { |
5233 | // 6. If timeString is the empty string, then: |
5234 | // 1. If the code point in input pointed to by position is not U+002E |
5235 | // (.), then return. |
5236 | if (position == end || *position != '.') { |
5237 | return; |
5238 | } |
5239 | } else { |
5240 | // 7. Otherwise, set time to the result of parsing timeString using the |
5241 | // rules for parsing non-negative integers. |
5242 | nsContentUtils::ParseHTMLIntegerResultFlags result; |
5243 | uint32_t seconds = |
5244 | nsContentUtils::ParseHTMLInteger(digitsStart, position, &result); |
5245 | 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)" , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 5245); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!(result & nsContentUtils::eParseHTMLInteger_Negative)" ")"); do { *((volatile int*)__null) = 5245; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
5246 | if (result & nsContentUtils::eParseHTMLInteger_Error) { |
5247 | // The spec assumes no errors here (since we only pass ASCII digits in), |
5248 | // but we can still overflow, so this block should deal with that (and |
5249 | // only that). |
5250 | MOZ_ASSERT(!(result & nsContentUtils::eParseHTMLInteger_ErrorOverflow))do { static_assert( mozilla::detail::AssertionConditionType< decltype(!(result & nsContentUtils::eParseHTMLInteger_ErrorOverflow ))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(!(result & nsContentUtils::eParseHTMLInteger_ErrorOverflow )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("!(result & nsContentUtils::eParseHTMLInteger_ErrorOverflow)" , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 5250); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!(result & nsContentUtils::eParseHTMLInteger_ErrorOverflow)" ")"); do { *((volatile int*)__null) = 5250; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
5251 | return; |
5252 | } |
5253 | 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)" , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 5254); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!(result & nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput)" ")"); do { *((volatile int*)__null) = 5254; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
5254 | !(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)" , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 5254); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!(result & nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput)" ")"); do { *((volatile int*)__null) = 5254; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
5255 | |
5256 | milliSeconds = seconds; |
5257 | milliSeconds *= 1000; |
5258 | if (!milliSeconds.isValid()) { |
5259 | return; |
5260 | } |
5261 | } |
5262 | |
5263 | // 8. Collect a sequence of code points that are ASCII digits and U+002E FULL |
5264 | // STOP characters (.) from input given position. Ignore any collected |
5265 | // characters. |
5266 | while (position != end && |
5267 | (mozilla::IsAsciiDigit(*position) || *position == '.')) { |
5268 | ++position; |
5269 | } |
5270 | |
5271 | // 9. Let urlRecord be document's URL. |
5272 | nsCOMPtr<nsIURI> urlRecord(aDocument->GetDocumentURI()); |
5273 | |
5274 | // 10. If position is not past the end of input |
5275 | if (position != end) { |
5276 | // 1. If the code point in input pointed to by position is not U+003B (;), |
5277 | // U+002C (,), or ASCII whitespace, then return. |
5278 | if (*position != ';' && *position != ',' && |
5279 | !mozilla::IsAsciiWhitespace(*position)) { |
5280 | return; |
5281 | } |
5282 | |
5283 | // 2. Skip ASCII whitespace within input given position. |
5284 | position = SkipASCIIWhitespace(position, end); |
5285 | |
5286 | // 3. If the code point in input pointed to by position is U+003B (;) or |
5287 | // U+002C (,), then advance position to the next code point. |
5288 | if (position != end && (*position == ';' || *position == ',')) { |
5289 | ++position; |
5290 | |
5291 | // 4. Skip ASCII whitespace within input given position. |
5292 | position = SkipASCIIWhitespace(position, end); |
5293 | } |
5294 | |
5295 | // 11. If position is not past the end of input, then: |
5296 | if (position != end) { |
5297 | const char16_t* urlStart; |
5298 | const char16_t* urlEnd; |
5299 | |
5300 | // 1-10. See ExtractURLString. |
5301 | std::tie(urlStart, urlEnd) = ExtractURLString(position, end); |
5302 | |
5303 | // 11. Parse: Parse urlString relative to document. If that fails, return. |
5304 | // Otherwise, set urlRecord to the resulting URL record. |
5305 | nsresult rv = |
5306 | NS_NewURI(getter_AddRefs(urlRecord), |
5307 | Substring(urlStart, std::distance(urlStart, urlEnd)), |
5308 | /* charset = */ nullptr, aDocument->GetDocBaseURI()); |
5309 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 5309); return; } } while (false); |
5310 | } |
5311 | } |
5312 | |
5313 | nsIPrincipal* principal = aDocument->NodePrincipal(); |
5314 | nsCOMPtr<nsIScriptSecurityManager> securityManager = |
5315 | nsContentUtils::GetSecurityManager(); |
5316 | nsresult rv = securityManager->CheckLoadURIWithPrincipal( |
5317 | principal, urlRecord, |
5318 | nsIScriptSecurityManager::LOAD_IS_AUTOMATIC_DOCUMENT_REPLACEMENT, |
5319 | aDocument->InnerWindowID()); |
5320 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 5320); return; } } while (false); |
5321 | |
5322 | bool isjs = true; |
5323 | rv = NS_URIChainHasFlags( |
5324 | urlRecord, nsIProtocolHandler::URI_OPENING_EXECUTES_SCRIPT, &isjs); |
5325 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 5325); return; } } while (false); |
5326 | |
5327 | if (isjs) { |
5328 | return; |
5329 | } |
5330 | |
5331 | RefreshURI(urlRecord, principal, milliSeconds.value()); |
5332 | } |
5333 | |
5334 | static void DoCancelRefreshURITimers(nsIMutableArray* aTimerList) { |
5335 | if (!aTimerList) { |
5336 | return; |
5337 | } |
5338 | |
5339 | uint32_t n = 0; |
5340 | aTimerList->GetLength(&n); |
5341 | |
5342 | while (n) { |
5343 | nsCOMPtr<nsITimer> timer(do_QueryElementAt(aTimerList, --n)); |
5344 | |
5345 | aTimerList->RemoveElementAt(n); // bye bye owning timer ref |
5346 | |
5347 | if (timer) { |
5348 | timer->Cancel(); |
5349 | } |
5350 | } |
5351 | } |
5352 | |
5353 | NS_IMETHODIMPnsresult |
5354 | nsDocShell::CancelRefreshURITimers() { |
5355 | DoCancelRefreshURITimers(mRefreshURIList); |
5356 | DoCancelRefreshURITimers(mSavedRefreshURIList); |
5357 | DoCancelRefreshURITimers(mBFCachedRefreshURIList); |
5358 | mRefreshURIList = nullptr; |
5359 | mSavedRefreshURIList = nullptr; |
5360 | mBFCachedRefreshURIList = nullptr; |
5361 | |
5362 | return NS_OK; |
5363 | } |
5364 | |
5365 | NS_IMETHODIMPnsresult |
5366 | nsDocShell::GetRefreshPending(bool* aResult) { |
5367 | if (!mRefreshURIList) { |
5368 | *aResult = false; |
5369 | return NS_OK; |
5370 | } |
5371 | |
5372 | uint32_t count; |
5373 | nsresult rv = mRefreshURIList->GetLength(&count); |
5374 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) { |
5375 | *aResult = (count != 0); |
5376 | } |
5377 | return rv; |
5378 | } |
5379 | |
5380 | void nsDocShell::RefreshURIToQueue() { |
5381 | if (mRefreshURIList) { |
5382 | uint32_t n = 0; |
5383 | mRefreshURIList->GetLength(&n); |
5384 | |
5385 | for (uint32_t i = 0; i < n; ++i) { |
5386 | nsCOMPtr<nsITimer> timer = do_QueryElementAt(mRefreshURIList, i); |
5387 | if (!timer) { |
5388 | continue; // this must be a nsRefreshURI already |
5389 | } |
5390 | |
5391 | // Replace this timer object with a nsRefreshTimer object. |
5392 | nsCOMPtr<nsITimerCallback> callback; |
5393 | timer->GetCallback(getter_AddRefs(callback)); |
5394 | |
5395 | timer->Cancel(); |
5396 | |
5397 | mRefreshURIList->ReplaceElementAt(callback, i); |
5398 | } |
5399 | } |
5400 | } |
5401 | |
5402 | NS_IMETHODIMPnsresult |
5403 | nsDocShell::SuspendRefreshURIs() { |
5404 | RefreshURIToQueue(); |
5405 | |
5406 | // Suspend refresh URIs for our child shells as well. |
5407 | for (auto* child : mChildList.ForwardRange()) { |
5408 | nsCOMPtr<nsIDocShell> shell = do_QueryObject(child); |
5409 | if (shell) { |
5410 | shell->SuspendRefreshURIs(); |
5411 | } |
5412 | } |
5413 | |
5414 | return NS_OK; |
5415 | } |
5416 | |
5417 | NS_IMETHODIMPnsresult |
5418 | nsDocShell::ResumeRefreshURIs() { |
5419 | RefreshURIFromQueue(); |
5420 | |
5421 | // Resume refresh URIs for our child shells as well. |
5422 | for (auto* child : mChildList.ForwardRange()) { |
5423 | nsCOMPtr<nsIDocShell> shell = do_QueryObject(child); |
5424 | if (shell) { |
5425 | shell->ResumeRefreshURIs(); |
5426 | } |
5427 | } |
5428 | |
5429 | return NS_OK; |
5430 | } |
5431 | |
5432 | nsresult nsDocShell::RefreshURIFromQueue() { |
5433 | if (!mRefreshURIList) { |
5434 | return NS_OK; |
5435 | } |
5436 | uint32_t n = 0; |
5437 | mRefreshURIList->GetLength(&n); |
5438 | |
5439 | while (n) { |
5440 | nsCOMPtr<nsITimerCallback> refreshInfo = |
5441 | do_QueryElementAt(mRefreshURIList, --n); |
5442 | |
5443 | if (refreshInfo) { |
5444 | // This is the nsRefreshTimer object, waiting to be |
5445 | // setup in a timer object and fired. |
5446 | // Create the timer and trigger it. |
5447 | uint32_t delay = static_cast<nsRefreshTimer*>( |
5448 | static_cast<nsITimerCallback*>(refreshInfo)) |
5449 | ->GetDelay(); |
5450 | nsCOMPtr<nsPIDOMWindowOuter> win = GetWindow(); |
5451 | if (win) { |
5452 | nsCOMPtr<nsITimer> timer; |
5453 | NS_NewTimerWithCallback(getter_AddRefs(timer), refreshInfo, delay, |
5454 | nsITimer::TYPE_ONE_SHOT); |
5455 | |
5456 | if (timer) { |
5457 | // Replace the nsRefreshTimer element in the queue with |
5458 | // its corresponding timer object, so that in case another |
5459 | // load comes through before the timer can go off, the timer will |
5460 | // get cancelled in CancelRefreshURITimer() |
5461 | mRefreshURIList->ReplaceElementAt(timer, n); |
5462 | } |
5463 | } |
5464 | } |
5465 | } |
5466 | |
5467 | return NS_OK; |
5468 | } |
5469 | |
5470 | static bool IsFollowupPartOfMultipart(nsIRequest* aRequest) { |
5471 | nsCOMPtr<nsIMultiPartChannel> multiPartChannel = do_QueryInterface(aRequest); |
5472 | bool firstPart = false; |
5473 | return multiPartChannel && |
5474 | NS_SUCCEEDED(multiPartChannel->GetIsFirstPart(&firstPart))((bool)(__builtin_expect(!!(!NS_FAILED_impl(multiPartChannel-> GetIsFirstPart(&firstPart))), 1))) && |
5475 | !firstPart; |
5476 | } |
5477 | |
5478 | nsresult nsDocShell::Embed(nsIDocumentViewer* aDocumentViewer, |
5479 | WindowGlobalChild* aWindowActor, |
5480 | bool aIsTransientAboutBlank, bool aPersist, |
5481 | nsIRequest* aRequest, nsIURI* aPreviousURI) { |
5482 | // Save the LayoutHistoryState of the previous document, before |
5483 | // setting up new document |
5484 | PersistLayoutHistoryState(); |
5485 | |
5486 | nsresult rv = SetupNewViewer(aDocumentViewer, aWindowActor); |
5487 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 5487); return rv; } } while (false); |
5488 | |
5489 | // XXX What if SetupNewViewer fails? |
5490 | if (mozilla::SessionHistoryInParent() ? !!mLoadingEntry : !!mLSHE) { |
5491 | // Set history.state |
5492 | SetDocCurrentStateObj(mLSHE, |
5493 | mLoadingEntry ? &mLoadingEntry->mInfo : nullptr); |
5494 | } |
5495 | |
5496 | if (mLSHE) { |
5497 | // Restore the editing state, if it's stored in session history. |
5498 | if (mLSHE->HasDetachedEditor()) { |
5499 | ReattachEditorToWindow(mLSHE); |
5500 | } |
5501 | |
5502 | SetHistoryEntryAndUpdateBC(Nothing(), Some<nsISHEntry*>(mLSHE)); |
5503 | } |
5504 | |
5505 | if (!aIsTransientAboutBlank && mozilla::SessionHistoryInParent() && |
5506 | !IsFollowupPartOfMultipart(aRequest)) { |
5507 | bool expired = false; |
5508 | uint32_t cacheKey = 0; |
5509 | nsCOMPtr<nsICacheInfoChannel> cacheChannel = do_QueryInterface(aRequest); |
5510 | if (cacheChannel) { |
5511 | // Check if the page has expired from cache |
5512 | uint32_t expTime = 0; |
5513 | cacheChannel->GetCacheTokenExpirationTime(&expTime); |
5514 | uint32_t now = PRTimeToSeconds(PR_Now()); |
5515 | if (expTime <= now) { |
5516 | expired = true; |
5517 | } |
5518 | |
5519 | // The checks for updating cache key are similar to the old session |
5520 | // history in OnNewURI. Try to update the cache key if |
5521 | // - we should update session history and aren't doing a session |
5522 | // history load. |
5523 | // - we're doing a forced reload. |
5524 | if (((!mLoadingEntry || !mLoadingEntry->mLoadIsFromSessionHistory) && |
5525 | mBrowsingContext->ShouldUpdateSessionHistory(mLoadType)) || |
5526 | IsForceReloadType(mLoadType)) { |
5527 | cacheChannel->GetCacheKey(&cacheKey); |
5528 | } |
5529 | } |
5530 | |
5531 | 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); |
5532 | MoveLoadingToActiveEntry(aPersist, expired, cacheKey, aPreviousURI); |
5533 | } |
5534 | |
5535 | bool updateHistory = true; |
5536 | |
5537 | // Determine if this type of load should update history |
5538 | switch (mLoadType) { |
5539 | case LOAD_NORMAL_REPLACE: |
5540 | case LOAD_REFRESH_REPLACE: |
5541 | case LOAD_STOP_CONTENT_AND_REPLACE: |
5542 | case LOAD_RELOAD_BYPASS_CACHE: |
5543 | case LOAD_RELOAD_BYPASS_PROXY: |
5544 | case LOAD_RELOAD_BYPASS_PROXY_AND_CACHE: |
5545 | case LOAD_REPLACE_BYPASS_CACHE: |
5546 | updateHistory = false; |
5547 | break; |
5548 | default: |
5549 | break; |
5550 | } |
5551 | |
5552 | if (!updateHistory) { |
5553 | SetLayoutHistoryState(nullptr); |
5554 | } |
5555 | |
5556 | return NS_OK; |
5557 | } |
5558 | |
5559 | //***************************************************************************** |
5560 | // nsDocShell::nsIWebProgressListener |
5561 | //***************************************************************************** |
5562 | |
5563 | NS_IMETHODIMPnsresult |
5564 | nsDocShell::OnProgressChange(nsIWebProgress* aProgress, nsIRequest* aRequest, |
5565 | int32_t aCurSelfProgress, int32_t aMaxSelfProgress, |
5566 | int32_t aCurTotalProgress, |
5567 | int32_t aMaxTotalProgress) { |
5568 | return NS_OK; |
5569 | } |
5570 | |
5571 | NS_IMETHODIMPnsresult |
5572 | nsDocShell::OnStateChange(nsIWebProgress* aProgress, nsIRequest* aRequest, |
5573 | uint32_t aStateFlags, nsresult aStatus) { |
5574 | if ((~aStateFlags & (STATE_START | STATE_IS_NETWORK)) == 0) { |
5575 | // Save timing statistics. |
5576 | nsCOMPtr<nsIChannel> channel(do_QueryInterface(aRequest)); |
5577 | nsCOMPtr<nsIURI> uri; |
5578 | channel->GetURI(getter_AddRefs(uri)); |
5579 | nsAutoCString aURI; |
5580 | uri->GetAsciiSpec(aURI); |
5581 | |
5582 | if (this == aProgress) { |
5583 | mozilla::Unused << MaybeInitTiming(); |
5584 | mTiming->NotifyFetchStart(uri, |
5585 | ConvertLoadTypeToNavigationType(mLoadType)); |
5586 | // If we are starting a DocumentChannel, we need to pass the timing |
5587 | // statistics so that should a process switch occur, the starting type can |
5588 | // be passed to the new DocShell running in the other content process. |
5589 | if (RefPtr<DocumentChannel> docChannel = do_QueryObject(aRequest)) { |
5590 | docChannel->SetNavigationTiming(mTiming); |
5591 | } |
5592 | } |
5593 | |
5594 | // Page has begun to load |
5595 | mBusyFlags = (BusyFlags)(BUSY_FLAGS_BUSY | BUSY_FLAGS_BEFORE_PAGE_LOAD); |
5596 | |
5597 | if ((aStateFlags & STATE_RESTORING) == 0) { |
5598 | if (SessionStorePlatformCollection()) { |
5599 | if (IsForceReloadType(mLoadType)) { |
5600 | if (WindowContext* windowContext = |
5601 | mBrowsingContext->GetCurrentWindowContext()) { |
5602 | SessionStoreChild::From(windowContext->GetWindowGlobalChild()) |
5603 | ->ResetSessionStore(mBrowsingContext, |
5604 | mBrowsingContext->GetSessionStoreEpoch()); |
5605 | } |
5606 | } |
5607 | } |
5608 | } |
5609 | } else if ((~aStateFlags & (STATE_TRANSFERRING | STATE_IS_DOCUMENT)) == 0) { |
5610 | // Page is loading |
5611 | mBusyFlags = (BusyFlags)(BUSY_FLAGS_BUSY | BUSY_FLAGS_PAGE_LOADING); |
5612 | } else if ((aStateFlags & STATE_STOP) && (aStateFlags & STATE_IS_NETWORK)) { |
5613 | // Page has finished loading |
5614 | mBusyFlags = BUSY_FLAGS_NONE; |
5615 | } |
5616 | |
5617 | if ((~aStateFlags & (STATE_IS_DOCUMENT | STATE_STOP)) == 0) { |
5618 | nsCOMPtr<nsIWebProgress> webProgress = |
5619 | do_QueryInterface(GetAsSupports(this)); |
5620 | // Is the document stop notification for this document? |
5621 | if (aProgress == webProgress.get()) { |
5622 | nsCOMPtr<nsIChannel> channel(do_QueryInterface(aRequest)); |
5623 | EndPageLoad(aProgress, channel, aStatus); |
5624 | } |
5625 | } |
5626 | // note that redirect state changes will go through here as well, but it |
5627 | // is better to handle those in OnRedirectStateChange where more |
5628 | // information is available. |
5629 | return NS_OK; |
5630 | } |
5631 | |
5632 | NS_IMETHODIMPnsresult |
5633 | nsDocShell::OnLocationChange(nsIWebProgress* aProgress, nsIRequest* aRequest, |
5634 | nsIURI* aURI, uint32_t aFlags) { |
5635 | // Since we've now changed Documents, notify the BrowsingContext that we've |
5636 | // changed. Ideally we'd just let the BrowsingContext do this when it |
5637 | // changes the current window global, but that happens before this and we |
5638 | // have a lot of tests that depend on the specific ordering of messages. |
5639 | bool isTopLevel = false; |
5640 | if (XRE_IsParentProcess() && |
5641 | !(aFlags & nsIWebProgressListener::LOCATION_CHANGE_SAME_DOCUMENT) && |
5642 | NS_SUCCEEDED(aProgress->GetIsTopLevel(&isTopLevel))((bool)(__builtin_expect(!!(!NS_FAILED_impl(aProgress->GetIsTopLevel (&isTopLevel))), 1))) && isTopLevel) { |
5643 | GetBrowsingContext()->Canonical()->UpdateSecurityState(); |
5644 | } |
5645 | return NS_OK; |
5646 | } |
5647 | |
5648 | void nsDocShell::OnRedirectStateChange(nsIChannel* aOldChannel, |
5649 | nsIChannel* aNewChannel, |
5650 | uint32_t aRedirectFlags, |
5651 | uint32_t aStateFlags) { |
5652 | 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", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 5653); MOZ_PretendNoReturn(); } } while (0) |
5653 | "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", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 5653); MOZ_PretendNoReturn(); } } while (0); |
5654 | |
5655 | if (!(aStateFlags & STATE_IS_DOCUMENT)) { |
5656 | return; // not a toplevel document |
5657 | } |
5658 | |
5659 | nsCOMPtr<nsIURI> oldURI, newURI; |
5660 | aOldChannel->GetURI(getter_AddRefs(oldURI)); |
5661 | aNewChannel->GetURI(getter_AddRefs(newURI)); |
5662 | if (!oldURI || !newURI) { |
5663 | return; |
5664 | } |
5665 | |
5666 | // DocumentChannel adds redirect chain to global history in the parent |
5667 | // process. The redirect chain can't be queried from the content process, so |
5668 | // there's no need to update global history here. |
5669 | RefPtr<DocumentChannel> docChannel = do_QueryObject(aOldChannel); |
5670 | if (!docChannel) { |
5671 | // Below a URI visit is saved (see AddURIVisit method doc). |
5672 | // The visit chain looks something like: |
5673 | // ... |
5674 | // Site N - 1 |
5675 | // => Site N |
5676 | // (redirect to =>) Site N + 1 (we are here!) |
5677 | |
5678 | // Get N - 1 and transition type |
5679 | nsCOMPtr<nsIURI> previousURI; |
5680 | uint32_t previousFlags = 0; |
5681 | ExtractLastVisit(aOldChannel, getter_AddRefs(previousURI), &previousFlags); |
5682 | |
5683 | if (aRedirectFlags & nsIChannelEventSink::REDIRECT_INTERNAL || |
5684 | net::ChannelIsPost(aOldChannel)) { |
5685 | // 1. Internal redirects are ignored because they are specific to the |
5686 | // channel implementation. |
5687 | // 2. POSTs are not saved by global history. |
5688 | // |
5689 | // Regardless, we need to propagate the previous visit to the new |
5690 | // channel. |
5691 | SaveLastVisit(aNewChannel, previousURI, previousFlags); |
5692 | } else { |
5693 | // Get the HTTP response code, if available. |
5694 | uint32_t responseStatus = 0; |
5695 | nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aOldChannel); |
5696 | if (httpChannel) { |
5697 | Unused << httpChannel->GetResponseStatus(&responseStatus); |
5698 | } |
5699 | |
5700 | // Add visit N -1 => N |
5701 | AddURIVisit(oldURI, previousURI, previousFlags, responseStatus); |
5702 | |
5703 | // Since N + 1 could be the final destination, we will not save N => N + 1 |
5704 | // here. OnNewURI will do that, so we will cache it. |
5705 | SaveLastVisit(aNewChannel, oldURI, aRedirectFlags); |
5706 | } |
5707 | } |
5708 | |
5709 | if (!(aRedirectFlags & nsIChannelEventSink::REDIRECT_INTERNAL) && |
5710 | mLoadType & (LOAD_CMD_RELOAD | LOAD_CMD_HISTORY)) { |
5711 | mLoadType = LOAD_NORMAL_REPLACE; |
5712 | SetHistoryEntryAndUpdateBC(Some(nullptr), Nothing()); |
5713 | } |
5714 | } |
5715 | |
5716 | NS_IMETHODIMPnsresult |
5717 | nsDocShell::OnStatusChange(nsIWebProgress* aWebProgress, nsIRequest* aRequest, |
5718 | nsresult aStatus, const char16_t* aMessage) { |
5719 | 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(...)" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 5719); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: " "notification excluded in AddProgressListener(...)" ")"); do { *((volatile int*)__null) = 5719; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
5720 | return NS_OK; |
5721 | } |
5722 | |
5723 | NS_IMETHODIMPnsresult |
5724 | nsDocShell::OnSecurityChange(nsIWebProgress* aWebProgress, nsIRequest* aRequest, |
5725 | uint32_t aState) { |
5726 | 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(...)" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 5726); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: " "notification excluded in AddProgressListener(...)" ")"); do { *((volatile int*)__null) = 5726; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
5727 | return NS_OK; |
5728 | } |
5729 | |
5730 | NS_IMETHODIMPnsresult |
5731 | nsDocShell::OnContentBlockingEvent(nsIWebProgress* aWebProgress, |
5732 | nsIRequest* aRequest, uint32_t aEvent) { |
5733 | 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(...)" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 5733); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: " "notification excluded in AddProgressListener(...)" ")"); do { *((volatile int*)__null) = 5733; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
5734 | return NS_OK; |
5735 | } |
5736 | |
5737 | already_AddRefed<nsIURIFixupInfo> nsDocShell::KeywordToURI( |
5738 | const nsACString& aKeyword, bool aIsPrivateContext) { |
5739 | nsCOMPtr<nsIURIFixupInfo> info; |
5740 | if (!XRE_IsContentProcess()) { |
5741 | nsCOMPtr<nsIURIFixup> uriFixup = components::URIFixup::Service(); |
5742 | if (uriFixup) { |
5743 | uriFixup->KeywordToURI(aKeyword, aIsPrivateContext, getter_AddRefs(info)); |
5744 | } |
5745 | } |
5746 | return info.forget(); |
5747 | } |
5748 | |
5749 | /* static */ |
5750 | already_AddRefed<nsIURI> nsDocShell::MaybeFixBadCertDomainErrorURI( |
5751 | nsIChannel* aChannel, nsIURI* aUrl) { |
5752 | if (!aChannel) { |
5753 | return nullptr; |
5754 | } |
5755 | |
5756 | nsresult rv = NS_OK; |
5757 | nsAutoCString host; |
5758 | rv = aUrl->GetAsciiHost(host); |
5759 | if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv )), 0))), "NS_FAILED(rv)", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 5759)) { |
5760 | return nullptr; |
5761 | } |
5762 | |
5763 | // Return if fixup enable pref is turned off. |
5764 | if (!mozilla::StaticPrefs::security_bad_cert_domain_error_url_fix_enabled()) { |
5765 | return nullptr; |
5766 | } |
5767 | |
5768 | // Return if scheme is not HTTPS. |
5769 | if (!SchemeIsHTTPS(aUrl)) { |
5770 | return nullptr; |
5771 | } |
5772 | |
5773 | nsCOMPtr<nsILoadInfo> info = aChannel->LoadInfo(); |
5774 | if (!info) { |
5775 | return nullptr; |
5776 | } |
5777 | |
5778 | // Skip doing the fixup if our channel was redirected, because we |
5779 | // shouldn't be guessing things about the post-redirect URI. |
5780 | if (!info->RedirectChain().IsEmpty()) { |
5781 | return nullptr; |
5782 | } |
5783 | |
5784 | int32_t port = 0; |
5785 | rv = aUrl->GetPort(&port); |
5786 | if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv )), 0))), "NS_FAILED(rv)", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 5786)) { |
5787 | return nullptr; |
5788 | } |
5789 | |
5790 | // Don't fix up hosts with ports. |
5791 | if (port != -1) { |
5792 | return nullptr; |
5793 | } |
5794 | |
5795 | // Don't fix up localhost url. |
5796 | if (host == "localhost") { |
5797 | return nullptr; |
5798 | } |
5799 | |
5800 | // Don't fix up hostnames with IP address. |
5801 | if (net_IsValidIPv4Addr(host) || net_IsValidIPv6Addr(host)) { |
5802 | return nullptr; |
5803 | } |
5804 | |
5805 | nsAutoCString userPass; |
5806 | rv = aUrl->GetUserPass(userPass); |
5807 | if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv )), 0))), "NS_FAILED(rv)", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 5807)) { |
5808 | return nullptr; |
5809 | } |
5810 | |
5811 | // Security - URLs with user / password info should NOT be modified. |
5812 | if (!userPass.IsEmpty()) { |
5813 | return nullptr; |
5814 | } |
5815 | |
5816 | nsCOMPtr<nsITransportSecurityInfo> tsi; |
5817 | rv = aChannel->GetSecurityInfo(getter_AddRefs(tsi)); |
5818 | if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv )), 0))), "NS_FAILED(rv)", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 5818)) { |
5819 | return nullptr; |
5820 | } |
5821 | |
5822 | if (NS_WARN_IF(!tsi)NS_warn_if_impl(!tsi, "!tsi", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 5822)) { |
5823 | return nullptr; |
5824 | } |
5825 | |
5826 | nsCOMPtr<nsIX509Cert> cert; |
5827 | rv = tsi->GetServerCert(getter_AddRefs(cert)); |
5828 | 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", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 5828)) { |
5829 | return nullptr; |
5830 | } |
5831 | |
5832 | nsTArray<uint8_t> certBytes; |
5833 | rv = cert->GetRawDER(certBytes); |
5834 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
5835 | return nullptr; |
5836 | } |
5837 | |
5838 | mozilla::pkix::Input serverCertInput; |
5839 | mozilla::pkix::Result result = |
5840 | serverCertInput.Init(certBytes.Elements(), certBytes.Length()); |
5841 | if (result != mozilla::pkix::Success) { |
5842 | return nullptr; |
5843 | } |
5844 | |
5845 | constexpr auto wwwPrefix = "www."_ns; |
5846 | nsAutoCString newHost; |
5847 | if (StringBeginsWith(host, wwwPrefix)) { |
5848 | // Try www.example.com -> example.com |
5849 | newHost.Assign(Substring(host, wwwPrefix.Length())); |
5850 | } else { |
5851 | // Try example.com -> www.example.com |
5852 | newHost.Assign(wwwPrefix); |
5853 | newHost.Append(host); |
5854 | } |
5855 | |
5856 | mozilla::pkix::Input newHostInput; |
5857 | result = newHostInput.Init( |
5858 | BitwiseCast<const uint8_t*, const char*>(newHost.BeginReading()), |
5859 | newHost.Length()); |
5860 | if (result != mozilla::pkix::Success) { |
5861 | return nullptr; |
5862 | } |
5863 | |
5864 | // Because certificate verification returned Result::ERROR_BAD_CERT_DOMAIN / |
5865 | // SSL_ERROR_BAD_CERT_DOMAIN, a chain was built and we know whether or not |
5866 | // the root was a built-in. |
5867 | bool rootIsBuiltIn; |
5868 | if (NS_FAILED(tsi->GetIsBuiltCertChainRootBuiltInRoot(&rootIsBuiltIn))((bool)(__builtin_expect(!!(NS_FAILED_impl(tsi->GetIsBuiltCertChainRootBuiltInRoot (&rootIsBuiltIn))), 0)))) { |
5869 | return nullptr; |
5870 | } |
5871 | mozilla::psm::SkipInvalidSANsForNonBuiltInRootsPolicy nameMatchingPolicy( |
5872 | rootIsBuiltIn); |
5873 | |
5874 | // Check if the certificate is valid for the new hostname. |
5875 | result = mozilla::pkix::CheckCertHostname(serverCertInput, newHostInput, |
5876 | nameMatchingPolicy); |
5877 | if (result != mozilla::pkix::Success) { |
5878 | return nullptr; |
5879 | } |
5880 | |
5881 | nsCOMPtr<nsIURI> newURI; |
5882 | Unused << NS_MutateURI(aUrl).SetHost(newHost).Finalize( |
5883 | getter_AddRefs(newURI)); |
5884 | |
5885 | return newURI.forget(); |
5886 | } |
5887 | |
5888 | /* static */ |
5889 | already_AddRefed<nsIURI> nsDocShell::AttemptURIFixup( |
5890 | nsIChannel* aChannel, nsresult aStatus, |
5891 | const mozilla::Maybe<nsCString>& aOriginalURIString, uint32_t aLoadType, |
5892 | bool aIsTopFrame, bool aAllowKeywordFixup, bool aUsePrivateBrowsing, |
5893 | bool aNotifyKeywordSearchLoading, nsIInputStream** aNewPostData, |
5894 | bool* outWasSchemelessInput) { |
5895 | if (aStatus != NS_ERROR_UNKNOWN_HOST && aStatus != NS_ERROR_NET_RESET && |
5896 | aStatus != NS_ERROR_CONNECTION_REFUSED && |
5897 | aStatus != |
5898 | mozilla::psm::GetXPCOMFromNSSError(SSL_ERROR_BAD_CERT_DOMAIN)) { |
5899 | return nullptr; |
5900 | } |
5901 | |
5902 | if (!(aLoadType == LOAD_NORMAL && aIsTopFrame) && !aAllowKeywordFixup) { |
5903 | return nullptr; |
5904 | } |
5905 | |
5906 | nsCOMPtr<nsIURI> url; |
5907 | nsresult rv = aChannel->GetURI(getter_AddRefs(url)); |
5908 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
5909 | return nullptr; |
5910 | } |
5911 | |
5912 | // |
5913 | // Try and make an alternative URI from the old one |
5914 | // |
5915 | nsCOMPtr<nsIURI> newURI; |
5916 | nsCOMPtr<nsIInputStream> newPostData; |
5917 | |
5918 | nsAutoCString oldSpec; |
5919 | url->GetSpec(oldSpec); |
5920 | |
5921 | // |
5922 | // First try keyword fixup |
5923 | // |
5924 | nsAutoString keywordProviderName, keywordAsSent; |
5925 | if (aStatus == NS_ERROR_UNKNOWN_HOST && aAllowKeywordFixup) { |
5926 | // we should only perform a keyword search under the following |
5927 | // conditions: |
5928 | // (0) Pref keyword.enabled is true |
5929 | // (1) the url scheme is http (or https) |
5930 | // (2) the url does not have a protocol scheme |
5931 | // If we don't enforce such a policy, then we end up doing |
5932 | // keyword searchs on urls we don't intend like imap, file, |
5933 | // mailbox, etc. This could lead to a security problem where we |
5934 | // send data to the keyword server that we shouldn't be. |
5935 | // Someone needs to clean up keywords in general so we can |
5936 | // determine on a per url basis if we want keywords |
5937 | // enabled...this is just a bandaid... |
5938 | nsAutoCString scheme; |
5939 | Unused << url->GetScheme(scheme); |
5940 | if (Preferences::GetBool("keyword.enabled", false) && |
5941 | StringBeginsWith(scheme, "http"_ns)) { |
5942 | bool attemptFixup = false; |
5943 | nsAutoCString host; |
5944 | Unused << url->GetHost(host); |
5945 | if (host.FindChar('.') == kNotFound) { |
5946 | attemptFixup = true; |
5947 | } else { |
5948 | // For domains with dots, we check the public suffix validity. |
5949 | nsCOMPtr<nsIEffectiveTLDService> tldService = |
5950 | do_GetService(NS_EFFECTIVETLDSERVICE_CONTRACTID"@mozilla.org/network/effective-tld-service;1"); |
5951 | if (tldService) { |
5952 | nsAutoCString suffix; |
5953 | attemptFixup = |
5954 | NS_SUCCEEDED(tldService->GetKnownPublicSuffix(url, suffix))((bool)(__builtin_expect(!!(!NS_FAILED_impl(tldService->GetKnownPublicSuffix (url, suffix))), 1))) && |
5955 | suffix.IsEmpty(); |
5956 | } |
5957 | } |
5958 | if (attemptFixup) { |
5959 | nsCOMPtr<nsIURIFixupInfo> info; |
5960 | // only send non-qualified hosts to the keyword server |
5961 | if (aOriginalURIString && !aOriginalURIString->IsEmpty()) { |
5962 | info = KeywordToURI(*aOriginalURIString, aUsePrivateBrowsing); |
5963 | } else { |
5964 | // |
5965 | // If this string was passed through nsStandardURL by |
5966 | // chance, then it may have been converted from UTF-8 to |
5967 | // Punycode, which would result in a completely bogus keyword |
5968 | // query. Here we try to recover the original Unicode |
5969 | // value, but this is not 100% correct since the value may |
5970 | // have been normalized per the IDN normalization rules. |
5971 | // |
5972 | // Since we don't have access to the exact original string |
5973 | // that was entered by the user, this will just have to do. |
5974 | nsAutoCString utf8Host; |
5975 | mozilla_net_recover_keyword_from_punycode(&host, &utf8Host); |
5976 | info = KeywordToURI(utf8Host, aUsePrivateBrowsing); |
5977 | } |
5978 | if (info) { |
5979 | info->GetPreferredURI(getter_AddRefs(newURI)); |
5980 | info->GetWasSchemelessInput(outWasSchemelessInput); |
5981 | if (newURI) { |
5982 | info->GetKeywordAsSent(keywordAsSent); |
5983 | info->GetKeywordProviderName(keywordProviderName); |
5984 | info->GetPostData(getter_AddRefs(newPostData)); |
5985 | } |
5986 | } |
5987 | } |
5988 | } |
5989 | } |
5990 | |
5991 | // |
5992 | // Now try change the address, e.g. turn http://foo into |
5993 | // http://www.foo.com, and if that doesn't work try https with |
5994 | // https://foo and https://www.foo.com. |
5995 | // |
5996 | if (aStatus == NS_ERROR_UNKNOWN_HOST || aStatus == NS_ERROR_NET_RESET) { |
5997 | // Skip fixup for anything except a normal document load |
5998 | // operation on the topframe. |
5999 | bool doCreateAlternate = aLoadType == LOAD_NORMAL && aIsTopFrame; |
6000 | |
6001 | if (doCreateAlternate) { |
6002 | nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo(); |
6003 | nsIPrincipal* principal = loadInfo->TriggeringPrincipal(); |
6004 | // Only do this if our channel was loaded directly by the user from the |
6005 | // URL bar or similar (system principal) and not redirected, because we |
6006 | // shouldn't be guessing things about links from other sites, or a |
6007 | // post-redirect URI. |
6008 | doCreateAlternate = principal && principal->IsSystemPrincipal() && |
6009 | loadInfo->RedirectChain().IsEmpty(); |
6010 | } |
6011 | // Test if keyword lookup produced a new URI or not |
6012 | if (doCreateAlternate && newURI) { |
6013 | bool sameURI = false; |
6014 | url->Equals(newURI, &sameURI); |
6015 | if (!sameURI) { |
6016 | // Keyword lookup made a new URI so no need to try |
6017 | // an alternate one. |
6018 | doCreateAlternate = false; |
6019 | } |
6020 | } |
6021 | if (doCreateAlternate) { |
6022 | newURI = nullptr; |
6023 | newPostData = nullptr; |
6024 | keywordProviderName.Truncate(); |
6025 | keywordAsSent.Truncate(); |
6026 | nsCOMPtr<nsIURIFixup> uriFixup = components::URIFixup::Service(); |
6027 | if (uriFixup) { |
6028 | nsCOMPtr<nsIURIFixupInfo> fixupInfo; |
6029 | uriFixup->GetFixupURIInfo(oldSpec, nsIURIFixup::FIXUP_FLAG_NONE, |
6030 | getter_AddRefs(fixupInfo)); |
6031 | if (fixupInfo) { |
6032 | fixupInfo->GetPreferredURI(getter_AddRefs(newURI)); |
6033 | } |
6034 | } |
6035 | } |
6036 | } else if (aStatus == NS_ERROR_CONNECTION_REFUSED && |
6037 | Preferences::GetBool("browser.fixup.fallback-to-https", false)) { |
6038 | // Try HTTPS, since http didn't work |
6039 | if (SchemeIsHTTP(url)) { |
6040 | int32_t port = 0; |
6041 | url->GetPort(&port); |
6042 | |
6043 | // Fall back to HTTPS only if port is default |
6044 | if (port == -1) { |
6045 | newURI = nullptr; |
6046 | newPostData = nullptr; |
6047 | Unused << NS_MutateURI(url) |
6048 | .SetScheme("https"_ns) |
6049 | .Finalize(getter_AddRefs(newURI)); |
6050 | } |
6051 | } |
6052 | } |
6053 | |
6054 | // If we have a SSL_ERROR_BAD_CERT_DOMAIN error, try adding or removing |
6055 | // "www." to/from the beginning of the domain name to see if we can avoid |
6056 | // showing the cert error page. For example, https://example.com -> |
6057 | // https://www.example.com or https://www.example.com -> https://example.com. |
6058 | if (aStatus == |
6059 | mozilla::psm::GetXPCOMFromNSSError(SSL_ERROR_BAD_CERT_DOMAIN)) { |
6060 | newPostData = nullptr; |
6061 | newURI = MaybeFixBadCertDomainErrorURI(aChannel, url); |
6062 | } |
6063 | |
6064 | // Did we make a new URI that is different to the old one? If so |
6065 | // load it. |
6066 | // |
6067 | if (newURI) { |
6068 | // Make sure the new URI is different from the old one, |
6069 | // otherwise there's little point trying to load it again. |
6070 | bool sameURI = false; |
6071 | url->Equals(newURI, &sameURI); |
6072 | if (!sameURI) { |
6073 | if (aNewPostData) { |
6074 | newPostData.forget(aNewPostData); |
6075 | } |
6076 | if (aNotifyKeywordSearchLoading) { |
6077 | // This notification is meant for Firefox Health Report so it |
6078 | // can increment counts from the search engine |
6079 | MaybeNotifyKeywordSearchLoading(keywordProviderName, keywordAsSent); |
6080 | } |
6081 | return newURI.forget(); |
6082 | } |
6083 | } |
6084 | |
6085 | return nullptr; |
6086 | } |
6087 | |
6088 | nsresult nsDocShell::FilterStatusForErrorPage( |
6089 | nsresult aStatus, nsIChannel* aChannel, uint32_t aLoadType, |
6090 | bool aIsTopFrame, bool aUseErrorPages, |
6091 | bool* aSkippedUnknownProtocolNavigation) { |
6092 | // Errors to be shown only on top-level frames |
6093 | if ((aStatus == NS_ERROR_UNKNOWN_HOST || |
6094 | aStatus == NS_ERROR_CONNECTION_REFUSED || |
6095 | aStatus == NS_ERROR_UNKNOWN_PROXY_HOST || |
6096 | aStatus == NS_ERROR_PROXY_CONNECTION_REFUSED || |
6097 | aStatus == NS_ERROR_PROXY_FORBIDDEN || |
6098 | aStatus == NS_ERROR_PROXY_NOT_IMPLEMENTED || |
6099 | aStatus == NS_ERROR_PROXY_AUTHENTICATION_FAILED || |
6100 | aStatus == NS_ERROR_PROXY_TOO_MANY_REQUESTS || |
6101 | aStatus == NS_ERROR_MALFORMED_URI || |
6102 | aStatus == NS_ERROR_BLOCKED_BY_POLICY || |
6103 | aStatus == NS_ERROR_DOM_COOP_FAILED || |
6104 | aStatus == NS_ERROR_DOM_COEP_FAILED) && |
6105 | (aIsTopFrame || aUseErrorPages)) { |
6106 | return aStatus; |
6107 | } |
6108 | |
6109 | if (aStatus == NS_ERROR_NET_TIMEOUT || |
6110 | aStatus == NS_ERROR_NET_TIMEOUT_EXTERNAL || |
6111 | aStatus == NS_ERROR_NET_ERROR_RESPONSE || |
6112 | aStatus == NS_ERROR_PROXY_GATEWAY_TIMEOUT || |
6113 | aStatus == NS_ERROR_REDIRECT_LOOP || |
6114 | aStatus == NS_ERROR_UNKNOWN_SOCKET_TYPE || |
6115 | aStatus == NS_ERROR_NET_INTERRUPT || aStatus == NS_ERROR_NET_RESET || |
6116 | aStatus == NS_ERROR_PROXY_BAD_GATEWAY || aStatus == NS_ERROR_OFFLINE || |
6117 | aStatus == NS_ERROR_MALWARE_URI || aStatus == NS_ERROR_PHISHING_URI || |
6118 | aStatus == NS_ERROR_UNWANTED_URI || aStatus == NS_ERROR_HARMFUL_URI || |
6119 | aStatus == NS_ERROR_UNSAFE_CONTENT_TYPE || |
6120 | aStatus == NS_ERROR_INTERCEPTION_FAILED || |
6121 | aStatus == NS_ERROR_NET_INADEQUATE_SECURITY || |
6122 | aStatus == NS_ERROR_NET_HTTP2_SENT_GOAWAY || |
6123 | aStatus == NS_ERROR_NET_HTTP3_PROTOCOL_ERROR || |
6124 | aStatus == NS_ERROR_DOM_BAD_URI || aStatus == NS_ERROR_FILE_NOT_FOUND || |
6125 | aStatus == NS_ERROR_FILE_ACCESS_DENIED || |
6126 | aStatus == NS_ERROR_CORRUPTED_CONTENT || |
6127 | aStatus == NS_ERROR_INVALID_CONTENT_ENCODING || |
6128 | NS_ERROR_GET_MODULE(aStatus) == NS_ERROR_MODULE_SECURITY21) { |
6129 | // Errors to be shown for any frame |
6130 | return aStatus; |
6131 | } |
6132 | |
6133 | if (aStatus == NS_ERROR_UNKNOWN_PROTOCOL) { |
6134 | // For unknown protocols we only display an error if the load is triggered |
6135 | // by the browser itself. Showing the error for page-triggered navigations |
6136 | // causes annoying behavior for users, see bug 1528305. |
6137 | nsCOMPtr<nsILoadInfo> info = aChannel->LoadInfo(); |
6138 | if (!info->TriggeringPrincipal()->IsSystemPrincipal()) { |
6139 | if (aSkippedUnknownProtocolNavigation) { |
6140 | *aSkippedUnknownProtocolNavigation = true; |
6141 | } |
6142 | return NS_OK; |
6143 | } |
6144 | return aStatus; |
6145 | } |
6146 | |
6147 | if (aStatus == NS_ERROR_DOCUMENT_NOT_CACHED) { |
6148 | // Non-caching channels will simply return NS_ERROR_OFFLINE. |
6149 | // Caching channels would have to look at their flags to work |
6150 | // out which error to return. Or we can fix up the error here. |
6151 | if (!(aLoadType & LOAD_CMD_HISTORY)) { |
6152 | return NS_ERROR_OFFLINE; |
6153 | } |
6154 | return aStatus; |
6155 | } |
6156 | |
6157 | return NS_OK; |
6158 | } |
6159 | |
6160 | nsresult nsDocShell::EndPageLoad(nsIWebProgress* aProgress, |
6161 | nsIChannel* aChannel, nsresult aStatus) { |
6162 | 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) |
6163 | ("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) |
6164 | 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); |
6165 | if (!aChannel) { |
6166 | return NS_ERROR_NULL_POINTER; |
6167 | } |
6168 | |
6169 | // Make sure to discard the initial client if we never created the initial |
6170 | // about:blank document. Do this before possibly returning from the method |
6171 | // due to an error. |
6172 | mInitialClientSource.reset(); |
6173 | |
6174 | nsCOMPtr<nsIConsoleReportCollector> reporter = do_QueryInterface(aChannel); |
6175 | if (reporter) { |
6176 | nsCOMPtr<nsILoadGroup> loadGroup; |
6177 | aChannel->GetLoadGroup(getter_AddRefs(loadGroup)); |
6178 | if (loadGroup) { |
6179 | reporter->FlushConsoleReports(loadGroup); |
6180 | } else { |
6181 | reporter->FlushConsoleReports(GetDocument()); |
6182 | } |
6183 | } |
6184 | |
6185 | nsCOMPtr<nsIURI> url; |
6186 | nsresult rv = aChannel->GetURI(getter_AddRefs(url)); |
6187 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
6188 | return rv; |
6189 | } |
6190 | |
6191 | nsCOMPtr<nsITimedChannel> timingChannel = do_QueryInterface(aChannel); |
6192 | if (timingChannel) { |
6193 | TimeStamp channelCreationTime; |
6194 | rv = timingChannel->GetChannelCreation(&channelCreationTime); |
6195 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && !channelCreationTime.IsNull()) { |
6196 | glean::performance_page::total_content_page_load.AccumulateRawDuration( |
6197 | TimeStamp::Now() - channelCreationTime); |
6198 | } |
6199 | } |
6200 | |
6201 | // Timing is picked up by the window, we don't need it anymore |
6202 | mTiming = nullptr; |
6203 | |
6204 | // clean up reload state for meta charset |
6205 | if (eCharsetReloadRequested == mCharsetReloadState) { |
6206 | mCharsetReloadState = eCharsetReloadStopOrigional; |
6207 | } else { |
6208 | mCharsetReloadState = eCharsetReloadInit; |
6209 | } |
6210 | |
6211 | // Save a pointer to the currently-loading history entry. |
6212 | // nsDocShell::EndPageLoad will clear mLSHE, but we may need this history |
6213 | // entry further down in this method. |
6214 | nsCOMPtr<nsISHEntry> loadingSHE = mLSHE; |
6215 | mozilla::Unused << loadingSHE; // XXX: Not sure if we need this anymore |
6216 | |
6217 | // |
6218 | // one of many safeguards that prevent death and destruction if |
6219 | // someone is so very very rude as to bring this window down |
6220 | // during this load handler. |
6221 | // |
6222 | nsCOMPtr<nsIDocShell> kungFuDeathGrip(this); |
6223 | |
6224 | // Notify the DocumentViewer that the Document has finished loading. This |
6225 | // will cause any OnLoad(...) and PopState(...) handlers to fire. |
6226 | if (!mEODForCurrentDocument && mDocumentViewer) { |
6227 | mIsExecutingOnLoadHandler = true; |
6228 | nsCOMPtr<nsIDocumentViewer> viewer = mDocumentViewer; |
6229 | viewer->LoadComplete(aStatus); |
6230 | mIsExecutingOnLoadHandler = false; |
6231 | |
6232 | mEODForCurrentDocument = true; |
6233 | } |
6234 | /* Check if the httpChannel has any cache-control related response headers, |
6235 | * like no-store, no-cache. If so, update SHEntry so that |
6236 | * when a user goes back/forward to this page, we appropriately do |
6237 | * form value restoration or load from server. |
6238 | */ |
6239 | nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(aChannel)); |
6240 | if (!httpChannel) { |
6241 | // HttpChannel could be hiding underneath a Multipart channel. |
6242 | GetHttpChannel(aChannel, getter_AddRefs(httpChannel)); |
6243 | } |
6244 | |
6245 | if (httpChannel) { |
6246 | // figure out if SH should be saving layout state. |
6247 | bool discardLayoutState = ShouldDiscardLayoutState(httpChannel); |
6248 | if (mLSHE && discardLayoutState && (mLoadType & LOAD_CMD_NORMAL) && |
6249 | (mLoadType != LOAD_BYPASS_HISTORY) && (mLoadType != LOAD_ERROR_PAGE)) { |
6250 | mLSHE->SetSaveLayoutStateFlag(false); |
6251 | } |
6252 | } |
6253 | |
6254 | // Clear mLSHE after calling the onLoadHandlers. This way, if the |
6255 | // onLoadHandler tries to load something different in |
6256 | // itself or one of its children, we can deal with it appropriately. |
6257 | if (mLSHE) { |
6258 | mLSHE->SetLoadType(LOAD_HISTORY); |
6259 | |
6260 | // Clear the mLSHE reference to indicate document loading is done one |
6261 | // way or another. |
6262 | SetHistoryEntryAndUpdateBC(Some(nullptr), Nothing()); |
6263 | } |
6264 | mActiveEntryIsLoadingFromSessionHistory = false; |
6265 | |
6266 | // if there's a refresh header in the channel, this method |
6267 | // will set it up for us. |
6268 | if (mBrowsingContext->IsActive() || !mDisableMetaRefreshWhenInactive) |
6269 | RefreshURIFromQueue(); |
6270 | |
6271 | // Test whether this is the top frame or a subframe |
6272 | bool isTopFrame = mBrowsingContext->IsTop(); |
6273 | |
6274 | bool hadErrorStatus = false; |
6275 | // If status code indicates an error it means that DocumentChannel already |
6276 | // tried to fixup the uri and failed. Throw an error dialog box here. |
6277 | if (NS_FAILED(aStatus)((bool)(__builtin_expect(!!(NS_FAILED_impl(aStatus)), 0)))) { |
6278 | // If we got CONTENT_BLOCKED from EndPageLoad, then we need to fire |
6279 | // the error event to our embedder, since tests are relying on this. |
6280 | // The error event is usually fired by the caller of InternalLoad, but |
6281 | // this particular error can happen asynchronously. |
6282 | // Bug 1629201 is filed for having much clearer decision making around |
6283 | // which cases need error events. |
6284 | bool fireFrameErrorEvent = (aStatus == NS_ERROR_CONTENT_BLOCKED_SHOW_ALT || |
6285 | aStatus == NS_ERROR_CONTENT_BLOCKED); |
6286 | UnblockEmbedderLoadEventForFailure(fireFrameErrorEvent); |
6287 | |
6288 | bool skippedUnknownProtocolNavigation = false; |
6289 | aStatus = FilterStatusForErrorPage(aStatus, aChannel, mLoadType, isTopFrame, |
6290 | mBrowsingContext->GetUseErrorPages(), |
6291 | &skippedUnknownProtocolNavigation); |
6292 | hadErrorStatus = true; |
6293 | if (NS_FAILED(aStatus)((bool)(__builtin_expect(!!(NS_FAILED_impl(aStatus)), 0)))) { |
6294 | if (!mIsBeingDestroyed) { |
6295 | DisplayLoadError(aStatus, url, nullptr, aChannel); |
6296 | } |
6297 | } else if (skippedUnknownProtocolNavigation) { |
6298 | nsAutoCString sanitized; |
6299 | nsTArray<nsString> params; |
6300 | if (NS_SUCCEEDED(NS_GetSanitizedURIStringFromURI(url, sanitized))((bool)(__builtin_expect(!!(!NS_FAILED_impl(NS_GetSanitizedURIStringFromURI (url, sanitized))), 1)))) { |
6301 | params.AppendElement(NS_ConvertUTF8toUTF16(sanitized)); |
6302 | } else { |
6303 | params.AppendElement(u"(unknown uri)"_ns); |
6304 | } |
6305 | nsContentUtils::ReportToConsole( |
6306 | nsIScriptError::warningFlag, "DOM"_ns, GetExtantDocument(), |
6307 | nsContentUtils::eDOM_PROPERTIES, "UnknownProtocolNavigationPrevented", |
6308 | params); |
6309 | } |
6310 | } else { |
6311 | // If we have a host |
6312 | nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo(); |
6313 | PredictorLearnRedirect(url, aChannel, loadInfo->GetOriginAttributes()); |
6314 | } |
6315 | |
6316 | if (hadErrorStatus) { |
6317 | // Don't send session store updates if the reason EndPageLoad was called is |
6318 | // because we are process switching. Sometimes the update takes too long and |
6319 | // incorrectly overrides session store data from the following load. |
6320 | return NS_OK; |
6321 | } |
6322 | if (SessionStorePlatformCollection()) { |
6323 | if (WindowContext* windowContext = |
6324 | mBrowsingContext->GetCurrentWindowContext()) { |
6325 | using Change = SessionStoreChangeListener::Change; |
6326 | |
6327 | // We've finished loading the page and now we want to collect all the |
6328 | // session store state that the page is initialized with. |
6329 | SessionStoreChangeListener::CollectSessionStoreData( |
6330 | windowContext, |
6331 | EnumSet<Change>(Change::Input, Change::Scroll, Change::SessionHistory, |
6332 | Change::WireFrame)); |
6333 | } |
6334 | } |
6335 | |
6336 | return NS_OK; |
6337 | } |
6338 | |
6339 | //***************************************************************************** |
6340 | // nsDocShell: Content Viewer Management |
6341 | //***************************************************************************** |
6342 | |
6343 | nsresult nsDocShell::EnsureDocumentViewer() { |
6344 | if (mDocumentViewer) { |
6345 | return NS_OK; |
6346 | } |
6347 | if (mIsBeingDestroyed) { |
6348 | return NS_ERROR_FAILURE; |
6349 | } |
6350 | |
6351 | nsCOMPtr<nsIContentSecurityPolicy> cspToInheritForAboutBlank; |
6352 | nsCOMPtr<nsIURI> baseURI; |
6353 | nsIPrincipal* principal = GetInheritedPrincipal(false); |
6354 | nsIPrincipal* partitionedPrincipal = GetInheritedPrincipal(false, true); |
6355 | |
6356 | nsCOMPtr<nsIDocShellTreeItem> parentItem; |
6357 | GetInProcessSameTypeParent(getter_AddRefs(parentItem)); |
6358 | if (parentItem) { |
6359 | if (nsCOMPtr<nsPIDOMWindowOuter> domWin = GetWindow()) { |
6360 | nsCOMPtr<Element> parentElement = domWin->GetFrameElementInternal(); |
6361 | if (parentElement) { |
6362 | baseURI = parentElement->GetBaseURI(); |
6363 | cspToInheritForAboutBlank = parentElement->GetCsp(); |
6364 | } |
6365 | } |
6366 | } |
6367 | |
6368 | nsresult rv = CreateAboutBlankDocumentViewer( |
6369 | principal, partitionedPrincipal, cspToInheritForAboutBlank, baseURI, |
6370 | /* aIsInitialDocument */ true); |
6371 | |
6372 | NS_ENSURE_STATE(mDocumentViewer)do { if ((__builtin_expect(!!(!(mDocumentViewer)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "mDocumentViewer" ") failed" , nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 6372); return NS_ERROR_UNEXPECTED; } } while (false); |
6373 | |
6374 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) { |
6375 | RefPtr<Document> doc(GetDocument()); |
6376 | 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!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 6378); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc" ") (" "Should have doc if CreateAboutBlankDocumentViewer " "succeeded!" ")"); do { *((volatile int*)__null) = 6378; __attribute__ ((nomerge)) ::abort(); } while (false); } } while (false) |
6377 | "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!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 6378); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc" ") (" "Should have doc if CreateAboutBlankDocumentViewer " "succeeded!" ")"); do { *((volatile int*)__null) = 6378; __attribute__ ((nomerge)) ::abort(); } while (false); } } while (false) |
6378 | "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!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 6378); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc" ") (" "Should have doc if CreateAboutBlankDocumentViewer " "succeeded!" ")"); do { *((volatile int*)__null) = 6378; __attribute__ ((nomerge)) ::abort(); } while (false); } } while (false); |
6379 | 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 6379); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc->IsInitialDocument()" ") (" "Document should be initial document" ")"); do { *((volatile int*)__null) = 6379; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
6380 | |
6381 | // Documents created using EnsureDocumentViewer may be transient |
6382 | // placeholders created by framescripts before content has a |
6383 | // chance to load. In some cases, window.open(..., "noopener") |
6384 | // will create such a document and then synchronously tear it |
6385 | // down, firing a "pagehide" event. Doing so violates our |
6386 | // assertions about DocGroups. It's easier to silence the |
6387 | // assertion here than to avoid creating the extra document. |
6388 | doc->IgnoreDocGroupMismatches(); |
6389 | } |
6390 | |
6391 | return rv; |
6392 | } |
6393 | |
6394 | nsresult nsDocShell::CreateAboutBlankDocumentViewer( |
6395 | nsIPrincipal* aPrincipal, nsIPrincipal* aPartitionedPrincipal, |
6396 | nsIContentSecurityPolicy* aCSP, nsIURI* aBaseURI, bool aIsInitialDocument, |
6397 | const Maybe<nsILoadInfo::CrossOriginEmbedderPolicy>& aCOEP, |
6398 | bool aTryToSaveOldPresentation, bool aCheckPermitUnload, |
6399 | WindowGlobalChild* aActor) { |
6400 | RefPtr<Document> blankDoc; |
6401 | nsCOMPtr<nsIDocumentViewer> viewer; |
6402 | nsresult rv = NS_ERROR_FAILURE; |
6403 | |
6404 | 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 ) |
6405 | MarkerStack::Capture())do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl ("CreateAboutBlankDocumentViewer", ::geckoprofiler::category:: DOM, MarkerStack::Capture()); } } while (false); } while (false ); |
6406 | |
6407 | 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" , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 6407); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aActor->DocumentPrincipal() == aPrincipal" ")"); do { *((volatile int*)__null) = 6407; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); |
6408 | |
6409 | /* mCreatingDocument should never be true at this point. However, it's |
6410 | a theoretical possibility. We want to know about it and make it stop, |
6411 | and this sounds like a job for an assertion. */ |
6412 | NS_ASSERTION(!mCreatingDocument,do { if (!(!mCreatingDocument)) { NS_DebugBreak(NS_DEBUG_ASSERTION , "infinite(?) loop creating document averted", "!mCreatingDocument" , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 6413); MOZ_PretendNoReturn(); } } while (0) |
6413 | "infinite(?) loop creating document averted")do { if (!(!mCreatingDocument)) { NS_DebugBreak(NS_DEBUG_ASSERTION , "infinite(?) loop creating document averted", "!mCreatingDocument" , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 6413); MOZ_PretendNoReturn(); } } while (0); |
6414 | if (mCreatingDocument) { |
6415 | return NS_ERROR_FAILURE; |
6416 | } |
6417 | |
6418 | if (!mBrowsingContext->AncestorsAreCurrent() || |
6419 | mBrowsingContext->IsInBFCache()) { |
6420 | mBrowsingContext->RemoveRootFromBFCacheSync(); |
6421 | return NS_ERROR_NOT_AVAILABLE; |
6422 | } |
6423 | |
6424 | // mDocumentViewer->PermitUnload may release |this| docshell. |
6425 | nsCOMPtr<nsIDocShell> kungFuDeathGrip(this); |
6426 | |
6427 | AutoRestore<bool> creatingDocument(mCreatingDocument); |
6428 | mCreatingDocument = true; |
6429 | |
6430 | if (aPrincipal && !aPrincipal->IsSystemPrincipal() && |
6431 | mItemType != typeChrome) { |
6432 | 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()" , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 6433); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPrincipal->OriginAttributesRef() == mBrowsingContext->OriginAttributesRef()" ")"); do { *((volatile int*)__null) = 6433; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
6433 | 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()" , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 6433); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPrincipal->OriginAttributesRef() == mBrowsingContext->OriginAttributesRef()" ")"); do { *((volatile int*)__null) = 6433; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
6434 | } |
6435 | |
6436 | // Make sure timing is created. But first record whether we had it |
6437 | // already, so we don't clobber the timing for an in-progress load. |
6438 | bool hadTiming = mTiming; |
6439 | bool toBeReset = MaybeInitTiming(); |
6440 | if (mDocumentViewer) { |
6441 | if (aCheckPermitUnload) { |
6442 | // We've got a content viewer already. Make sure the user |
6443 | // permits us to discard the current document and replace it |
6444 | // with about:blank. And also ensure we fire the unload events |
6445 | // in the current document. |
6446 | |
6447 | // Unload gets fired first for |
6448 | // document loaded from the session history. |
6449 | mTiming->NotifyBeforeUnload(); |
6450 | |
6451 | bool okToUnload; |
6452 | rv = mDocumentViewer->PermitUnload(&okToUnload); |
6453 | |
6454 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && !okToUnload) { |
6455 | // The user chose not to unload the page, interrupt the load. |
6456 | MaybeResetInitTiming(toBeReset); |
6457 | return NS_ERROR_FAILURE; |
6458 | } |
6459 | if (mTiming) { |
6460 | mTiming->NotifyUnloadAccepted(mCurrentURI); |
6461 | } |
6462 | } |
6463 | |
6464 | mSavingOldViewer = |
6465 | aTryToSaveOldPresentation && |
6466 | CanSavePresentation(LOAD_NORMAL, nullptr, nullptr, |
6467 | /* aReportBFCacheComboTelemetry */ true); |
6468 | |
6469 | // Make sure to blow away our mLoadingURI just in case. No loads |
6470 | // from inside this pagehide. |
6471 | mLoadingURI = nullptr; |
6472 | |
6473 | // Stop any in-progress loading, so that we don't accidentally trigger any |
6474 | // PageShow notifications from Embed() interrupting our loading below. |
6475 | Stop(); |
6476 | |
6477 | // Notify the current document that it is about to be unloaded!! |
6478 | // |
6479 | // It is important to fire the unload() notification *before* any state |
6480 | // is changed within the DocShell - otherwise, javascript will get the |
6481 | // wrong information :-( |
6482 | // |
6483 | (void)FirePageHideNotification(!mSavingOldViewer); |
6484 | // pagehide notification might destroy this docshell. |
6485 | if (mIsBeingDestroyed) { |
6486 | return NS_ERROR_DOCSHELL_DYING; |
6487 | } |
6488 | } |
6489 | |
6490 | // Now make sure we don't think we're in the middle of firing unload after |
6491 | // this point. This will make us fire unload when the about:blank document |
6492 | // unloads... but that's ok, more or less. Would be nice if it fired load |
6493 | // too, of course. |
6494 | mFiredUnloadEvent = false; |
6495 | |
6496 | nsCOMPtr<nsIDocumentLoaderFactory> docFactory = |
6497 | nsContentUtils::FindInternalDocumentViewer("text/html"_ns); |
6498 | |
6499 | if (docFactory) { |
6500 | nsCOMPtr<nsIPrincipal> principal, partitionedPrincipal; |
6501 | const uint32_t sandboxFlags = |
6502 | mBrowsingContext->GetHasLoadedNonInitialDocument() |
6503 | ? mBrowsingContext->GetSandboxFlags() |
6504 | : mBrowsingContext->GetInitialSandboxFlags(); |
6505 | // If we're sandboxed, then create a new null principal. We skip |
6506 | // this if we're being created from WindowGlobalChild, since in |
6507 | // that case we already have a null principal if required. |
6508 | // We can't compare againt the BrowsingContext sandbox flag, since |
6509 | // the value was taken when the load initiated and may have since |
6510 | // changed. |
6511 | if ((sandboxFlags & SANDBOXED_ORIGIN) && !aActor) { |
6512 | if (aPrincipal) { |
6513 | principal = NullPrincipal::CreateWithInheritedAttributes(aPrincipal); |
6514 | } else { |
6515 | principal = NullPrincipal::Create(GetOriginAttributes()); |
6516 | } |
6517 | partitionedPrincipal = principal; |
6518 | } else { |
6519 | principal = aPrincipal; |
6520 | partitionedPrincipal = aPartitionedPrincipal; |
6521 | } |
6522 | |
6523 | // We cannot get the foreign partitioned prinicpal for the initial |
6524 | // about:blank page. So, we change to check if we need to use the |
6525 | // partitioned principal for the service worker here. |
6526 | MaybeCreateInitialClientSource( |
6527 | StoragePrincipalHelper::ShouldUsePartitionPrincipalForServiceWorker( |
6528 | this) |
6529 | ? partitionedPrincipal |
6530 | : principal); |
6531 | |
6532 | // generate (about:blank) document to load |
6533 | blankDoc = nsContentDLF::CreateBlankDocument(mLoadGroup, principal, |
6534 | partitionedPrincipal, this); |
6535 | if (blankDoc) { |
6536 | // Hack: manually set the CSP for the new document |
6537 | // Please create an actual copy of the CSP (do not share the same |
6538 | // reference) otherwise appending a new policy within the new |
6539 | // document will be incorrectly propagated to the opening doc. |
6540 | if (aCSP) { |
6541 | RefPtr<nsCSPContext> cspToInherit = new nsCSPContext(); |
6542 | cspToInherit->InitFromOther(static_cast<nsCSPContext*>(aCSP)); |
6543 | blankDoc->SetCsp(cspToInherit); |
6544 | } |
6545 | |
6546 | blankDoc->SetIsInitialDocument(aIsInitialDocument); |
6547 | |
6548 | blankDoc->SetEmbedderPolicy(aCOEP); |
6549 | |
6550 | // Hack: set the base URI manually, since this document never |
6551 | // got Reset() with a channel. |
6552 | blankDoc->SetBaseURI(aBaseURI); |
6553 | |
6554 | // Copy our sandbox flags to the document. These are immutable |
6555 | // after being set here. |
6556 | blankDoc->SetSandboxFlags(sandboxFlags); |
6557 | |
6558 | // create a content viewer for us and the new document |
6559 | docFactory->CreateInstanceForDocument( |
6560 | NS_ISUPPORTS_CAST(nsIDocShell*, this)static_cast<nsISupports*>(static_cast<nsIDocShell*> (this)), blankDoc, "view", |
6561 | getter_AddRefs(viewer)); |
6562 | |
6563 | // hook 'em up |
6564 | if (viewer) { |
6565 | viewer->SetContainer(this); |
6566 | rv = Embed(viewer, aActor, true, false, nullptr, mCurrentURI); |
6567 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 6567); return rv; } } while (false); |
6568 | |
6569 | SetCurrentURI(blankDoc->GetDocumentURI(), nullptr, |
6570 | /* aFireLocationChange */ true, |
6571 | /* aIsInitialAboutBlank */ true, |
6572 | /* aLocationFlags */ 0); |
6573 | rv = mIsBeingDestroyed ? NS_ERROR_NOT_AVAILABLE : NS_OK; |
6574 | } |
6575 | |
6576 | if (Element* embedderElement = blankDoc->GetEmbedderElement()) { |
6577 | blankDoc->InitFeaturePolicy(AsVariant(embedderElement)); |
6578 | } else { |
6579 | blankDoc->InitFeaturePolicy(AsVariant(Nothing{})); |
6580 | } |
6581 | } |
6582 | } |
6583 | |
6584 | // The transient about:blank viewer doesn't have a session history entry. |
6585 | SetHistoryEntryAndUpdateBC(Nothing(), Some(nullptr)); |
6586 | |
6587 | // Clear out our mTiming like we would in EndPageLoad, if we didn't |
6588 | // have one before entering this function. |
6589 | if (!hadTiming) { |
6590 | mTiming = nullptr; |
6591 | mBlankTiming = true; |
6592 | } |
6593 | |
6594 | return rv; |
6595 | } |
6596 | |
6597 | NS_IMETHODIMPnsresult |
6598 | nsDocShell::CreateAboutBlankDocumentViewer(nsIPrincipal* aPrincipal, |
6599 | nsIPrincipal* aPartitionedPrincipal, |
6600 | nsIContentSecurityPolicy* aCSP) { |
6601 | return CreateAboutBlankDocumentViewer(aPrincipal, aPartitionedPrincipal, aCSP, |
6602 | nullptr, |
6603 | /* aIsInitialDocument */ false); |
6604 | } |
6605 | |
6606 | nsresult nsDocShell::CreateDocumentViewerForActor( |
6607 | WindowGlobalChild* aWindowActor) { |
6608 | 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", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 6608); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aWindowActor" ")"); do { *((volatile int*)__null) = 6608; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
6609 | |
6610 | // FIXME: WindowGlobalChild should provide the PartitionedPrincipal. |
6611 | // FIXME: We may want to support non-initial documents here. |
6612 | nsresult rv = CreateAboutBlankDocumentViewer( |
6613 | aWindowActor->DocumentPrincipal(), aWindowActor->DocumentPrincipal(), |
6614 | /* aCsp */ nullptr, |
6615 | /* aBaseURI */ nullptr, |
6616 | /* aIsInitialDocument */ true, |
6617 | /* aCOEP */ Nothing(), |
6618 | /* aTryToSaveOldPresentation */ true, |
6619 | /* aCheckPermitUnload */ true, aWindowActor); |
6620 | #ifdef DEBUG1 |
6621 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) { |
6622 | RefPtr<Document> doc(GetDocument()); |
6623 | 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 6625); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc" ") (" "Should have a document if CreateAboutBlankDocumentViewer succeeded" ")"); do { *((volatile int*)__null) = 6625; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
6624 | 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 6625); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc" ") (" "Should have a document if CreateAboutBlankDocumentViewer succeeded" ")"); do { *((volatile int*)__null) = 6625; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
6625 | "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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 6625); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc" ") (" "Should have a document if CreateAboutBlankDocumentViewer succeeded" ")"); do { *((volatile int*)__null) = 6625; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
6626 | 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 6627); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc->GetOwnerGlobal() == aWindowActor->GetWindowGlobal()" ") (" "New document should be in the same global as our actor" ")"); do { *((volatile int*)__null) = 6627; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
6627 | "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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 6627); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc->GetOwnerGlobal() == aWindowActor->GetWindowGlobal()" ") (" "New document should be in the same global as our actor" ")"); do { *((volatile int*)__null) = 6627; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
6628 | 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 6629); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc->IsInitialDocument()" ") (" "New document should be an initial document" ")"); do { *((volatile int*)__null) = 6629; __attribute__((nomerge)) :: abort(); } while (false); } } while (false) |
6629 | "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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 6629); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc->IsInitialDocument()" ") (" "New document should be an initial document" ")"); do { *((volatile int*)__null) = 6629; __attribute__((nomerge)) :: abort(); } while (false); } } while (false); |
6630 | } |
6631 | #endif |
6632 | |
6633 | return rv; |
6634 | } |
6635 | |
6636 | bool nsDocShell::CanSavePresentation(uint32_t aLoadType, |
6637 | nsIRequest* aNewRequest, |
6638 | Document* aNewDocument, |
6639 | bool aReportBFCacheComboTelemetry) { |
6640 | if (!mOSHE) { |
6641 | return false; // no entry to save into |
6642 | } |
6643 | |
6644 | 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 6645); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()" ") (" "mOSHE cannot be non-null with SHIP" ")"); do { *((volatile int*)__null) = 6645; __attribute__((nomerge)) ::abort(); } while (false); } } while (false) |
6645 | "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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 6645); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()" ") (" "mOSHE cannot be non-null with SHIP" ")"); do { *((volatile int*)__null) = 6645; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
6646 | nsCOMPtr<nsIDocumentViewer> viewer = mOSHE->GetDocumentViewer(); |
6647 | if (viewer) { |
6648 | NS_WARNING("mOSHE already has a content viewer!")NS_DebugBreak(NS_DEBUG_WARNING, "mOSHE already has a content viewer!" , nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 6648); |
6649 | return false; |
6650 | } |
6651 | |
6652 | // Only save presentation for "normal" loads and link loads. Anything else |
6653 | // probably wants to refetch the page, so caching the old presentation |
6654 | // would be incorrect. |
6655 | if (aLoadType != LOAD_NORMAL && aLoadType != LOAD_HISTORY && |
6656 | aLoadType != LOAD_LINK && aLoadType != LOAD_STOP_CONTENT && |
6657 | aLoadType != LOAD_STOP_CONTENT_AND_REPLACE && |
6658 | aLoadType != LOAD_ERROR_PAGE) { |
6659 | return false; |
6660 | } |
6661 | |
6662 | // If the session history entry has the saveLayoutState flag set to false, |
6663 | // then we should not cache the presentation. |
6664 | if (!mOSHE->GetSaveLayoutStateFlag()) { |
6665 | return false; |
6666 | } |
6667 | |
6668 | // If the document is not done loading, don't cache it. |
6669 | if (!mScriptGlobal || mScriptGlobal->IsLoading()) { |
6670 | 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) |
6671 | ("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); |
6672 | return false; |
6673 | } |
6674 | |
6675 | if (mScriptGlobal->WouldReuseInnerWindow(aNewDocument)) { |
6676 | return false; |
6677 | } |
6678 | |
6679 | // Avoid doing the work of saving the presentation state in the case where |
6680 | // the content viewer cache is disabled. |
6681 | if (nsSHistory::GetMaxTotalViewers() == 0) { |
6682 | return false; |
6683 | } |
6684 | |
6685 | // Don't cache the content viewer if we're in a subframe. |
6686 | if (mBrowsingContext->GetParent()) { |
6687 | return false; // this is a subframe load |
6688 | } |
6689 | |
6690 | // If the document does not want its presentation cached, then don't. |
6691 | RefPtr<Document> doc = mScriptGlobal->GetExtantDoc(); |
6692 | |
6693 | uint32_t bfCacheCombo = 0; |
6694 | bool canSavePresentation = |
6695 | doc->CanSavePresentation(aNewRequest, bfCacheCombo, true); |
6696 | 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", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 6696); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bfCacheCombo == 0" ")"); do { *((volatile int*)__null) = 6696; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); |
6697 | if (canSavePresentation && doc->IsTopLevelContentDocument()) { |
6698 | auto* browsingContextGroup = mBrowsingContext->Group(); |
6699 | nsTArray<RefPtr<BrowsingContext>>& topLevelContext = |
6700 | browsingContextGroup->Toplevels(); |
6701 | |
6702 | for (const auto& browsingContext : topLevelContext) { |
6703 | if (browsingContext != mBrowsingContext) { |
6704 | if (StaticPrefs::docshell_shistory_bfcache_require_no_opener()) { |
6705 | canSavePresentation = false; |
6706 | } |
6707 | bfCacheCombo |= BFCacheStatus::NOT_ONLY_TOPLEVEL_IN_BCG; |
6708 | break; |
6709 | } |
6710 | } |
6711 | } |
6712 | |
6713 | if (aReportBFCacheComboTelemetry) { |
6714 | ReportBFCacheComboTelemetry(bfCacheCombo); |
6715 | } |
6716 | return doc && canSavePresentation; |
6717 | } |
6718 | |
6719 | /* static */ |
6720 | void nsDocShell::ReportBFCacheComboTelemetry(uint32_t aCombo) { |
6721 | // There are 11 possible reasons to make a request fails to use BFCache |
6722 | // (see BFCacheStatus in dom/base/Document.h), and we'd like to record |
6723 | // the common combinations for reasons which make requests fail to use |
6724 | // BFCache. These combinations are generated based on some local browsings, |
6725 | // we need to adjust them when necessary. |
6726 | enum BFCacheStatusCombo : uint32_t { |
6727 | BFCACHE_SUCCESS, |
6728 | NOT_ONLY_TOPLEVEL = mozilla::dom::BFCacheStatus::NOT_ONLY_TOPLEVEL_IN_BCG, |
6729 | // If both unload and beforeunload listeners are presented, it'll be |
6730 | // recorded as unload |
6731 | UNLOAD = mozilla::dom::BFCacheStatus::UNLOAD_LISTENER, |
6732 | UNLOAD_REQUEST = mozilla::dom::BFCacheStatus::UNLOAD_LISTENER | |
6733 | mozilla::dom::BFCacheStatus::REQUEST, |
6734 | REQUEST = mozilla::dom::BFCacheStatus::REQUEST, |
6735 | UNLOAD_REQUEST_PEER = mozilla::dom::BFCacheStatus::UNLOAD_LISTENER | |
6736 | mozilla::dom::BFCacheStatus::REQUEST | |
6737 | mozilla::dom::BFCacheStatus::ACTIVE_PEER_CONNECTION, |
6738 | UNLOAD_REQUEST_PEER_MSE = |
6739 | mozilla::dom::BFCacheStatus::UNLOAD_LISTENER | |
6740 | mozilla::dom::BFCacheStatus::REQUEST | |
6741 | mozilla::dom::BFCacheStatus::ACTIVE_PEER_CONNECTION | |
6742 | mozilla::dom::BFCacheStatus::CONTAINS_MSE_CONTENT, |
6743 | UNLOAD_REQUEST_MSE = mozilla::dom::BFCacheStatus::UNLOAD_LISTENER | |
6744 | mozilla::dom::BFCacheStatus::REQUEST | |
6745 | mozilla::dom::BFCacheStatus::CONTAINS_MSE_CONTENT, |
6746 | SUSPENDED_UNLOAD_REQUEST_PEER = |
6747 | mozilla::dom::BFCacheStatus::SUSPENDED | |
6748 | mozilla::dom::BFCacheStatus::UNLOAD_LISTENER | |
6749 | mozilla::dom::BFCacheStatus::REQUEST | |
6750 | mozilla::dom::BFCacheStatus::ACTIVE_PEER_CONNECTION, |
6751 | REMOTE_SUBFRAMES = mozilla::dom::BFCacheStatus::CONTAINS_REMOTE_SUBFRAMES, |
6752 | BEFOREUNLOAD = mozilla::dom::BFCacheStatus::BEFOREUNLOAD_LISTENER, |
6753 | }; |
6754 | |
6755 | // Beforeunload is recorded as a blocker only if it is the only one to block |
6756 | // bfcache. |
6757 | if (aCombo != mozilla::dom::BFCacheStatus::BEFOREUNLOAD_LISTENER) { |
6758 | aCombo &= ~mozilla::dom::BFCacheStatus::BEFOREUNLOAD_LISTENER; |
6759 | } |
6760 | switch (aCombo) { |
6761 | case BFCACHE_SUCCESS: |
6762 | Telemetry::AccumulateCategorical( |
6763 | Telemetry::LABELS_BFCACHE_COMBO::BFCache_Success); |
6764 | break; |
6765 | case NOT_ONLY_TOPLEVEL: |
6766 | if (StaticPrefs::docshell_shistory_bfcache_require_no_opener()) { |
6767 | Telemetry::AccumulateCategorical( |
6768 | Telemetry::LABELS_BFCACHE_COMBO::Other); |
6769 | break; |
6770 | } |
6771 | Telemetry::AccumulateCategorical( |
6772 | Telemetry::LABELS_BFCACHE_COMBO::BFCache_Success); |
6773 | Telemetry::AccumulateCategorical( |
6774 | Telemetry::LABELS_BFCACHE_COMBO::Success_Not_Toplevel); |
6775 | break; |
6776 | case UNLOAD: |
6777 | Telemetry::AccumulateCategorical(Telemetry::LABELS_BFCACHE_COMBO::Unload); |
6778 | break; |
6779 | case BEFOREUNLOAD: |
6780 | Telemetry::AccumulateCategorical( |
6781 | Telemetry::LABELS_BFCACHE_COMBO::Beforeunload); |
6782 | break; |
6783 | case UNLOAD_REQUEST: |
6784 | Telemetry::AccumulateCategorical( |
6785 | Telemetry::LABELS_BFCACHE_COMBO::Unload_Req); |
6786 | break; |
6787 | case REQUEST: |
6788 | Telemetry::AccumulateCategorical(Telemetry::LABELS_BFCACHE_COMBO::Req); |
6789 | break; |
6790 | case UNLOAD_REQUEST_PEER: |
6791 | Telemetry::AccumulateCategorical( |
6792 | Telemetry::LABELS_BFCACHE_COMBO::Unload_Req_Peer); |
6793 | break; |
6794 | case UNLOAD_REQUEST_PEER_MSE: |
6795 | Telemetry::AccumulateCategorical( |
6796 | Telemetry::LABELS_BFCACHE_COMBO::Unload_Req_Peer_MSE); |
6797 | break; |
6798 | case UNLOAD_REQUEST_MSE: |
6799 | Telemetry::AccumulateCategorical( |
6800 | Telemetry::LABELS_BFCACHE_COMBO::Unload_Req_MSE); |
6801 | break; |
6802 | case SUSPENDED_UNLOAD_REQUEST_PEER: |
6803 | Telemetry::AccumulateCategorical( |
6804 | Telemetry::LABELS_BFCACHE_COMBO::SPD_Unload_Req_Peer); |
6805 | break; |
6806 | case REMOTE_SUBFRAMES: |
6807 | Telemetry::AccumulateCategorical( |
6808 | Telemetry::LABELS_BFCACHE_COMBO::Remote_Subframes); |
6809 | break; |
6810 | default: |
6811 | Telemetry::AccumulateCategorical(Telemetry::LABELS_BFCACHE_COMBO::Other); |
6812 | break; |
6813 | } |
6814 | }; |
6815 | |
6816 | void nsDocShell::ReattachEditorToWindow(nsISHEntry* aSHEntry) { |
6817 | 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()", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 6817); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()" ")"); do { *((volatile int*)__null) = 6817; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
6818 | 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" , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 6818); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mIsBeingDestroyed" ")"); do { *((volatile int*)__null) = 6818; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
6819 | |
6820 | NS_ASSERTION(!mEditorData,do { if (!(!mEditorData)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Why reattach an editor when we already have one?", "!mEditorData" , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 6821); MOZ_PretendNoReturn(); } } while (0) |
6821 | "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" , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 6821); MOZ_PretendNoReturn(); } } while (0); |
6822 | 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()", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 6823); MOZ_PretendNoReturn(); } } while (0) |
6823 | "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()", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 6823); MOZ_PretendNoReturn(); } } while (0); |
6824 | |
6825 | if (mEditorData || !aSHEntry) { |
6826 | return; |
6827 | } |
6828 | |
6829 | mEditorData = WrapUnique(aSHEntry->ForgetEditorData()); |
6830 | if (mEditorData) { |
6831 | #ifdef DEBUG1 |
6832 | nsresult rv = |
6833 | #endif |
6834 | mEditorData->ReattachToWindow(this); |
6835 | 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)", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 6835); MOZ_PretendNoReturn(); } } while (0); |
6836 | } |
6837 | } |
6838 | |
6839 | void nsDocShell::DetachEditorFromWindow() { |
6840 | if (!mEditorData || mEditorData->WaitingForLoad()) { |
6841 | // If there's nothing to detach, or if the editor data is actually set |
6842 | // up for the _new_ page that's coming in, don't detach. |
6843 | return; |
6844 | } |
6845 | |
6846 | 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()", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 6847); MOZ_PretendNoReturn(); } } while (0) |
6847 | "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()", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 6847); MOZ_PretendNoReturn(); } } while (0); |
6848 | |
6849 | nsresult res = mEditorData->DetachFromWindow(); |
6850 | 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)", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 6850); MOZ_PretendNoReturn(); } } while (0); |
6851 | |
6852 | if (NS_SUCCEEDED(res)((bool)(__builtin_expect(!!(!NS_FAILED_impl(res)), 1)))) { |
6853 | // Make mOSHE hold the owning ref to the editor data. |
6854 | if (mOSHE) { |
6855 | 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" ")" , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 6857); 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 { *((volatile int*)__null) = 6857; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
6856 | "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" ")" , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 6857); 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 { *((volatile int*)__null) = 6857; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
6857 | "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" ")" , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 6857); 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 { *((volatile int*)__null) = 6857; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
6858 | mOSHE->SetEditorData(mEditorData.release()); |
6859 | } else { |
6860 | mEditorData = nullptr; |
6861 | } |
6862 | } |
6863 | |
6864 | #ifdef DEBUG1 |
6865 | { |
6866 | bool isEditable; |
6867 | GetEditable(&isEditable); |
6868 | NS_ASSERTION(!isEditable,do { if (!(!isEditable)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Window is still editable after detaching editor." , "!isEditable", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 6869); MOZ_PretendNoReturn(); } } while (0) |
6869 | "Window is still editable after detaching editor.")do { if (!(!isEditable)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Window is still editable after detaching editor." , "!isEditable", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 6869); MOZ_PretendNoReturn(); } } while (0); |
6870 | } |
6871 | #endif // DEBUG |
6872 | } |
6873 | |
6874 | nsresult nsDocShell::CaptureState() { |
6875 | 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()", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 6875); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()" ")"); do { *((volatile int*)__null) = 6875; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
6876 | |
6877 | if (!mOSHE || mOSHE == mLSHE) { |
6878 | // No entry to save into, or we're replacing the existing entry. |
6879 | return NS_ERROR_FAILURE; |
6880 | } |
6881 | |
6882 | if (!mScriptGlobal) { |
6883 | return NS_ERROR_FAILURE; |
6884 | } |
6885 | |
6886 | nsCOMPtr<nsISupports> windowState = mScriptGlobal->SaveWindowState(); |
6887 | NS_ENSURE_TRUE(windowState, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(windowState)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "windowState" ") failed" , nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 6887); return NS_ERROR_FAILURE; } } while (false); |
6888 | |
6889 | if (MOZ_UNLIKELY(MOZ_LOG_TEST(gPageCacheLog, LogLevel::Debug))(__builtin_expect(!!((__builtin_expect(!!(mozilla::detail::log_test (gPageCacheLog, LogLevel::Debug)), 0))), 0))) { |
6890 | nsAutoCString spec; |
6891 | nsCOMPtr<nsIURI> uri = mOSHE->GetURI(); |
6892 | if (uri) { |
6893 | uri->GetSpec(spec); |
6894 | } |
6895 | 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) |
6896 | ("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); |
6897 | } |
6898 | |
6899 | mOSHE->SetWindowState(windowState); |
6900 | |
6901 | // Suspend refresh URIs and save off the timer queue |
6902 | mOSHE->SetRefreshURIList(mSavedRefreshURIList); |
6903 | |
6904 | // Capture the current content viewer bounds. |
6905 | if (mDocumentViewer) { |
6906 | nsIntRect bounds; |
6907 | mDocumentViewer->GetBounds(bounds); |
6908 | mOSHE->SetViewerBounds(bounds); |
6909 | } |
6910 | |
6911 | // Capture the docshell hierarchy. |
6912 | mOSHE->ClearChildShells(); |
6913 | |
6914 | uint32_t childCount = mChildList.Length(); |
6915 | for (uint32_t i = 0; i < childCount; ++i) { |
6916 | nsCOMPtr<nsIDocShellTreeItem> childShell = do_QueryInterface(ChildAt(i)); |
6917 | NS_ASSERTION(childShell, "null child shell")do { if (!(childShell)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "null child shell" , "childShell", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 6917); MOZ_PretendNoReturn(); } } while (0); |
6918 | |
6919 | mOSHE->AddChildShell(childShell); |
6920 | } |
6921 | |
6922 | return NS_OK; |
6923 | } |
6924 | |
6925 | NS_IMETHODIMPnsresult |
6926 | nsDocShell::RestorePresentationEvent::Run() { |
6927 | 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()", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 6927); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()" ")"); do { *((volatile int*)__null) = 6927; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
6928 | |
6929 | if (mDocShell && NS_FAILED(mDocShell->RestoreFromHistory())((bool)(__builtin_expect(!!(NS_FAILED_impl(mDocShell->RestoreFromHistory ())), 0)))) { |
6930 | NS_WARNING("RestoreFromHistory failed")NS_DebugBreak(NS_DEBUG_WARNING, "RestoreFromHistory failed", nullptr , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 6930); |
6931 | } |
6932 | return NS_OK; |
6933 | } |
6934 | |
6935 | NS_IMETHODIMPnsresult |
6936 | nsDocShell::BeginRestore(nsIDocumentViewer* aDocumentViewer, bool aTop) { |
6937 | 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()", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 6937); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()" ")"); do { *((volatile int*)__null) = 6937; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
6938 | |
6939 | nsresult rv; |
6940 | if (!aDocumentViewer) { |
6941 | rv = EnsureDocumentViewer(); |
6942 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 6942); return rv; } } while (false); |
6943 | |
6944 | aDocumentViewer = mDocumentViewer; |
6945 | } |
6946 | |
6947 | // Dispatch events for restoring the presentation. We try to simulate |
6948 | // the progress notifications loading the document would cause, so we add |
6949 | // the document's channel to the loadgroup to initiate stateChange |
6950 | // notifications. |
6951 | |
6952 | RefPtr<Document> doc = aDocumentViewer->GetDocument(); |
6953 | if (doc) { |
6954 | nsIChannel* channel = doc->GetChannel(); |
6955 | if (channel) { |
6956 | mEODForCurrentDocument = false; |
6957 | mIsRestoringDocument = true; |
6958 | mLoadGroup->AddRequest(channel, nullptr); |
6959 | mIsRestoringDocument = false; |
6960 | } |
6961 | } |
6962 | |
6963 | if (!aTop) { |
6964 | // This point corresponds to us having gotten OnStartRequest or |
6965 | // STATE_START, so do the same thing that CreateDocumentViewer does at |
6966 | // this point to ensure that unload/pagehide events for this document |
6967 | // will fire when it's unloaded again. |
6968 | mFiredUnloadEvent = false; |
6969 | |
6970 | // For non-top frames, there is no notion of making sure that the |
6971 | // previous document is in the domwindow when STATE_START notifications |
6972 | // happen. We can just call BeginRestore for all of the child shells |
6973 | // now. |
6974 | rv = BeginRestoreChildren(); |
6975 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 6975); return rv; } } while (false); |
6976 | } |
6977 | |
6978 | return NS_OK; |
6979 | } |
6980 | |
6981 | nsresult nsDocShell::BeginRestoreChildren() { |
6982 | 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()", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 6982); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()" ")"); do { *((volatile int*)__null) = 6982; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
6983 | |
6984 | for (auto* childDocLoader : mChildList.ForwardRange()) { |
6985 | nsCOMPtr<nsIDocShell> child = do_QueryObject(childDocLoader); |
6986 | if (child) { |
6987 | nsresult rv = child->BeginRestore(nullptr, false); |
6988 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 6988); return rv; } } while (false); |
6989 | } |
6990 | } |
6991 | return NS_OK; |
6992 | } |
6993 | |
6994 | NS_IMETHODIMPnsresult |
6995 | nsDocShell::FinishRestore() { |
6996 | 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()", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 6996); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()" ")"); do { *((volatile int*)__null) = 6996; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
6997 | |
6998 | // First we call finishRestore() on our children. In the simulated load, |
6999 | // all of the child frames finish loading before the main document. |
7000 | |
7001 | for (auto* childDocLoader : mChildList.ForwardRange()) { |
7002 | nsCOMPtr<nsIDocShell> child = do_QueryObject(childDocLoader); |
7003 | if (child) { |
7004 | child->FinishRestore(); |
7005 | } |
7006 | } |
7007 | |
7008 | if (mOSHE && mOSHE->HasDetachedEditor()) { |
7009 | ReattachEditorToWindow(mOSHE); |
7010 | } |
7011 | |
7012 | RefPtr<Document> doc = GetDocument(); |
7013 | if (doc) { |
7014 | // Finally, we remove the request from the loadgroup. This will |
7015 | // cause onStateChange(STATE_STOP) to fire, which will fire the |
7016 | // pageshow event to the chrome. |
7017 | |
7018 | nsIChannel* channel = doc->GetChannel(); |
7019 | if (channel) { |
7020 | mIsRestoringDocument = true; |
7021 | mLoadGroup->RemoveRequest(channel, nullptr, NS_OK); |
7022 | mIsRestoringDocument = false; |
7023 | } |
7024 | } |
7025 | |
7026 | return NS_OK; |
7027 | } |
7028 | |
7029 | NS_IMETHODIMPnsresult |
7030 | nsDocShell::GetRestoringDocument(bool* aRestoring) { |
7031 | *aRestoring = mIsRestoringDocument; |
7032 | return NS_OK; |
7033 | } |
7034 | |
7035 | nsresult nsDocShell::RestorePresentation(nsISHEntry* aSHEntry, |
7036 | bool* aRestoring) { |
7037 | 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()", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 7037); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()" ")"); do { *((volatile int*)__null) = 7037; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
7038 | 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" , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 7038); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mIsBeingDestroyed" ")"); do { *((volatile int*)__null) = 7038; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
7039 | |
7040 | 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", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 7041); MOZ_PretendNoReturn(); } } while (0) |
7041 | "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", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 7041); MOZ_PretendNoReturn(); } } while (0); |
7042 | |
7043 | nsCOMPtr<nsIDocumentViewer> viewer = aSHEntry->GetDocumentViewer(); |
7044 | |
7045 | nsAutoCString spec; |
7046 | if (MOZ_UNLIKELY(MOZ_LOG_TEST(gPageCacheLog, LogLevel::Debug))(__builtin_expect(!!((__builtin_expect(!!(mozilla::detail::log_test (gPageCacheLog, LogLevel::Debug)), 0))), 0))) { |
7047 | nsCOMPtr<nsIURI> uri = aSHEntry->GetURI(); |
7048 | if (uri) { |
7049 | uri->GetSpec(spec); |
7050 | } |
7051 | } |
7052 | |
7053 | *aRestoring = false; |
7054 | |
7055 | if (!viewer) { |
7056 | 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) |
7057 | ("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); |
7058 | return NS_OK; |
7059 | } |
7060 | |
7061 | // We need to make sure the content viewer's container is this docshell. |
7062 | // In subframe navigation, it's possible for the docshell that the |
7063 | // content viewer was originally loaded into to be replaced with a |
7064 | // different one. We don't currently support restoring the presentation |
7065 | // in that case. |
7066 | |
7067 | nsCOMPtr<nsIDocShell> container; |
7068 | viewer->GetContainer(getter_AddRefs(container)); |
7069 | if (!::SameCOMIdentity(container, GetAsSupports(this))) { |
7070 | 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) |
7071 | ("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); |
7072 | aSHEntry->SetDocumentViewer(nullptr); |
7073 | return NS_ERROR_FAILURE; |
7074 | } |
7075 | |
7076 | NS_ASSERTION(mDocumentViewer != viewer, "Restoring existing presentation")do { if (!(mDocumentViewer != viewer)) { NS_DebugBreak(NS_DEBUG_ASSERTION , "Restoring existing presentation", "mDocumentViewer != viewer" , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 7076); MOZ_PretendNoReturn(); } } while (0); |
7077 | |
7078 | 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) |
7079 | ("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); |
7080 | |
7081 | SetHistoryEntryAndUpdateBC(Some(aSHEntry), Nothing()); |
7082 | |
7083 | // Post an event that will remove the request after we've returned |
7084 | // to the event loop. This mimics the way it is called by nsIChannel |
7085 | // implementations. |
7086 | |
7087 | // Revoke any pending restore (just in case). |
7088 | NS_ASSERTION(!mRestorePresentationEvent.IsPending(),do { if (!(!mRestorePresentationEvent.IsPending())) { NS_DebugBreak (NS_DEBUG_ASSERTION, "should only have one RestorePresentationEvent" , "!mRestorePresentationEvent.IsPending()", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 7089); MOZ_PretendNoReturn(); } } while (0) |
7089 | "should only have one RestorePresentationEvent")do { if (!(!mRestorePresentationEvent.IsPending())) { NS_DebugBreak (NS_DEBUG_ASSERTION, "should only have one RestorePresentationEvent" , "!mRestorePresentationEvent.IsPending()", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 7089); MOZ_PretendNoReturn(); } } while (0); |
7090 | mRestorePresentationEvent.Revoke(); |
7091 | |
7092 | RefPtr<RestorePresentationEvent> evt = new RestorePresentationEvent(this); |
7093 | nsresult rv = Dispatch(do_AddRef(evt)); |
7094 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) { |
7095 | mRestorePresentationEvent = evt.get(); |
7096 | // The rest of the restore processing will happen on our event |
7097 | // callback. |
7098 | *aRestoring = true; |
7099 | } |
7100 | |
7101 | return rv; |
7102 | } |
7103 | |
7104 | namespace { |
7105 | class MOZ_STACK_CLASS PresentationEventForgetter { |
7106 | public: |
7107 | explicit PresentationEventForgetter( |
7108 | nsRevocableEventPtr<nsDocShell::RestorePresentationEvent>& |
7109 | aRestorePresentationEvent) |
7110 | : mRestorePresentationEvent(aRestorePresentationEvent), |
7111 | mEvent(aRestorePresentationEvent.get()) {} |
7112 | |
7113 | ~PresentationEventForgetter() { Forget(); } |
7114 | |
7115 | void Forget() { |
7116 | if (mRestorePresentationEvent.get() == mEvent) { |
7117 | mRestorePresentationEvent.Forget(); |
7118 | mEvent = nullptr; |
7119 | } |
7120 | } |
7121 | |
7122 | private: |
7123 | nsRevocableEventPtr<nsDocShell::RestorePresentationEvent>& |
7124 | mRestorePresentationEvent; |
7125 | RefPtr<nsDocShell::RestorePresentationEvent> mEvent; |
7126 | }; |
7127 | |
7128 | } // namespace |
7129 | |
7130 | bool nsDocShell::SandboxFlagsImplyCookies(const uint32_t& aSandboxFlags) { |
7131 | return (aSandboxFlags & (SANDBOXED_ORIGIN | SANDBOXED_SCRIPTS)) == 0; |
7132 | } |
7133 | |
7134 | nsresult nsDocShell::RestoreFromHistory() { |
7135 | 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()", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 7135); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()" ")"); do { *((volatile int*)__null) = 7135; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
7136 | 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()" , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 7136); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mRestorePresentationEvent.IsPending()" ")"); do { *((volatile int*)__null) = 7136; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
7137 | PresentationEventForgetter forgetter(mRestorePresentationEvent); |
7138 | |
7139 | // This section of code follows the same ordering as CreateDocumentViewer. |
7140 | if (!mLSHE) { |
7141 | return NS_ERROR_FAILURE; |
7142 | } |
7143 | |
7144 | nsCOMPtr<nsIDocumentViewer> viewer = mLSHE->GetDocumentViewer(); |
7145 | if (!viewer) { |
7146 | return NS_ERROR_FAILURE; |
7147 | } |
7148 | |
7149 | if (mSavingOldViewer) { |
7150 | // We determined that it was safe to cache the document presentation |
7151 | // at the time we initiated the new load. We need to check whether |
7152 | // it's still safe to do so, since there may have been DOM mutations |
7153 | // or new requests initiated. |
7154 | RefPtr<Document> doc = viewer->GetDocument(); |
7155 | nsIRequest* request = nullptr; |
7156 | if (doc) { |
7157 | request = doc->GetChannel(); |
7158 | } |
7159 | mSavingOldViewer = CanSavePresentation( |
7160 | mLoadType, request, doc, /* aReportBFCacheComboTelemetry */ false); |
7161 | } |
7162 | |
7163 | // Protect against mLSHE going away via a load triggered from |
7164 | // pagehide or unload. |
7165 | nsCOMPtr<nsISHEntry> origLSHE = mLSHE; |
7166 | |
7167 | // Make sure to blow away our mLoadingURI just in case. No loads |
7168 | // from inside this pagehide. |
7169 | mLoadingURI = nullptr; |
7170 | |
7171 | // Notify the old content viewer that it's being hidden. |
7172 | FirePageHideNotification(!mSavingOldViewer); |
7173 | // pagehide notification might destroy this docshell. |
7174 | if (mIsBeingDestroyed) { |
7175 | return NS_ERROR_DOCSHELL_DYING; |
7176 | } |
7177 | |
7178 | // If mLSHE was changed as a result of the pagehide event, then |
7179 | // something else was loaded. Don't finish restoring. |
7180 | if (mLSHE != origLSHE) { |
7181 | return NS_OK; |
7182 | } |
7183 | |
7184 | // Add the request to our load group. We do this before swapping out |
7185 | // the content viewers so that consumers of STATE_START can access |
7186 | // the old document. We only deal with the toplevel load at this time -- |
7187 | // to be consistent with normal document loading, subframes cannot start |
7188 | // loading until after data arrives, which is after STATE_START completes. |
7189 | |
7190 | RefPtr<RestorePresentationEvent> currentPresentationRestoration = |
7191 | mRestorePresentationEvent.get(); |
7192 | Stop(); |
7193 | // Make sure we're still restoring the same presentation. |
7194 | // If we aren't, docshell is in process doing another load already. |
7195 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 7196); return NS_ERROR_UNEXPECTED; } } while (false) |
7196 | mRestorePresentationEvent.get())do { if ((__builtin_expect(!!(!(currentPresentationRestoration == mRestorePresentationEvent.get())), 0))) { NS_DebugBreak(NS_DEBUG_WARNING , "NS_ENSURE_TRUE(" "currentPresentationRestoration == mRestorePresentationEvent.get()" ") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 7196); return NS_ERROR_UNEXPECTED; } } while (false); |
7197 | BeginRestore(viewer, true); |
7198 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 7199); return NS_ERROR_UNEXPECTED; } } while (false) |
7199 | mRestorePresentationEvent.get())do { if ((__builtin_expect(!!(!(currentPresentationRestoration == mRestorePresentationEvent.get())), 0))) { NS_DebugBreak(NS_DEBUG_WARNING , "NS_ENSURE_TRUE(" "currentPresentationRestoration == mRestorePresentationEvent.get()" ") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 7199); return NS_ERROR_UNEXPECTED; } } while (false); |
7200 | forgetter.Forget(); |
7201 | |
7202 | // Set mFiredUnloadEvent = false so that the unload handler for the |
7203 | // *new* document will fire. |
7204 | mFiredUnloadEvent = false; |
7205 | |
7206 | mURIResultedInDocument = true; |
7207 | RefPtr<ChildSHistory> rootSH = GetRootSessionHistory(); |
7208 | if (rootSH) { |
7209 | mPreviousEntryIndex = rootSH->Index(); |
7210 | rootSH->LegacySHistory()->UpdateIndex(); |
7211 | mLoadedEntryIndex = rootSH->Index(); |
7212 | 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) |
7213 | ("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) |
7214 | 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); |
7215 | } |
7216 | |
7217 | // Rather than call Embed(), we will retrieve the viewer from the session |
7218 | // history entry and swap it in. |
7219 | // XXX can we refactor this so that we can just call Embed()? |
7220 | PersistLayoutHistoryState(); |
7221 | nsresult rv; |
7222 | if (mDocumentViewer) { |
7223 | if (mSavingOldViewer && NS_FAILED(CaptureState())((bool)(__builtin_expect(!!(NS_FAILED_impl(CaptureState())), 0 )))) { |
7224 | if (mOSHE) { |
7225 | mOSHE->SyncPresentationState(); |
7226 | } |
7227 | mSavingOldViewer = false; |
7228 | } |
7229 | } |
7230 | |
7231 | mSavedRefreshURIList = nullptr; |
7232 | |
7233 | // In cases where we use a transient about:blank viewer between loads, |
7234 | // we never show the transient viewer, so _its_ previous viewer is never |
7235 | // unhooked from the view hierarchy. Destroy any such previous viewer now, |
7236 | // before we grab the root view sibling, so that we don't grab a view |
7237 | // that's about to go away. |
7238 | |
7239 | if (mDocumentViewer) { |
7240 | // Make sure to hold a strong ref to previousViewer here while we |
7241 | // drop the reference to it from mDocumentViewer. |
7242 | nsCOMPtr<nsIDocumentViewer> previousViewer = |
7243 | mDocumentViewer->GetPreviousViewer(); |
7244 | if (previousViewer) { |
7245 | mDocumentViewer->SetPreviousViewer(nullptr); |
7246 | previousViewer->Destroy(); |
7247 | } |
7248 | } |
7249 | |
7250 | // Save off the root view's parent and sibling so that we can insert the |
7251 | // new content viewer's root view at the same position. Also save the |
7252 | // bounds of the root view's widget. |
7253 | |
7254 | nsView* rootViewSibling = nullptr; |
7255 | nsView* rootViewParent = nullptr; |
7256 | nsIntRect newBounds(0, 0, 0, 0); |
7257 | |
7258 | PresShell* oldPresShell = GetPresShell(); |
7259 | if (oldPresShell) { |
7260 | nsViewManager* vm = oldPresShell->GetViewManager(); |
7261 | if (vm) { |
7262 | nsView* oldRootView = vm->GetRootView(); |
7263 | |
7264 | if (oldRootView) { |
7265 | rootViewSibling = oldRootView->GetNextSibling(); |
7266 | rootViewParent = oldRootView->GetParent(); |
7267 | |
7268 | mDocumentViewer->GetBounds(newBounds); |
7269 | } |
7270 | } |
7271 | } |
7272 | |
7273 | nsCOMPtr<nsIContent> container; |
7274 | RefPtr<Document> sibling; |
7275 | if (rootViewParent && rootViewParent->GetParent()) { |
7276 | nsIFrame* frame = rootViewParent->GetParent()->GetFrame(); |
7277 | container = frame ? frame->GetContent() : nullptr; |
7278 | } |
7279 | if (rootViewSibling) { |
7280 | nsIFrame* frame = rootViewSibling->GetFrame(); |
7281 | sibling = frame ? frame->PresShell()->GetDocument() : nullptr; |
7282 | } |
7283 | |
7284 | // Transfer ownership to mDocumentViewer. By ensuring that either the |
7285 | // docshell or the session history, but not both, have references to the |
7286 | // content viewer, we prevent the viewer from being torn down after |
7287 | // Destroy() is called. |
7288 | |
7289 | if (mDocumentViewer) { |
7290 | mDocumentViewer->Close(mSavingOldViewer ? mOSHE.get() : nullptr); |
7291 | viewer->SetPreviousViewer(mDocumentViewer); |
7292 | } |
7293 | if (mOSHE && (!mDocumentViewer || !mSavingOldViewer)) { |
7294 | // We don't plan to save a viewer in mOSHE; tell it to drop |
7295 | // any other state it's holding. |
7296 | mOSHE->SyncPresentationState(); |
7297 | } |
7298 | |
7299 | // Order the mDocumentViewer setup just like Embed does. |
7300 | mDocumentViewer = nullptr; |
7301 | |
7302 | // Now that we're about to switch documents, forget all of our children. |
7303 | // Note that we cached them as needed up in CaptureState above. |
7304 | DestroyChildren(); |
7305 | |
7306 | mDocumentViewer.swap(viewer); |
7307 | |
7308 | // Grab all of the related presentation from the SHEntry now. |
7309 | // Clearing the viewer from the SHEntry will clear all of this state. |
7310 | nsCOMPtr<nsISupports> windowState = mLSHE->GetWindowState(); |
7311 | mLSHE->SetWindowState(nullptr); |
7312 | |
7313 | bool sticky = mLSHE->GetSticky(); |
7314 | |
7315 | RefPtr<Document> document = mDocumentViewer->GetDocument(); |
7316 | |
7317 | nsCOMArray<nsIDocShellTreeItem> childShells; |
7318 | int32_t i = 0; |
7319 | nsCOMPtr<nsIDocShellTreeItem> child; |
7320 | while (NS_SUCCEEDED(mLSHE->ChildShellAt(i++, getter_AddRefs(child)))((bool)(__builtin_expect(!!(!NS_FAILED_impl(mLSHE->ChildShellAt (i++, getter_AddRefs(child)))), 1))) && |
7321 | child) { |
7322 | childShells.AppendObject(child); |
7323 | } |
7324 | |
7325 | // get the previous content viewer size |
7326 | nsIntRect oldBounds(0, 0, 0, 0); |
7327 | mLSHE->GetViewerBounds(oldBounds); |
7328 | |
7329 | // Restore the refresh URI list. The refresh timers will be restarted |
7330 | // when EndPageLoad() is called. |
7331 | nsCOMPtr<nsIMutableArray> refreshURIList = mLSHE->GetRefreshURIList(); |
7332 | |
7333 | // Reattach to the window object. |
7334 | mIsRestoringDocument = true; // for MediaDocument::BecomeInteractive |
7335 | rv = mDocumentViewer->Open(windowState, mLSHE); |
7336 | mIsRestoringDocument = false; |
7337 | |
7338 | // Hack to keep nsDocShellEditorData alive across the |
7339 | // SetContentViewer(nullptr) call below. |
7340 | UniquePtr<nsDocShellEditorData> data(mLSHE->ForgetEditorData()); |
7341 | |
7342 | // Now remove it from the cached presentation. |
7343 | mLSHE->SetDocumentViewer(nullptr); |
7344 | mEODForCurrentDocument = false; |
7345 | |
7346 | mLSHE->SetEditorData(data.release()); |
7347 | |
7348 | #ifdef DEBUG1 |
7349 | { |
7350 | nsCOMPtr<nsIMutableArray> refreshURIs = mLSHE->GetRefreshURIList(); |
7351 | nsCOMPtr<nsIDocShellTreeItem> childShell; |
7352 | mLSHE->ChildShellAt(0, getter_AddRefs(childShell)); |
7353 | NS_ASSERTION(!refreshURIs && !childShell,do { if (!(!refreshURIs && !childShell)) { NS_DebugBreak (NS_DEBUG_ASSERTION, "SHEntry should have cleared presentation state" , "!refreshURIs && !childShell", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 7354); MOZ_PretendNoReturn(); } } while (0) |
7354 | "SHEntry should have cleared presentation state")do { if (!(!refreshURIs && !childShell)) { NS_DebugBreak (NS_DEBUG_ASSERTION, "SHEntry should have cleared presentation state" , "!refreshURIs && !childShell", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 7354); MOZ_PretendNoReturn(); } } while (0); |
7355 | } |
7356 | #endif |
7357 | |
7358 | // Restore the sticky state of the viewer. The viewer has set this state |
7359 | // on the history entry in Destroy() just before marking itself non-sticky, |
7360 | // to avoid teardown of the presentation. |
7361 | mDocumentViewer->SetSticky(sticky); |
7362 | |
7363 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 7363); return rv; } } while (false); |
7364 | |
7365 | // mLSHE is now our currently-loaded document. |
7366 | SetHistoryEntryAndUpdateBC(Nothing(), Some<nsISHEntry*>(mLSHE)); |
7367 | |
7368 | // We aren't going to restore any items from the LayoutHistoryState, |
7369 | // but we don't want them to stay around in case the page is reloaded. |
7370 | SetLayoutHistoryState(nullptr); |
7371 | |
7372 | // This is the end of our Embed() replacement |
7373 | |
7374 | mSavingOldViewer = false; |
7375 | mEODForCurrentDocument = false; |
7376 | |
7377 | if (document) { |
7378 | RefPtr<nsDocShell> parent = GetInProcessParentDocshell(); |
7379 | if (parent) { |
7380 | RefPtr<Document> d = parent->GetDocument(); |
7381 | if (d) { |
7382 | if (d->EventHandlingSuppressed()) { |
7383 | document->SuppressEventHandling(d->EventHandlingSuppressed()); |
7384 | } |
7385 | } |
7386 | } |
7387 | |
7388 | // Use the uri from the mLSHE we had when we entered this function |
7389 | // (which need not match the document's URI if anchors are involved), |
7390 | // since that's the history entry we're loading. Note that if we use |
7391 | // origLSHE we don't have to worry about whether the entry in question |
7392 | // is still mLSHE or whether it's now mOSHE. |
7393 | nsCOMPtr<nsIURI> uri = origLSHE->GetURI(); |
7394 | SetCurrentURI(uri, document->GetChannel(), /* aFireLocationChange */ true, |
7395 | /* aIsInitialAboutBlank */ false, |
7396 | /* aLocationFlags */ 0); |
7397 | } |
7398 | |
7399 | // This is the end of our CreateDocumentViewer() replacement. |
7400 | // Now we simulate a load. First, we restore the state of the javascript |
7401 | // window object. |
7402 | nsCOMPtr<nsPIDOMWindowOuter> privWin = GetWindow(); |
7403 | NS_ASSERTION(privWin, "could not get nsPIDOMWindow interface")do { if (!(privWin)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "could not get nsPIDOMWindow interface" , "privWin", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 7403); MOZ_PretendNoReturn(); } } while (0); |
7404 | |
7405 | // Now, dispatch a title change event which would happen as the |
7406 | // <head> is parsed. |
7407 | document->NotifyPossibleTitleChange(false); |
7408 | |
7409 | // Now we simulate appending child docshells for subframes. |
7410 | for (i = 0; i < childShells.Count(); ++i) { |
7411 | nsIDocShellTreeItem* childItem = childShells.ObjectAt(i); |
7412 | nsCOMPtr<nsIDocShell> childShell = do_QueryInterface(childItem); |
7413 | |
7414 | // Make sure to not clobber the state of the child. Since AddChild |
7415 | // always clobbers it, save it off first. |
7416 | bool allowRedirects; |
7417 | childShell->GetAllowMetaRedirects(&allowRedirects); |
7418 | |
7419 | bool allowSubframes; |
7420 | childShell->GetAllowSubframes(&allowSubframes); |
7421 | |
7422 | bool allowImages; |
7423 | childShell->GetAllowImages(&allowImages); |
7424 | |
7425 | bool allowMedia = childShell->GetAllowMedia(); |
7426 | |
7427 | bool allowDNSPrefetch; |
7428 | childShell->GetAllowDNSPrefetch(&allowDNSPrefetch); |
7429 | |
7430 | bool allowContentRetargeting = childShell->GetAllowContentRetargeting(); |
7431 | bool allowContentRetargetingOnChildren = |
7432 | childShell->GetAllowContentRetargetingOnChildren(); |
7433 | |
7434 | // this.AddChild(child) calls child.SetDocLoaderParent(this), meaning that |
7435 | // the child inherits our state. Among other things, this means that the |
7436 | // child inherits our mPrivateBrowsingId, which is what we want. |
7437 | AddChild(childItem); |
7438 | |
7439 | childShell->SetAllowMetaRedirects(allowRedirects); |
7440 | childShell->SetAllowSubframes(allowSubframes); |
7441 | childShell->SetAllowImages(allowImages); |
7442 | childShell->SetAllowMedia(allowMedia); |
7443 | childShell->SetAllowDNSPrefetch(allowDNSPrefetch); |
7444 | childShell->SetAllowContentRetargeting(allowContentRetargeting); |
7445 | childShell->SetAllowContentRetargetingOnChildren( |
7446 | allowContentRetargetingOnChildren); |
7447 | |
7448 | rv = childShell->BeginRestore(nullptr, false); |
7449 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 7449); return rv; } } while (false); |
7450 | } |
7451 | |
7452 | // Make sure to restore the window state after adding the child shells back |
7453 | // to the tree. This is necessary for Thaw() and Resume() to propagate |
7454 | // properly. |
7455 | rv = privWin->RestoreWindowState(windowState); |
7456 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 7456); return rv; } } while (false); |
7457 | |
7458 | RefPtr<PresShell> presShell = GetPresShell(); |
7459 | |
7460 | // We may be displayed on a different monitor (or in a different |
7461 | // HiDPI mode) than when we got into the history list. So we need |
7462 | // to check if this has happened. See bug 838239. |
7463 | |
7464 | // Because the prescontext normally handles resolution changes via |
7465 | // a runnable (see nsPresContext::UIResolutionChanged), its device |
7466 | // context won't be -immediately- updated as a result of calling |
7467 | // presShell->BackingScaleFactorChanged(). |
7468 | |
7469 | // But we depend on that device context when adjusting the view size |
7470 | // via mDocumentViewer->SetBounds(newBounds) below. So we need to |
7471 | // explicitly tell it to check for changed resolution here. |
7472 | if (presShell) { |
7473 | RefPtr<nsPresContext> pc = presShell->GetPresContext(); |
7474 | if (pc->DeviceContext()->CheckDPIChange()) { |
7475 | presShell->BackingScaleFactorChanged(); |
7476 | } |
7477 | // Recompute zoom and text-zoom and such. |
7478 | pc->RecomputeBrowsingContextDependentData(); |
7479 | } |
7480 | |
7481 | nsViewManager* newVM = presShell ? presShell->GetViewManager() : nullptr; |
7482 | nsView* newRootView = newVM ? newVM->GetRootView() : nullptr; |
7483 | |
7484 | // Insert the new root view at the correct location in the view tree. |
7485 | if (container) { |
7486 | nsSubDocumentFrame* subDocFrame = |
7487 | do_QueryFrame(container->GetPrimaryFrame()); |
7488 | rootViewParent = subDocFrame ? subDocFrame->EnsureInnerView() : nullptr; |
7489 | } else { |
7490 | rootViewParent = nullptr; |
7491 | } |
7492 | if (sibling && sibling->GetPresShell() && |
7493 | sibling->GetPresShell()->GetViewManager()) { |
7494 | rootViewSibling = sibling->GetPresShell()->GetViewManager()->GetRootView(); |
7495 | } else { |
7496 | rootViewSibling = nullptr; |
7497 | } |
7498 | if (rootViewParent && newRootView && |
7499 | newRootView->GetParent() != rootViewParent) { |
7500 | nsViewManager* parentVM = rootViewParent->GetViewManager(); |
7501 | if (parentVM) { |
7502 | // InsertChild(parent, child, sib, true) inserts the child after |
7503 | // sib in content order, which is before sib in view order. BUT |
7504 | // when sib is null it inserts at the end of the the document |
7505 | // order, i.e., first in view order. But when oldRootSibling is |
7506 | // null, the old root as at the end of the view list --- last in |
7507 | // content order --- and we want to call InsertChild(parent, child, |
7508 | // nullptr, false) in that case. |
7509 | parentVM->InsertChild(rootViewParent, newRootView, rootViewSibling, |
7510 | rootViewSibling ? true : false); |
7511 | |
7512 | NS_ASSERTION(newRootView->GetNextSibling() == rootViewSibling,do { if (!(newRootView->GetNextSibling() == rootViewSibling )) { NS_DebugBreak(NS_DEBUG_ASSERTION, "error in InsertChild" , "newRootView->GetNextSibling() == rootViewSibling", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 7513); MOZ_PretendNoReturn(); } } while (0) |
7513 | "error in InsertChild")do { if (!(newRootView->GetNextSibling() == rootViewSibling )) { NS_DebugBreak(NS_DEBUG_ASSERTION, "error in InsertChild" , "newRootView->GetNextSibling() == rootViewSibling", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 7513); MOZ_PretendNoReturn(); } } while (0); |
7514 | } |
7515 | } |
7516 | |
7517 | nsCOMPtr<nsPIDOMWindowInner> privWinInner = privWin->GetCurrentInnerWindow(); |
7518 | |
7519 | // If parent is suspended, increase suspension count. |
7520 | // This can't be done as early as event suppression since this |
7521 | // depends on docshell tree. |
7522 | privWinInner->SyncStateFromParentWindow(); |
7523 | |
7524 | // Now that all of the child docshells have been put into place, we can |
7525 | // restart the timers for the window and all of the child frames. |
7526 | privWinInner->Resume(); |
7527 | |
7528 | // Now that we have found the inner window of the page restored |
7529 | // from the history, we have to make sure that |
7530 | // performance.navigation.type is 2. |
7531 | Performance* performance = privWinInner->GetPerformance(); |
7532 | if (performance) { |
7533 | performance->GetDOMTiming()->NotifyRestoreStart(); |
7534 | } |
7535 | |
7536 | // Restore the refresh URI list. The refresh timers will be restarted |
7537 | // when EndPageLoad() is called. |
7538 | mRefreshURIList = refreshURIList; |
7539 | |
7540 | // Meta-refresh timers have been restarted for this shell, but not |
7541 | // for our children. Walk the child shells and restart their timers. |
7542 | for (auto* childDocLoader : mChildList.ForwardRange()) { |
7543 | nsCOMPtr<nsIDocShell> child = do_QueryObject(childDocLoader); |
7544 | if (child) { |
7545 | child->ResumeRefreshURIs(); |
7546 | } |
7547 | } |
7548 | |
7549 | // Make sure this presentation is the same size as the previous |
7550 | // presentation. If this is not the same size we showed it at last time, |
7551 | // then we need to resize the widget. |
7552 | |
7553 | // XXXbryner This interacts poorly with Firefox's infobar. If the old |
7554 | // presentation had the infobar visible, then we will resize the new |
7555 | // presentation to that smaller size. However, firing the locationchanged |
7556 | // event will hide the infobar, which will immediately resize the window |
7557 | // back to the larger size. A future optimization might be to restore |
7558 | // the presentation at the "wrong" size, then fire the locationchanged |
7559 | // event and check whether the docshell's new size is the same as the |
7560 | // cached viewer size (skipping the resize if they are equal). |
7561 | |
7562 | if (newRootView) { |
7563 | if (!newBounds.IsEmpty() && !newBounds.IsEqualEdges(oldBounds)) { |
7564 | 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) |
7565 | ("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) |
7566 | 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); |
7567 | mDocumentViewer->SetBounds(newBounds); |
7568 | } else if (ScrollContainerFrame* sf = |
7569 | presShell->GetRootScrollContainerFrame()) { |
7570 | sf->PostScrolledAreaEventForCurrentArea(); |
7571 | } |
7572 | } |
7573 | |
7574 | // The FinishRestore call below can kill these, null them out so we don't |
7575 | // have invalid pointer lying around. |
7576 | newRootView = rootViewSibling = rootViewParent = nullptr; |
7577 | newVM = nullptr; |
7578 | |
7579 | // If the IsUnderHiddenEmbedderElement() state has been changed, we need to |
7580 | // update it. |
7581 | if (oldPresShell && presShell && |
7582 | presShell->IsUnderHiddenEmbedderElement() != |
7583 | oldPresShell->IsUnderHiddenEmbedderElement()) { |
7584 | presShell->SetIsUnderHiddenEmbedderElement( |
7585 | oldPresShell->IsUnderHiddenEmbedderElement()); |
7586 | } |
7587 | |
7588 | // Simulate the completion of the load. |
7589 | nsDocShell::FinishRestore(); |
7590 | |
7591 | // Restart plugins, and paint the content. |
7592 | if (presShell) { |
7593 | presShell->Thaw(); |
7594 | } |
7595 | |
7596 | return privWin->FireDelayedDOMEvents(true); |
7597 | } |
7598 | |
7599 | nsresult nsDocShell::CreateDocumentViewer(const nsACString& aContentType, |
7600 | nsIRequest* aRequest, |
7601 | nsIStreamListener** aContentHandler) { |
7602 | *aContentHandler = nullptr; |
7603 | |
7604 | if (!mTreeOwner || mIsBeingDestroyed) { |
7605 | // If we don't have a tree owner, then we're in the process of being |
7606 | // destroyed. Rather than continue trying to load something, just give up. |
7607 | return NS_ERROR_DOCSHELL_DYING; |
7608 | } |
7609 | |
7610 | if (!mBrowsingContext->AncestorsAreCurrent() || |
7611 | mBrowsingContext->IsInBFCache()) { |
7612 | mBrowsingContext->RemoveRootFromBFCacheSync(); |
7613 | return NS_ERROR_NOT_AVAILABLE; |
7614 | } |
7615 | |
7616 | // Can we check the content type of the current content viewer |
7617 | // and reuse it without destroying it and re-creating it? |
7618 | |
7619 | NS_ASSERTION(mLoadGroup, "Someone ignored return from Init()?")do { if (!(mLoadGroup)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Someone ignored return from Init()?" , "mLoadGroup", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 7619); MOZ_PretendNoReturn(); } } while (0); |
7620 | |
7621 | // Instantiate the content viewer object |
7622 | nsCOMPtr<nsIDocumentViewer> viewer; |
7623 | nsresult rv = NewDocumentViewerObj(aContentType, aRequest, mLoadGroup, |
7624 | aContentHandler, getter_AddRefs(viewer)); |
7625 | |
7626 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
7627 | return rv; |
7628 | } |
7629 | |
7630 | // Notify the current document that it is about to be unloaded!! |
7631 | // |
7632 | // It is important to fire the unload() notification *before* any state |
7633 | // is changed within the DocShell - otherwise, javascript will get the |
7634 | // wrong information :-( |
7635 | // |
7636 | |
7637 | if (mSavingOldViewer) { |
7638 | // We determined that it was safe to cache the document presentation |
7639 | // at the time we initiated the new load. We need to check whether |
7640 | // it's still safe to do so, since there may have been DOM mutations |
7641 | // or new requests initiated. |
7642 | RefPtr<Document> doc = viewer->GetDocument(); |
7643 | mSavingOldViewer = CanSavePresentation( |
7644 | mLoadType, aRequest, doc, /* aReportBFCacheComboTelemetry */ false); |
7645 | } |
7646 | |
7647 | NS_ASSERTION(!mLoadingURI, "Re-entering unload?")do { if (!(!mLoadingURI)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Re-entering unload?", "!mLoadingURI", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 7647); MOZ_PretendNoReturn(); } } while (0); |
7648 | |
7649 | nsCOMPtr<nsIChannel> aOpenedChannel = do_QueryInterface(aRequest); |
7650 | if (aOpenedChannel) { |
7651 | aOpenedChannel->GetURI(getter_AddRefs(mLoadingURI)); |
7652 | } |
7653 | |
7654 | // Grab the current URI, we need to pass it to Embed, and OnNewURI will reset |
7655 | // it before we do call Embed. |
7656 | nsCOMPtr<nsIURI> previousURI = mCurrentURI; |
7657 | |
7658 | FirePageHideNotification(!mSavingOldViewer); |
7659 | if (mIsBeingDestroyed) { |
7660 | // Force to stop the newly created orphaned viewer. |
7661 | viewer->Stop(); |
7662 | return NS_ERROR_DOCSHELL_DYING; |
7663 | } |
7664 | mLoadingURI = nullptr; |
7665 | |
7666 | // Set mFiredUnloadEvent = false so that the unload handler for the |
7667 | // *new* document will fire. |
7668 | mFiredUnloadEvent = false; |
7669 | |
7670 | // we've created a new document so go ahead and call |
7671 | // OnNewURI(), but don't fire OnLocationChange() |
7672 | // notifications before we've called Embed(). See bug 284993. |
7673 | mURIResultedInDocument = true; |
7674 | bool errorOnLocationChangeNeeded = false; |
7675 | nsCOMPtr<nsIChannel> failedChannel = mFailedChannel; |
7676 | nsCOMPtr<nsIURI> failedURI; |
7677 | |
7678 | if (mLoadType == LOAD_ERROR_PAGE) { |
7679 | // We need to set the SH entry and our current URI here and not |
7680 | // at the moment we load the page. We want the same behavior |
7681 | // of Stop() as for a normal page load. See bug 514232 for details. |
7682 | |
7683 | // Revert mLoadType to load type to state the page load failed, |
7684 | // following function calls need it. |
7685 | mLoadType = mFailedLoadType; |
7686 | |
7687 | Document* doc = viewer->GetDocument(); |
7688 | if (doc) { |
7689 | doc->SetFailedChannel(failedChannel); |
7690 | } |
7691 | |
7692 | nsCOMPtr<nsIPrincipal> triggeringPrincipal; |
7693 | if (failedChannel) { |
7694 | // Make sure we have a URI to set currentURI. |
7695 | NS_GetFinalChannelURI(failedChannel, getter_AddRefs(failedURI)); |
7696 | } else { |
7697 | // if there is no failed channel we have to explicitly provide |
7698 | // a triggeringPrincipal for the history entry. |
7699 | triggeringPrincipal = nsContentUtils::GetSystemPrincipal(); |
7700 | } |
7701 | |
7702 | if (!failedURI) { |
7703 | failedURI = mFailedURI; |
7704 | } |
7705 | if (!failedURI) { |
7706 | // We need a URI object to store a session history entry, so make up a URI |
7707 | NS_NewURI(getter_AddRefs(failedURI), "about:blank"); |
7708 | } |
7709 | |
7710 | // When we don't have failedURI, something wrong will happen. See |
7711 | // bug 291876. |
7712 | 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." ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 7712); AnnotateMozCrashReason("MOZ_ASSERT" "(" "failedURI" ") (" "We don't have a URI for history APIs." ")"); do { *((volatile int*)__null) = 7712; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
7713 | |
7714 | mFailedChannel = nullptr; |
7715 | mFailedURI = nullptr; |
7716 | |
7717 | // Create an shistory entry for the old load. |
7718 | if (failedURI) { |
7719 | errorOnLocationChangeNeeded = |
7720 | OnNewURI(failedURI, failedChannel, triggeringPrincipal, nullptr, |
7721 | nullptr, nullptr, false, false); |
7722 | } |
7723 | |
7724 | // Be sure to have a correct mLSHE, it may have been cleared by |
7725 | // EndPageLoad. See bug 302115. |
7726 | ChildSHistory* shistory = GetSessionHistory(); |
7727 | if (!mozilla::SessionHistoryInParent() && shistory && !mLSHE) { |
7728 | int32_t idx = shistory->LegacySHistory()->GetRequestedIndex(); |
7729 | if (idx == -1) { |
7730 | idx = shistory->Index(); |
7731 | } |
7732 | shistory->LegacySHistory()->GetEntryAtIndex(idx, getter_AddRefs(mLSHE)); |
7733 | } |
7734 | |
7735 | mLoadType = LOAD_ERROR_PAGE; |
7736 | } |
7737 | |
7738 | nsCOMPtr<nsIURI> finalURI; |
7739 | // If this a redirect, use the final url (uri) |
7740 | // else use the original url |
7741 | // |
7742 | // Note that this should match what documents do (see Document::Reset). |
7743 | NS_GetFinalChannelURI(aOpenedChannel, getter_AddRefs(finalURI)); |
7744 | |
7745 | bool onLocationChangeNeeded = false; |
7746 | if (finalURI) { |
7747 | // Pass false for aCloneSHChildren, since we're loading a new page here. |
7748 | onLocationChangeNeeded = OnNewURI(finalURI, aOpenedChannel, nullptr, |
7749 | nullptr, nullptr, nullptr, true, false); |
7750 | } |
7751 | |
7752 | // let's try resetting the load group if we need to... |
7753 | nsCOMPtr<nsILoadGroup> currentLoadGroup; |
7754 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 7756); return NS_ERROR_FAILURE; } } while (false) |
7755 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 7756); return NS_ERROR_FAILURE; } } while (false) |
7756 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 7756); return NS_ERROR_FAILURE; } } while (false); |
7757 | |
7758 | if (currentLoadGroup != mLoadGroup) { |
7759 | nsLoadFlags loadFlags = 0; |
7760 | |
7761 | // Cancel any URIs that are currently loading... |
7762 | // XXX: Need to do this eventually Stop(); |
7763 | // |
7764 | // Retarget the document to this loadgroup... |
7765 | // |
7766 | /* First attach the channel to the right loadgroup |
7767 | * and then remove from the old loadgroup. This |
7768 | * puts the notifications in the right order and |
7769 | * we don't null-out mLSHE in OnStateChange() for |
7770 | * all redirected urls |
7771 | */ |
7772 | aOpenedChannel->SetLoadGroup(mLoadGroup); |
7773 | |
7774 | // Mark the channel as being a document URI... |
7775 | aOpenedChannel->GetLoadFlags(&loadFlags); |
7776 | loadFlags |= nsIChannel::LOAD_DOCUMENT_URI; |
7777 | nsCOMPtr<nsILoadInfo> loadInfo = aOpenedChannel->LoadInfo(); |
7778 | if (SandboxFlagsImplyCookies(loadInfo->GetSandboxFlags())) { |
7779 | loadFlags |= nsIRequest::LOAD_DOCUMENT_NEEDS_COOKIE; |
7780 | } |
7781 | |
7782 | aOpenedChannel->SetLoadFlags(loadFlags); |
7783 | |
7784 | mLoadGroup->AddRequest(aRequest, nullptr); |
7785 | if (currentLoadGroup) { |
7786 | currentLoadGroup->RemoveRequest(aRequest, nullptr, NS_BINDING_RETARGETED); |
7787 | } |
7788 | |
7789 | // Update the notification callbacks, so that progress and |
7790 | // status information are sent to the right docshell... |
7791 | aOpenedChannel->SetNotificationCallbacks(this); |
7792 | } |
7793 | |
7794 | NS_ENSURE_SUCCESS(Embed(viewer, nullptr, false,do { nsresult __rv = Embed(viewer, nullptr, false, ShouldAddToSessionHistory (finalURI, aOpenedChannel), 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, ShouldAddToSessionHistory(finalURI, aOpenedChannel), aOpenedChannel, previousURI)" , "NS_ERROR_FAILURE", static_cast<uint32_t>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""); NS_DebugBreak (NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 7797); return NS_ERROR_FAILURE; } } while (false) |
7795 | ShouldAddToSessionHistory(finalURI, aOpenedChannel),do { nsresult __rv = Embed(viewer, nullptr, false, ShouldAddToSessionHistory (finalURI, aOpenedChannel), 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, ShouldAddToSessionHistory(finalURI, aOpenedChannel), aOpenedChannel, previousURI)" , "NS_ERROR_FAILURE", static_cast<uint32_t>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""); NS_DebugBreak (NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 7797); return NS_ERROR_FAILURE; } } while (false) |
7796 | aOpenedChannel, previousURI),do { nsresult __rv = Embed(viewer, nullptr, false, ShouldAddToSessionHistory (finalURI, aOpenedChannel), 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, ShouldAddToSessionHistory(finalURI, aOpenedChannel), aOpenedChannel, previousURI)" , "NS_ERROR_FAILURE", static_cast<uint32_t>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""); NS_DebugBreak (NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 7797); return NS_ERROR_FAILURE; } } while (false) |
7797 | NS_ERROR_FAILURE)do { nsresult __rv = Embed(viewer, nullptr, false, ShouldAddToSessionHistory (finalURI, aOpenedChannel), 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, ShouldAddToSessionHistory(finalURI, aOpenedChannel), aOpenedChannel, previousURI)" , "NS_ERROR_FAILURE", static_cast<uint32_t>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""); NS_DebugBreak (NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 7797); return NS_ERROR_FAILURE; } } while (false); |
7798 | |
7799 | if (!mBrowsingContext->GetHasLoadedNonInitialDocument()) { |
7800 | MOZ_ALWAYS_SUCCEEDS(mBrowsingContext->SetHasLoadedNonInitialDocument(true))do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl (mBrowsingContext->SetHasLoadedNonInitialDocument(true))), 1)))), 1))) { } else { do { static_assert( mozilla::detail:: AssertionConditionType<decltype(false)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("false" " (" "NS_SUCCEEDED(mBrowsingContext->SetHasLoadedNonInitialDocument(true))" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 7800); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false" ") (" "NS_SUCCEEDED(mBrowsingContext->SetHasLoadedNonInitialDocument(true))" ")"); do { *((volatile int*)__null) = 7800; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); |
7801 | } |
7802 | |
7803 | mSavedRefreshURIList = nullptr; |
7804 | mSavingOldViewer = false; |
7805 | mEODForCurrentDocument = false; |
7806 | |
7807 | // if this document is part of a multipart document, |
7808 | // the ID can be used to distinguish it from the other parts. |
7809 | nsCOMPtr<nsIMultiPartChannel> multiPartChannel(do_QueryInterface(aRequest)); |
7810 | if (multiPartChannel) { |
7811 | if (PresShell* presShell = GetPresShell()) { |
7812 | if (Document* doc = presShell->GetDocument()) { |
7813 | uint32_t partID; |
7814 | multiPartChannel->GetPartID(&partID); |
7815 | doc->SetPartID(partID); |
7816 | } |
7817 | } |
7818 | } |
7819 | |
7820 | if (errorOnLocationChangeNeeded) { |
7821 | FireOnLocationChange(this, failedChannel, failedURI, |
7822 | LOCATION_CHANGE_ERROR_PAGE); |
7823 | } else if (onLocationChangeNeeded) { |
7824 | uint32_t locationFlags = |
7825 | (mLoadType & LOAD_CMD_RELOAD) ? uint32_t(LOCATION_CHANGE_RELOAD) : 0; |
7826 | FireOnLocationChange(this, aRequest, mCurrentURI, locationFlags); |
7827 | } |
7828 | |
7829 | return NS_OK; |
7830 | } |
7831 | |
7832 | nsresult nsDocShell::NewDocumentViewerObj(const nsACString& aContentType, |
7833 | nsIRequest* aRequest, |
7834 | nsILoadGroup* aLoadGroup, |
7835 | nsIStreamListener** aContentHandler, |
7836 | nsIDocumentViewer** aViewer) { |
7837 | nsCOMPtr<nsIChannel> aOpenedChannel = do_QueryInterface(aRequest); |
7838 | |
7839 | nsCOMPtr<nsIDocumentLoaderFactory> docLoaderFactory = |
7840 | nsContentUtils::FindInternalDocumentViewer(aContentType); |
7841 | if (!docLoaderFactory) { |
7842 | return NS_ERROR_FAILURE; |
7843 | } |
7844 | |
7845 | // Now create an instance of the content viewer nsLayoutDLF makes the |
7846 | // determination if it should be a "view-source" instead of "view" |
7847 | nsresult rv = docLoaderFactory->CreateInstance( |
7848 | "view", aOpenedChannel, aLoadGroup, aContentType, this, nullptr, |
7849 | aContentHandler, aViewer); |
7850 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 7850); return rv; } } while (false); |
7851 | |
7852 | (*aViewer)->SetContainer(this); |
7853 | return NS_OK; |
7854 | } |
7855 | |
7856 | nsresult nsDocShell::SetupNewViewer(nsIDocumentViewer* aNewViewer, |
7857 | WindowGlobalChild* aWindowActor) { |
7858 | 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" , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 7858); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mIsBeingDestroyed" ")"); do { *((volatile int*)__null) = 7858; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
7859 | |
7860 | // |
7861 | // Copy content viewer state from previous or parent content viewer. |
7862 | // |
7863 | // The following logic is mirrored in nsHTMLDocument::StartDocumentLoad! |
7864 | // |
7865 | // Do NOT to maintain a reference to the old content viewer outside |
7866 | // of this "copying" block, or it will not be destroyed until the end of |
7867 | // this routine and all <SCRIPT>s and event handlers fail! (bug 20315) |
7868 | // |
7869 | // In this block of code, if we get an error result, we return it |
7870 | // but if we get a null pointer, that's perfectly legal for parent |
7871 | // and parentContentViewer. |
7872 | // |
7873 | |
7874 | int32_t x = 0; |
7875 | int32_t y = 0; |
7876 | int32_t cx = 0; |
7877 | int32_t cy = 0; |
7878 | |
7879 | // This will get the size from the current content viewer or from the |
7880 | // Init settings |
7881 | DoGetPositionAndSize(&x, &y, &cx, &cy); |
7882 | |
7883 | nsCOMPtr<nsIDocShellTreeItem> parentAsItem; |
7884 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 7885); return NS_ERROR_FAILURE; } } while (false) |
7885 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 7885); return NS_ERROR_FAILURE; } } while (false); |
7886 | nsCOMPtr<nsIDocShell> parent(do_QueryInterface(parentAsItem)); |
7887 | |
7888 | const Encoding* reloadEncoding = nullptr; |
7889 | int32_t reloadEncodingSource = kCharsetUninitialized; |
7890 | // |newMUDV| also serves as a flag to set the data from the above vars |
7891 | nsCOMPtr<nsIDocumentViewer> newViewer; |
7892 | |
7893 | if (mDocumentViewer || parent) { |
7894 | nsCOMPtr<nsIDocumentViewer> oldViewer; |
7895 | if (mDocumentViewer) { |
7896 | // Get any interesting state from old content viewer |
7897 | // XXX: it would be far better to just reuse the document viewer , |
7898 | // since we know we're just displaying the same document as before |
7899 | oldViewer = mDocumentViewer; |
7900 | |
7901 | // Tell the old content viewer to hibernate in session history when |
7902 | // it is destroyed. |
7903 | |
7904 | if (mSavingOldViewer && NS_FAILED(CaptureState())((bool)(__builtin_expect(!!(NS_FAILED_impl(CaptureState())), 0 )))) { |
7905 | if (mOSHE) { |
7906 | mOSHE->SyncPresentationState(); |
7907 | } |
7908 | mSavingOldViewer = false; |
7909 | } |
7910 | } else { |
7911 | // No old content viewer, so get state from parent's content viewer |
7912 | parent->GetDocViewer(getter_AddRefs(oldViewer)); |
7913 | } |
7914 | |
7915 | if (oldViewer) { |
7916 | newViewer = aNewViewer; |
7917 | if (newViewer) { |
7918 | reloadEncoding = |
7919 | oldViewer->GetReloadEncodingAndSource(&reloadEncodingSource); |
7920 | } |
7921 | } |
7922 | } |
7923 | |
7924 | nscolor bgcolor = NS_RGBA(0, 0, 0, 0)((nscolor)(((0) << 24) | ((0) << 16) | ((0) << 8) | (0))); |
7925 | bool isUnderHiddenEmbedderElement = false; |
7926 | // Ensure that the content viewer is destroyed *after* the GC - bug 71515 |
7927 | nsCOMPtr<nsIDocumentViewer> viewer = mDocumentViewer; |
7928 | if (viewer) { |
7929 | // Stop any activity that may be happening in the old document before |
7930 | // releasing it... |
7931 | viewer->Stop(); |
7932 | |
7933 | // Try to extract the canvas background color from the old |
7934 | // presentation shell, so we can use it for the next document. |
7935 | if (PresShell* presShell = viewer->GetPresShell()) { |
7936 | bgcolor = presShell->GetCanvasBackground(); |
7937 | isUnderHiddenEmbedderElement = presShell->IsUnderHiddenEmbedderElement(); |
7938 | } |
7939 | |
7940 | viewer->Close(mSavingOldViewer ? mOSHE.get() : nullptr); |
7941 | aNewViewer->SetPreviousViewer(viewer); |
7942 | } |
7943 | if (mOSHE && (!mDocumentViewer || !mSavingOldViewer)) { |
7944 | // We don't plan to save a viewer in mOSHE; tell it to drop |
7945 | // any other state it's holding. |
7946 | mOSHE->SyncPresentationState(); |
7947 | } |
7948 | |
7949 | mDocumentViewer = nullptr; |
7950 | |
7951 | // Now that we're about to switch documents, forget all of our children. |
7952 | // Note that we cached them as needed up in CaptureState above. |
7953 | DestroyChildren(); |
7954 | |
7955 | mDocumentViewer = aNewViewer; |
7956 | |
7957 | nsCOMPtr<nsIWidget> widget; |
7958 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 7958); return NS_ERROR_FAILURE; } } while (false); |
7959 | |
7960 | nsIntRect bounds(x, y, cx, cy); |
7961 | |
7962 | mDocumentViewer->SetNavigationTiming(mTiming); |
7963 | |
7964 | if (NS_FAILED(mDocumentViewer->Init(widget, bounds, aWindowActor))((bool)(__builtin_expect(!!(NS_FAILED_impl(mDocumentViewer-> Init(widget, bounds, aWindowActor))), 0)))) { |
7965 | nsCOMPtr<nsIDocumentViewer> viewer = mDocumentViewer; |
7966 | viewer->Close(nullptr); |
7967 | viewer->Destroy(); |
7968 | mDocumentViewer = nullptr; |
7969 | SetCurrentURIInternal(nullptr); |
7970 | NS_WARNING("ContentViewer Initialization failed")NS_DebugBreak(NS_DEBUG_WARNING, "ContentViewer Initialization failed" , nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 7970); |
7971 | return NS_ERROR_FAILURE; |
7972 | } |
7973 | |
7974 | // If we have old state to copy, set the old state onto the new content |
7975 | // viewer |
7976 | if (newViewer) { |
7977 | newViewer->SetReloadEncodingAndSource(reloadEncoding, reloadEncodingSource); |
7978 | } |
7979 | |
7980 | NS_ENSURE_TRUE(mDocumentViewer, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(mDocumentViewer)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "mDocumentViewer" ") failed" , nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 7980); return NS_ERROR_FAILURE; } } while (false); |
7981 | |
7982 | // Stuff the bgcolor from the old pres shell into the new |
7983 | // pres shell. This improves page load continuity. |
7984 | if (RefPtr<PresShell> presShell = mDocumentViewer->GetPresShell()) { |
7985 | presShell->SetCanvasBackground(bgcolor); |
7986 | presShell->ActivenessMaybeChanged(); |
7987 | if (isUnderHiddenEmbedderElement) { |
7988 | presShell->SetIsUnderHiddenEmbedderElement(isUnderHiddenEmbedderElement); |
7989 | } |
7990 | } |
7991 | |
7992 | // XXX: It looks like the LayoutState gets restored again in Embed() |
7993 | // right after the call to SetupNewViewer(...) |
7994 | |
7995 | // We don't show the mDocumentViewer yet, since we want to draw the old page |
7996 | // until we have enough of the new page to show. Just return with the new |
7997 | // viewer still set to hidden. |
7998 | |
7999 | return NS_OK; |
8000 | } |
8001 | |
8002 | void nsDocShell::SetDocCurrentStateObj(nsISHEntry* aShEntry, |
8003 | SessionHistoryInfo* aInfo) { |
8004 | NS_ENSURE_TRUE_VOID(mDocumentViewer)do { if ((__builtin_expect(!!(!(mDocumentViewer)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "mDocumentViewer" ") failed" , nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 8004); return; } } while (false); |
8005 | |
8006 | RefPtr<Document> document = GetDocument(); |
8007 | NS_ENSURE_TRUE_VOID(document)do { if ((__builtin_expect(!!(!(document)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "document" ") failed", nullptr , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 8007); return; } } while (false); |
8008 | |
8009 | nsCOMPtr<nsIStructuredCloneContainer> scContainer; |
8010 | if (mozilla::SessionHistoryInParent()) { |
8011 | // If aInfo is null, just set the document's state object to null. |
8012 | if (aInfo) { |
8013 | scContainer = aInfo->GetStateData(); |
8014 | } |
8015 | 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) |
8016 | ("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); |
8017 | } else { |
8018 | if (aShEntry) { |
8019 | scContainer = aShEntry->GetStateData(); |
8020 | |
8021 | // If aShEntry is null, just set the document's state object to null. |
8022 | } |
8023 | } |
8024 | |
8025 | // It's OK for scContainer too be null here; that just means there's no |
8026 | // state data associated with this history entry. |
8027 | document->SetStateObject(scContainer); |
8028 | } |
8029 | |
8030 | nsresult nsDocShell::CheckLoadingPermissions() { |
8031 | // This method checks whether the caller may load content into |
8032 | // this docshell. Even though we've done our best to hide windows |
8033 | // from code that doesn't have the right to access them, it's |
8034 | // still possible for an evil site to open a window and access |
8035 | // frames in the new window through window.frames[] (which is |
8036 | // allAccess for historic reasons), so we still need to do this |
8037 | // check on load. |
8038 | nsresult rv = NS_OK; |
8039 | |
8040 | if (!IsSubframe()) { |
8041 | // We're not a frame. Permit all loads. |
8042 | return rv; |
8043 | } |
8044 | |
8045 | // Note - The check for a current JSContext here isn't necessarily sensical. |
8046 | // It's just designed to preserve the old semantics during a mass-conversion |
8047 | // patch. |
8048 | if (!nsContentUtils::GetCurrentJSContext()) { |
8049 | return NS_OK; |
8050 | } |
8051 | |
8052 | // Check if the caller is from the same origin as this docshell, |
8053 | // or any of its ancestors. |
8054 | for (RefPtr<BrowsingContext> bc = mBrowsingContext; bc; |
8055 | bc = bc->GetParent()) { |
8056 | // If the BrowsingContext is not in process, then it |
8057 | // is true by construction that its principal will not |
8058 | // subsume the current docshell principal. |
8059 | if (!bc->IsInProcess()) { |
8060 | continue; |
8061 | } |
8062 | |
8063 | nsCOMPtr<nsIScriptGlobalObject> sgo = |
8064 | bc->GetDocShell()->GetScriptGlobalObject(); |
8065 | nsCOMPtr<nsIScriptObjectPrincipal> sop(do_QueryInterface(sgo)); |
8066 | |
8067 | nsIPrincipal* p; |
8068 | if (!sop || !(p = sop->GetPrincipal())) { |
8069 | return NS_ERROR_UNEXPECTED; |
8070 | } |
8071 | |
8072 | if (nsContentUtils::SubjectPrincipal()->Subsumes(p)) { |
8073 | // Same origin, permit load |
8074 | return NS_OK; |
8075 | } |
8076 | } |
8077 | |
8078 | return NS_ERROR_DOM_PROP_ACCESS_DENIED; |
8079 | } |
8080 | |
8081 | //***************************************************************************** |
8082 | // nsDocShell: Site Loading |
8083 | //***************************************************************************** |
8084 | |
8085 | void nsDocShell::CopyFavicon(nsIURI* aOldURI, nsIURI* aNewURI, |
8086 | bool aInPrivateBrowsing) { |
8087 | if (XRE_IsContentProcess()) { |
8088 | dom::ContentChild* contentChild = dom::ContentChild::GetSingleton(); |
8089 | if (contentChild) { |
8090 | contentChild->SendCopyFavicon(aOldURI, aNewURI, aInPrivateBrowsing); |
8091 | } |
8092 | return; |
8093 | } |
8094 | |
8095 | #ifdef MOZ_PLACES1 |
8096 | nsCOMPtr<nsIFaviconService> favSvc = |
8097 | do_GetService("@mozilla.org/browser/favicon-service;1"); |
8098 | if (favSvc) { |
8099 | favSvc->CopyFavicons(aOldURI, aNewURI, |
8100 | aInPrivateBrowsing |
8101 | ? nsIFaviconService::FAVICON_LOAD_PRIVATE |
8102 | : nsIFaviconService::FAVICON_LOAD_NON_PRIVATE, |
8103 | nullptr); |
8104 | } |
8105 | #endif |
8106 | } |
8107 | |
8108 | class InternalLoadEvent : public Runnable { |
8109 | public: |
8110 | InternalLoadEvent(nsDocShell* aDocShell, nsDocShellLoadState* aLoadState) |
8111 | : mozilla::Runnable("InternalLoadEvent"), |
8112 | mDocShell(aDocShell), |
8113 | mLoadState(aLoadState) { |
8114 | // For events, both target and filename should be the version of "null" they |
8115 | // expect. By the time the event is fired, both window targeting and file |
8116 | // downloading have been handled, so we should never have an internal load |
8117 | // event that retargets or had a download. |
8118 | mLoadState->SetTarget(u""_ns); |
8119 | mLoadState->SetFileName(VoidString()); |
8120 | } |
8121 | |
8122 | NS_IMETHODvirtual nsresult |
8123 | Run() override { |
8124 | #ifndef ANDROID |
8125 | 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 8126); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLoadState->TriggeringPrincipal()" ") (" "InternalLoadEvent: Should always have a principal here" ")"); do { *((volatile int*)__null) = 8126; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
8126 | "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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 8126); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLoadState->TriggeringPrincipal()" ") (" "InternalLoadEvent: Should always have a principal here" ")"); do { *((volatile int*)__null) = 8126; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
8127 | #endif |
8128 | return mDocShell->InternalLoad(mLoadState); |
8129 | } |
8130 | |
8131 | private: |
8132 | RefPtr<nsDocShell> mDocShell; |
8133 | RefPtr<nsDocShellLoadState> mLoadState; |
8134 | }; |
8135 | |
8136 | /** |
8137 | * Returns true if we started an asynchronous load (i.e., from the network), but |
8138 | * the document we're loading there hasn't yet become this docshell's active |
8139 | * document. |
8140 | * |
8141 | * When JustStartedNetworkLoad is true, you should be careful about modifying |
8142 | * mLoadType and mLSHE. These are both set when the asynchronous load first |
8143 | * starts, and the load expects that, when it eventually runs InternalLoad, |
8144 | * mLoadType and mLSHE will have their original values. |
8145 | */ |
8146 | bool nsDocShell::JustStartedNetworkLoad() { |
8147 | return mDocumentRequest && mDocumentRequest != GetCurrentDocChannel(); |
8148 | } |
8149 | |
8150 | // The contentType will be INTERNAL_(I)FRAME if this docshell is for a |
8151 | // non-toplevel browsing context in spec terms. (frame, iframe, <object>, |
8152 | // <embed>, etc) |
8153 | // |
8154 | // This return value will be used when we call NS_CheckContentLoadPolicy, and |
8155 | // later when we call DoURILoad. |
8156 | nsContentPolicyType nsDocShell::DetermineContentType() { |
8157 | if (!IsSubframe()) { |
8158 | return nsIContentPolicy::TYPE_DOCUMENT; |
8159 | } |
8160 | |
8161 | const auto& maybeEmbedderElementType = |
8162 | GetBrowsingContext()->GetEmbedderElementType(); |
8163 | if (!maybeEmbedderElementType) { |
8164 | // If the EmbedderElementType hasn't been set yet, just assume we're |
8165 | // an iframe since that's more common. |
8166 | return nsIContentPolicy::TYPE_INTERNAL_IFRAME; |
8167 | } |
8168 | |
8169 | return maybeEmbedderElementType->EqualsLiteral("iframe") |
8170 | ? nsIContentPolicy::TYPE_INTERNAL_IFRAME |
8171 | : nsIContentPolicy::TYPE_INTERNAL_FRAME; |
8172 | } |
8173 | |
8174 | bool nsDocShell::NoopenerForceEnabled() { |
8175 | // If current's top-level browsing context's active document's |
8176 | // cross-origin-opener-policy is "same-origin" or "same-origin + COEP" then |
8177 | // if currentDoc's origin is not same origin with currentDoc's top-level |
8178 | // origin, noopener is force enabled, and name is cleared to "_blank". |
8179 | auto topPolicy = mBrowsingContext->Top()->GetOpenerPolicy(); |
8180 | return (topPolicy == nsILoadInfo::OPENER_POLICY_SAME_ORIGIN || |
8181 | topPolicy == |
8182 | nsILoadInfo:: |
8183 | OPENER_POLICY_SAME_ORIGIN_EMBEDDER_POLICY_REQUIRE_CORP) && |
8184 | !mBrowsingContext->SameOriginWithTop(); |
8185 | } |
8186 | |
8187 | nsresult nsDocShell::PerformRetargeting(nsDocShellLoadState* aLoadState) { |
8188 | 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!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 8188); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState" ") (" "need a load state!" ")"); do { *((volatile int*)__null ) = 8188; __attribute__((nomerge)) ::abort(); } while (false) ; } } while (false); |
8189 | 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!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 8189); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aLoadState->Target().IsEmpty()" ") (" "should have a target here!" ")"); do { *((volatile int *)__null) = 8189; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
8190 | 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 8191); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->TargetBrowsingContext().IsNull()" ") (" "should not have picked target yet" ")"); do { *((volatile int*)__null) = 8191; __attribute__((nomerge)) ::abort(); } while (false); } } while (false) |
8191 | "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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 8191); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->TargetBrowsingContext().IsNull()" ") (" "should not have picked target yet" ")"); do { *((volatile int*)__null) = 8191; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
8192 | |
8193 | nsresult rv = NS_OK; |
8194 | RefPtr<BrowsingContext> targetContext; |
8195 | |
8196 | // Only _self, _parent, and _top are supported in noopener case. But we |
8197 | // have to be careful to not apply that to the noreferrer case. See bug |
8198 | // 1358469. |
8199 | bool allowNamedTarget = |
8200 | !aLoadState->HasInternalLoadFlags(INTERNAL_LOAD_FLAGS_NO_OPENER) || |
8201 | aLoadState->HasInternalLoadFlags(INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER); |
8202 | if (allowNamedTarget || |
8203 | aLoadState->Target().LowerCaseEqualsLiteral("_self") || |
8204 | aLoadState->Target().LowerCaseEqualsLiteral("_parent") || |
8205 | aLoadState->Target().LowerCaseEqualsLiteral("_top")) { |
8206 | Document* document = GetDocument(); |
8207 | NS_ENSURE_TRUE(document, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(document)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "document" ") failed", nullptr , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 8207); return NS_ERROR_FAILURE; } } while (false); |
8208 | WindowGlobalChild* wgc = document->GetWindowGlobalChild(); |
8209 | NS_ENSURE_TRUE(wgc, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(wgc)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING , "NS_ENSURE_TRUE(" "wgc" ") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 8209); return NS_ERROR_FAILURE; } } while (false); |
8210 | targetContext = wgc->FindBrowsingContextWithName( |
8211 | aLoadState->Target(), /* aUseEntryGlobalForAccessCheck */ false); |
8212 | } |
8213 | |
8214 | if (!targetContext) { |
8215 | // If the targetContext doesn't exist, then this is a new docShell and we |
8216 | // should consider this a TYPE_DOCUMENT load |
8217 | // |
8218 | // For example, when target="_blank" |
8219 | |
8220 | // If there's no targetContext, that means we are about to create a new |
8221 | // window. Perform a content policy check before creating the window. Please |
8222 | // note for all other docshell loads content policy checks are performed |
8223 | // within the contentSecurityManager when the channel is about to be |
8224 | // openend. |
8225 | nsISupports* requestingContext = nullptr; |
8226 | if (XRE_IsContentProcess()) { |
8227 | // In e10s the child process doesn't have access to the element that |
8228 | // contains the browsing context (because that element is in the chrome |
8229 | // process). So we just pass mScriptGlobal. |
8230 | requestingContext = ToSupports(mScriptGlobal); |
8231 | } else { |
8232 | // This is for loading non-e10s tabs and toplevel windows of various |
8233 | // sorts. |
8234 | // For the toplevel window cases, requestingElement will be null. |
8235 | nsCOMPtr<Element> requestingElement = |
8236 | mScriptGlobal->GetFrameElementInternal(); |
8237 | requestingContext = requestingElement; |
8238 | } |
8239 | |
8240 | // Ideally we should use the same loadinfo as within DoURILoad which |
8241 | // should match this one when both are applicable. |
8242 | nsCOMPtr<nsILoadInfo> secCheckLoadInfo = |
8243 | new LoadInfo(mScriptGlobal, aLoadState->URI(), |
8244 | aLoadState->TriggeringPrincipal(), requestingContext, |
8245 | nsILoadInfo::SEC_ONLY_FOR_EXPLICIT_CONTENTSEC_CHECK, 0); |
8246 | |
8247 | // Since Content Policy checks are performed within docShell as well as |
8248 | // the ContentSecurityManager we need a reliable way to let certain |
8249 | // nsIContentPolicy consumers ignore duplicate calls. |
8250 | secCheckLoadInfo->SetSkipContentPolicyCheckForWebRequest(true); |
8251 | |
8252 | int16_t shouldLoad = nsIContentPolicy::ACCEPT; |
8253 | rv = NS_CheckContentLoadPolicy(aLoadState->URI(), secCheckLoadInfo, |
8254 | &shouldLoad); |
8255 | |
8256 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || NS_CP_REJECTED(shouldLoad)((shouldLoad) != nsIContentPolicy::ACCEPT)) { |
8257 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) { |
8258 | if (shouldLoad == nsIContentPolicy::REJECT_TYPE) { |
8259 | return NS_ERROR_CONTENT_BLOCKED_SHOW_ALT; |
8260 | } |
8261 | if (shouldLoad == nsIContentPolicy::REJECT_POLICY) { |
8262 | return NS_ERROR_BLOCKED_BY_POLICY; |
8263 | } |
8264 | } |
8265 | |
8266 | return NS_ERROR_CONTENT_BLOCKED; |
8267 | } |
8268 | } |
8269 | |
8270 | // |
8271 | // Resolve the window target before going any further... |
8272 | // If the load has been targeted to another DocShell, then transfer the |
8273 | // load to it... |
8274 | // |
8275 | |
8276 | // We've already done our owner-inheriting. Mask out that bit, so we |
8277 | // don't try inheriting an owner from the target window if we came up |
8278 | // with a null owner above. |
8279 | aLoadState->UnsetInternalLoadFlag(INTERNAL_LOAD_FLAGS_INHERIT_PRINCIPAL); |
8280 | |
8281 | if (!targetContext) { |
8282 | // If the docshell's document is sandboxed, only open a new window |
8283 | // if the document's SANDBOXED_AUXILLARY_NAVIGATION flag is not set. |
8284 | // (i.e. if allow-popups is specified) |
8285 | NS_ENSURE_TRUE(mDocumentViewer, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(mDocumentViewer)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "mDocumentViewer" ") failed" , nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 8285); return NS_ERROR_FAILURE; } } while (false); |
8286 | Document* doc = mDocumentViewer->GetDocument(); |
8287 | |
8288 | const bool isDocumentAuxSandboxed = |
8289 | doc && (doc->GetSandboxFlags() & SANDBOXED_AUXILIARY_NAVIGATION); |
8290 | |
8291 | if (isDocumentAuxSandboxed) { |
8292 | return NS_ERROR_DOM_INVALID_ACCESS_ERR; |
8293 | } |
8294 | |
8295 | nsCOMPtr<nsPIDOMWindowOuter> win = GetWindow(); |
8296 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 8296); return NS_ERROR_NOT_AVAILABLE; } } while (false); |
8297 | |
8298 | RefPtr<BrowsingContext> newBC; |
8299 | nsAutoCString spec; |
8300 | aLoadState->URI()->GetSpec(spec); |
8301 | |
8302 | // If we are a noopener load, we just hand the whole thing over to our |
8303 | // window. |
8304 | if (aLoadState->HasInternalLoadFlags(INTERNAL_LOAD_FLAGS_NO_OPENER) || |
8305 | NoopenerForceEnabled()) { |
8306 | // Various asserts that we know to hold because NO_OPENER loads can only |
8307 | // happen for links. |
8308 | 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()", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 8308); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aLoadState->LoadReplace()" ")"); do { *((volatile int*)__null) = 8308; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
8309 | 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()" , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 8310); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->PrincipalToInherit() == aLoadState->TriggeringPrincipal()" ")"); do { *((volatile int*)__null) = 8310; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
8310 | 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()" , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 8310); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->PrincipalToInherit() == aLoadState->TriggeringPrincipal()" ")"); do { *((volatile int*)__null) = 8310; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
8311 | 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 8315); 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 { *((volatile int*)__null) = 8315; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
8312 | ~(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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 8315); 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 { *((volatile int*)__null) = 8315; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
8313 | 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 8315); 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 { *((volatile int*)__null) = 8315; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
8314 | "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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 8315); 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 { *((volatile int*)__null) = 8315; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
8315 | "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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 8315); 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 { *((volatile int*)__null) = 8315; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
8316 | 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()", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 8317); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->IsFormSubmission()" ")"); do { *((volatile int*)__null) = 8317; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) |
8317 | 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()", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 8317); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->IsFormSubmission()" ")"); do { *((volatile int*)__null) = 8317; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); |
8318 | 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()", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 8318); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aLoadState->HeadersStream()" ")"); do { *((volatile int*)__null) = 8318; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
8319 | // If OnLinkClickSync was invoked inside the onload handler, the load |
8320 | // type would be set to LOAD_NORMAL_REPLACE; otherwise it should be |
8321 | // LOAD_LINK. |
8322 | 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" , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 8323); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->LoadType() == LOAD_LINK || aLoadState->LoadType() == LOAD_NORMAL_REPLACE" ")"); do { *((volatile int*)__null) = 8323; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
8323 | 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" , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 8323); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->LoadType() == LOAD_LINK || aLoadState->LoadType() == LOAD_NORMAL_REPLACE" ")"); do { *((volatile int*)__null) = 8323; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
8324 | 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()" , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 8324); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aLoadState->LoadIsFromSessionHistory()" ")"); do { *((volatile int*)__null) = 8324; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
8325 | 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()" , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 8325); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->FirstParty()" ")"); do { *((volatile int*)__null) = 8325; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); // Windowwatcher will assume this. |
8326 | |
8327 | RefPtr<nsDocShellLoadState> loadState = |
8328 | new nsDocShellLoadState(aLoadState->URI()); |
8329 | |
8330 | // Set up our loadinfo so it will do the load as much like we would have |
8331 | // as possible. |
8332 | loadState->SetReferrerInfo(aLoadState->GetReferrerInfo()); |
8333 | loadState->SetOriginalURI(aLoadState->OriginalURI()); |
8334 | |
8335 | Maybe<nsCOMPtr<nsIURI>> resultPrincipalURI; |
8336 | aLoadState->GetMaybeResultPrincipalURI(resultPrincipalURI); |
8337 | |
8338 | loadState->SetMaybeResultPrincipalURI(resultPrincipalURI); |
8339 | loadState->SetKeepResultPrincipalURIIfSet( |
8340 | aLoadState->KeepResultPrincipalURIIfSet()); |
8341 | // LoadReplace will always be false due to asserts above, skip setting |
8342 | // it. |
8343 | loadState->SetTriggeringPrincipal(aLoadState->TriggeringPrincipal()); |
8344 | loadState->SetTriggeringSandboxFlags( |
8345 | aLoadState->TriggeringSandboxFlags()); |
8346 | loadState->SetTriggeringWindowId(aLoadState->TriggeringWindowId()); |
8347 | loadState->SetTriggeringStorageAccess( |
8348 | aLoadState->TriggeringStorageAccess()); |
8349 | loadState->SetCsp(aLoadState->Csp()); |
8350 | loadState->SetInheritPrincipal(aLoadState->HasInternalLoadFlags( |
8351 | INTERNAL_LOAD_FLAGS_INHERIT_PRINCIPAL)); |
8352 | // Explicit principal because we do not want any guesses as to what the |
8353 | // principal to inherit is: it should be aTriggeringPrincipal. |
8354 | loadState->SetPrincipalIsExplicit(true); |
8355 | loadState->SetLoadType(aLoadState->LoadType()); |
8356 | loadState->SetForceAllowDataURI(aLoadState->HasInternalLoadFlags( |
8357 | INTERNAL_LOAD_FLAGS_FORCE_ALLOW_DATA_URI)); |
8358 | |
8359 | loadState->SetHasValidUserGestureActivation( |
8360 | aLoadState->HasValidUserGestureActivation()); |
8361 | |
8362 | loadState->SetTextDirectiveUserActivation( |
8363 | aLoadState->GetTextDirectiveUserActivation()); |
8364 | |
8365 | // Propagate POST data to the new load. |
8366 | loadState->SetPostDataStream(aLoadState->PostDataStream()); |
8367 | loadState->SetIsFormSubmission(aLoadState->IsFormSubmission()); |
8368 | |
8369 | rv = win->Open(spec, |
8370 | aLoadState->Target(), // window name |
8371 | u""_ns, // Features |
8372 | loadState, |
8373 | true, // aForceNoOpener |
8374 | getter_AddRefs(newBC)); |
8375 | 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", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 8375); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!newBC" ")" ); do { *((volatile int*)__null) = 8375; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
8376 | return rv; |
8377 | } |
8378 | |
8379 | rv = win->OpenNoNavigate(spec, |
8380 | aLoadState->Target(), // window name |
8381 | u""_ns, // Features |
8382 | getter_AddRefs(newBC)); |
8383 | |
8384 | // In some cases the Open call doesn't actually result in a new |
8385 | // window being opened. We can detect these cases by examining the |
8386 | // document in |newBC|, if any. |
8387 | nsCOMPtr<nsPIDOMWindowOuter> piNewWin = |
8388 | newBC ? newBC->GetDOMWindow() : nullptr; |
8389 | if (piNewWin) { |
8390 | RefPtr<Document> newDoc = piNewWin->GetExtantDoc(); |
8391 | if (!newDoc || newDoc->IsInitialDocument()) { |
8392 | aLoadState->SetInternalLoadFlag(INTERNAL_LOAD_FLAGS_FIRST_LOAD); |
8393 | } |
8394 | } |
8395 | |
8396 | if (newBC) { |
8397 | targetContext = newBC; |
8398 | } |
8399 | } |
8400 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 8400); return rv; } } while (false); |
8401 | NS_ENSURE_TRUE(targetContext, rv)do { if ((__builtin_expect(!!(!(targetContext)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "targetContext" ") failed" , nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 8401); return rv; } } while (false); |
8402 | |
8403 | // If our target BrowsingContext is still pending initialization, ignore the |
8404 | // navigation request targeting it. |
8405 | if (NS_WARN_IF(targetContext->GetPendingInitialization())NS_warn_if_impl(targetContext->GetPendingInitialization(), "targetContext->GetPendingInitialization()", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 8405)) { |
8406 | return NS_OK; |
8407 | } |
8408 | |
8409 | aLoadState->SetTargetBrowsingContext(targetContext); |
8410 | if (aLoadState->IsFormSubmission()) { |
8411 | aLoadState->SetLoadType( |
8412 | GetLoadTypeForFormSubmission(targetContext, aLoadState)); |
8413 | } |
8414 | |
8415 | // |
8416 | // Transfer the load to the target BrowsingContext... Clear the window target |
8417 | // name to the empty string to prevent recursive retargeting! |
8418 | // |
8419 | // No window target |
8420 | aLoadState->SetTarget(u""_ns); |
8421 | // No forced download |
8422 | aLoadState->SetFileName(VoidString()); |
8423 | return targetContext->InternalLoad(aLoadState); |
8424 | } |
8425 | |
8426 | static nsAutoCString RefMaybeNull(nsIURI* aURI) { |
8427 | nsAutoCString result; |
8428 | if (NS_FAILED(aURI->GetRef(result))((bool)(__builtin_expect(!!(NS_FAILED_impl(aURI->GetRef(result ))), 0)))) { |
8429 | result.SetIsVoid(true); |
8430 | } |
8431 | return result; |
8432 | } |
8433 | |
8434 | uint32_t nsDocShell::GetSameDocumentNavigationFlags(nsIURI* aNewURI) { |
8435 | uint32_t flags = LOCATION_CHANGE_SAME_DOCUMENT; |
8436 | |
8437 | bool equal = false; |
8438 | if (mCurrentURI && |
8439 | NS_SUCCEEDED(mCurrentURI->EqualsExceptRef(aNewURI, &equal))((bool)(__builtin_expect(!!(!NS_FAILED_impl(mCurrentURI->EqualsExceptRef (aNewURI, &equal))), 1))) && equal && |
8440 | RefMaybeNull(mCurrentURI) != RefMaybeNull(aNewURI)) { |
8441 | flags |= LOCATION_CHANGE_HASHCHANGE; |
8442 | } |
8443 | |
8444 | return flags; |
8445 | } |
8446 | |
8447 | struct SameDocumentNavigationState { |
8448 | nsAutoCString mCurrentHash; |
8449 | nsAutoCString mNewHash; |
8450 | nsTArray<TextDirective> mTextDirectives; |
8451 | bool mCurrentURIHasRef = false; |
8452 | bool mNewURIHasRef = false; |
8453 | bool mSameExceptHashes = false; |
8454 | bool mSecureUpgradeURI = false; |
8455 | bool mHistoryNavBetweenSameDoc = false; |
8456 | }; |
8457 | |
8458 | bool nsDocShell::IsSameDocumentNavigation(nsDocShellLoadState* aLoadState, |
8459 | SameDocumentNavigationState& aState) { |
8460 | 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", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 8460); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState" ")"); do { *((volatile int*)__null) = 8460; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
8461 | if (!(aLoadState->LoadType() == LOAD_NORMAL || |
8462 | aLoadState->LoadType() == LOAD_STOP_CONTENT || |
8463 | LOAD_TYPE_HAS_FLAGS(aLoadState->LoadType(),((aLoadState->LoadType()) & ((LOAD_FLAGS_REPLACE_HISTORY ) << 16)) |
8464 | LOAD_FLAGS_REPLACE_HISTORY)((aLoadState->LoadType()) & ((LOAD_FLAGS_REPLACE_HISTORY ) << 16)) || |
8465 | aLoadState->LoadType() == LOAD_HISTORY || |
8466 | aLoadState->LoadType() == LOAD_LINK)) { |
8467 | return false; |
8468 | } |
8469 | |
8470 | nsCOMPtr<nsIURI> currentURI = mCurrentURI; |
8471 | |
8472 | nsresult rvURINew = aLoadState->URI()->GetRef(aState.mNewHash); |
8473 | if (NS_SUCCEEDED(rvURINew)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rvURINew)), 1)))) { |
8474 | rvURINew = aLoadState->URI()->GetHasRef(&aState.mNewURIHasRef); |
8475 | } |
8476 | |
8477 | // A Fragment Directive must be removed from the new hash in order to allow |
8478 | // fallback element id scroll. |
8479 | FragmentDirective::ParseAndRemoveFragmentDirectiveFromFragmentString( |
8480 | aState.mNewHash, &aState.mTextDirectives, aLoadState->URI()); |
8481 | |
8482 | if (currentURI && NS_SUCCEEDED(rvURINew)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rvURINew)), 1)))) { |
8483 | nsresult rvURIOld = currentURI->GetRef(aState.mCurrentHash); |
8484 | if (NS_SUCCEEDED(rvURIOld)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rvURIOld)), 1)))) { |
8485 | rvURIOld = currentURI->GetHasRef(&aState.mCurrentURIHasRef); |
8486 | } |
8487 | if (NS_SUCCEEDED(rvURIOld)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rvURIOld)), 1)))) { |
8488 | if (NS_FAILED(currentURI->EqualsExceptRef(aLoadState->URI(),((bool)(__builtin_expect(!!(NS_FAILED_impl(currentURI->EqualsExceptRef (aLoadState->URI(), &aState.mSameExceptHashes))), 0))) |
8489 | &aState.mSameExceptHashes))((bool)(__builtin_expect(!!(NS_FAILED_impl(currentURI->EqualsExceptRef (aLoadState->URI(), &aState.mSameExceptHashes))), 0)))) { |
8490 | aState.mSameExceptHashes = false; |
8491 | } |
8492 | } |
8493 | } |
8494 | |
8495 | if (!aState.mSameExceptHashes && currentURI && NS_SUCCEEDED(rvURINew)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rvURINew)), 1)))) { |
8496 | // Maybe aLoadState->URI() came from the exposable form of currentURI? |
8497 | nsCOMPtr<nsIURI> currentExposableURI = |
8498 | nsIOService::CreateExposableURI(currentURI); |
8499 | nsresult rvURIOld = currentExposableURI->GetRef(aState.mCurrentHash); |
8500 | if (NS_SUCCEEDED(rvURIOld)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rvURIOld)), 1)))) { |
8501 | rvURIOld = currentExposableURI->GetHasRef(&aState.mCurrentURIHasRef); |
8502 | } |
8503 | if (NS_SUCCEEDED(rvURIOld)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rvURIOld)), 1)))) { |
8504 | if (NS_FAILED(currentExposableURI->EqualsExceptRef(((bool)(__builtin_expect(!!(NS_FAILED_impl(currentExposableURI ->EqualsExceptRef( aLoadState->URI(), &aState.mSameExceptHashes ))), 0))) |
8505 | aLoadState->URI(), &aState.mSameExceptHashes))((bool)(__builtin_expect(!!(NS_FAILED_impl(currentExposableURI ->EqualsExceptRef( aLoadState->URI(), &aState.mSameExceptHashes ))), 0)))) { |
8506 | aState.mSameExceptHashes = false; |
8507 | } |
8508 | // HTTPS-Only Mode upgrades schemes from http to https in Necko, hence we |
8509 | // have to perform a special check here to avoid an actual navigation. If |
8510 | // HTTPS-Only Mode is enabled and the two URIs are same-origin (modulo the |
8511 | // fact that the new URI is currently http), then set mSameExceptHashes to |
8512 | // true and only perform a fragment navigation. |
8513 | if (!aState.mSameExceptHashes) { |
8514 | if (nsCOMPtr<nsIChannel> docChannel = GetCurrentDocChannel()) { |
8515 | nsCOMPtr<nsILoadInfo> docLoadInfo = docChannel->LoadInfo(); |
8516 | if (!docLoadInfo->GetLoadErrorPage() && |
8517 | nsHTTPSOnlyUtils::ShouldUpgradeConnection(docLoadInfo) && |
8518 | nsHTTPSOnlyUtils::IsHttpDowngrade(currentExposableURI, |
8519 | aLoadState->URI())) { |
8520 | uint32_t status = docLoadInfo->GetHttpsOnlyStatus(); |
8521 | if (status & (nsILoadInfo::HTTPS_ONLY_UPGRADED_LISTENER_REGISTERED | |
8522 | nsILoadInfo::HTTPS_ONLY_UPGRADED_HTTPS_FIRST)) { |
8523 | // At this point the requested URI is for sure a fragment |
8524 | // navigation via HTTP and HTTPS-Only mode or HTTPS-First is |
8525 | // enabled. Also it is not interfering the upgrade order of |
8526 | // https://searchfox.org/mozilla-central/source/netwerk/base/nsNetUtil.cpp#2948-2953. |
8527 | // Since we are on an HTTPS site the fragment |
8528 | // navigation should also be an HTTPS. |
8529 | // For that reason we should upgrade the URI to HTTPS. |
8530 | aState.mSecureUpgradeURI = true; |
8531 | aState.mSameExceptHashes = true; |
8532 | } |
8533 | } |
8534 | } |
8535 | } |
8536 | } |
8537 | } |
8538 | |
8539 | if (mozilla::SessionHistoryInParent()) { |
8540 | if (mActiveEntry && aLoadState->LoadIsFromSessionHistory()) { |
8541 | aState.mHistoryNavBetweenSameDoc = mActiveEntry->SharesDocumentWith( |
8542 | aLoadState->GetLoadingSessionHistoryInfo()->mInfo); |
8543 | } |
8544 | 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) |
8545 | ("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) |
8546 | 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); |
8547 | } else { |
8548 | if (mOSHE && aLoadState->LoadIsFromSessionHistory()) { |
8549 | // We're doing a history load. |
8550 | |
8551 | mOSHE->SharesDocumentWith(aLoadState->SHEntry(), |
8552 | &aState.mHistoryNavBetweenSameDoc); |
8553 | } |
8554 | } |
8555 | |
8556 | // A same document navigation happens when we navigate between two SHEntries |
8557 | // for the same document. We do a same document navigation under two |
8558 | // circumstances. Either |
8559 | // |
8560 | // a) we're navigating between two different SHEntries which share a |
8561 | // document, or |
8562 | // |
8563 | // b) we're navigating to a new shentry whose URI differs from the |
8564 | // current URI only in its hash, the new hash is non-empty, and |
8565 | // we're not doing a POST. |
8566 | // |
8567 | // The restriction that the SHEntries in (a) must be different ensures |
8568 | // that history.go(0) and the like trigger full refreshes, rather than |
8569 | // same document navigations. |
8570 | if (!mozilla::SessionHistoryInParent()) { |
8571 | bool doSameDocumentNavigation = |
8572 | (aState.mHistoryNavBetweenSameDoc && mOSHE != aLoadState->SHEntry()) || |
8573 | (!aLoadState->SHEntry() && !aLoadState->PostDataStream() && |
8574 | aState.mSameExceptHashes && aState.mNewURIHasRef); |
8575 | 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) |
8576 | ("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) |
8577 | 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); |
8578 | return doSameDocumentNavigation; |
8579 | } |
8580 | |
8581 | if (aState.mHistoryNavBetweenSameDoc && |
8582 | !aLoadState->GetLoadingSessionHistoryInfo()->mLoadingCurrentEntry) { |
8583 | return true; |
8584 | } |
8585 | |
8586 | 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) |
8587 | 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) |
8588 | ("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) |
8589 | "!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) |
8590 | 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) |
8591 | !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) |
8592 | 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) |
8593 | 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); |
8594 | return !aLoadState->LoadIsFromSessionHistory() && |
8595 | !aLoadState->PostDataStream() && aState.mSameExceptHashes && |
8596 | aState.mNewURIHasRef; |
8597 | } |
8598 | |
8599 | nsresult nsDocShell::HandleSameDocumentNavigation( |
8600 | nsDocShellLoadState* aLoadState, SameDocumentNavigationState& aState, |
8601 | bool& aSameDocument) { |
8602 | aSameDocument = true; |
8603 | #ifdef DEBUG1 |
8604 | SameDocumentNavigationState state; |
8605 | 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)" , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 8605); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsSameDocumentNavigation(aLoadState, state)" ")"); do { *((volatile int*)__null) = 8605; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
8606 | #endif |
8607 | |
8608 | 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) |
8609 | ("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) |
8610 | 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) |
8611 | 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); |
8612 | |
8613 | RefPtr<Document> doc = GetDocument(); |
8614 | NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(doc)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING , "NS_ENSURE_TRUE(" "doc" ") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 8614); return NS_ERROR_FAILURE; } } while (false); |
8615 | doc->DoNotifyPossibleTitleChange(); |
8616 | |
8617 | // Store the pending uninvoked directives if it is a same document navigation. |
8618 | // We need to set it here, in case the navigation happens before the document |
8619 | // has actually finished loading. |
8620 | doc->FragmentDirective()->SetTextDirectives( |
8621 | std::move(aState.mTextDirectives)); |
8622 | |
8623 | nsCOMPtr<nsIURI> currentURI = mCurrentURI; |
8624 | |
8625 | // We need to upgrade the new URI from http: to https: |
8626 | nsCOMPtr<nsIURI> newURI = aLoadState->URI(); |
8627 | if (aState.mSecureUpgradeURI) { |
8628 | MOZ_TRY(NS_GetSecureUpgradedURI(aLoadState->URI(), getter_AddRefs(newURI)))do { auto mozTryTempResult_ = ::mozilla::ToResult(NS_GetSecureUpgradedURI (aLoadState->URI(), getter_AddRefs(newURI))); if ((__builtin_expect (!!(mozTryTempResult_.isErr()), 0))) { return mozTryTempResult_ .propagateErr(); } } while (0); |
8629 | 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) |
8630 | ("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); |
8631 | } |
8632 | |
8633 | if (StaticPrefs::dom_security_setdocumenturi()) { |
8634 | // check if aLoadState->URI(), principalURI, mCurrentURI are same origin |
8635 | // skip handling otherwise |
8636 | nsCOMPtr<nsIPrincipal> origPrincipal = doc->NodePrincipal(); |
8637 | nsCOMPtr<nsIURI> principalURI = origPrincipal->GetURI(); |
8638 | if (origPrincipal->GetIsNullPrincipal()) { |
8639 | nsCOMPtr<nsIPrincipal> precursor = origPrincipal->GetPrecursorPrincipal(); |
8640 | if (precursor) { |
8641 | principalURI = precursor->GetURI(); |
8642 | } |
8643 | } |
8644 | |
8645 | if (nsScriptSecurityManager::IsHttpOrHttpsAndCrossOrigin(principalURI, |
8646 | newURI) || |
8647 | nsScriptSecurityManager::IsHttpOrHttpsAndCrossOrigin(principalURI, |
8648 | mCurrentURI) || |
8649 | nsScriptSecurityManager::IsHttpOrHttpsAndCrossOrigin(mCurrentURI, |
8650 | newURI)) { |
8651 | aSameDocument = false; |
8652 | 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) |
8653 | ("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) |
8654 | "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) |
8655 | 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); |
8656 | return NS_OK; |
8657 | } |
8658 | } |
8659 | |
8660 | #ifdef DEBUG1 |
8661 | if (aState.mSameExceptHashes) { |
8662 | bool sameExceptHashes = false; |
8663 | currentURI->EqualsExceptRef(newURI, &sameExceptHashes); |
8664 | 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" , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 8664); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sameExceptHashes" ")"); do { *((volatile int*)__null) = 8664; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
8665 | } |
8666 | #endif |
8667 | const nsCOMPtr<nsILoadInfo> loadInfo = |
8668 | doc->GetChannel() ? doc->GetChannel()->LoadInfo() : nullptr; |
8669 | if (loadInfo) { |
8670 | loadInfo->SetIsSameDocumentNavigation(true); |
8671 | } |
8672 | // Save the position of the scrollers. |
8673 | nsPoint scrollPos = GetCurScrollPos(); |
8674 | |
8675 | // Reset mLoadType to its original value once we exit this block, because this |
8676 | // same document navigation might have started after a normal, network load, |
8677 | // and we don't want to clobber its load type. See bug 737307. |
8678 | AutoRestore<uint32_t> loadTypeResetter(mLoadType); |
8679 | |
8680 | // If a non-same-document-navigation (i.e., a network load) is pending, make |
8681 | // this a replacement load, so that we don't add a SHEntry here and the |
8682 | // network load goes into the SHEntry it expects to. |
8683 | if (JustStartedNetworkLoad() && (aLoadState->LoadType() & LOAD_CMD_NORMAL)) { |
8684 | mLoadType = LOAD_NORMAL_REPLACE; |
8685 | } else { |
8686 | mLoadType = aLoadState->LoadType(); |
8687 | } |
8688 | |
8689 | mURIResultedInDocument = true; |
8690 | |
8691 | nsCOMPtr<nsISHEntry> oldLSHE = mLSHE; |
8692 | |
8693 | // we need to assign aLoadState->SHEntry() to mLSHE right here, so that on |
8694 | // History loads, SetCurrentURI() called from OnNewURI() will send proper |
8695 | // onLocationChange() notifications to the browser to update back/forward |
8696 | // buttons. |
8697 | SetHistoryEntryAndUpdateBC(Some<nsISHEntry*>(aLoadState->SHEntry()), |
8698 | Nothing()); |
8699 | UniquePtr<mozilla::dom::LoadingSessionHistoryInfo> oldLoadingEntry; |
8700 | mLoadingEntry.swap(oldLoadingEntry); |
8701 | if (aLoadState->GetLoadingSessionHistoryInfo()) { |
8702 | mLoadingEntry = MakeUnique<LoadingSessionHistoryInfo>( |
8703 | *aLoadState->GetLoadingSessionHistoryInfo()); |
8704 | mNeedToReportActiveAfterLoadingBecomesActive = false; |
8705 | } |
8706 | |
8707 | // Set the doc's URI according to the new history entry's URI. |
8708 | doc->SetDocumentURI(newURI); |
8709 | |
8710 | /* This is a anchor traversal within the same page. |
8711 | * call OnNewURI() so that, this traversal will be |
8712 | * recorded in session and global history. |
8713 | */ |
8714 | nsCOMPtr<nsIPrincipal> newURITriggeringPrincipal, newURIPrincipalToInherit, |
8715 | newURIPartitionedPrincipalToInherit; |
8716 | nsCOMPtr<nsIContentSecurityPolicy> newCsp; |
8717 | if (mozilla::SessionHistoryInParent() ? !!mActiveEntry : !!mOSHE) { |
8718 | if (mozilla::SessionHistoryInParent()) { |
8719 | newURITriggeringPrincipal = mActiveEntry->GetTriggeringPrincipal(); |
8720 | newURIPrincipalToInherit = mActiveEntry->GetPrincipalToInherit(); |
8721 | newURIPartitionedPrincipalToInherit = |
8722 | mActiveEntry->GetPartitionedPrincipalToInherit(); |
8723 | newCsp = mActiveEntry->GetCsp(); |
8724 | } else { |
8725 | newURITriggeringPrincipal = mOSHE->GetTriggeringPrincipal(); |
8726 | newURIPrincipalToInherit = mOSHE->GetPrincipalToInherit(); |
8727 | newURIPartitionedPrincipalToInherit = |
8728 | mOSHE->GetPartitionedPrincipalToInherit(); |
8729 | newCsp = mOSHE->GetCsp(); |
8730 | } |
8731 | } else { |
8732 | newURITriggeringPrincipal = aLoadState->TriggeringPrincipal(); |
8733 | newURIPrincipalToInherit = doc->NodePrincipal(); |
8734 | newURIPartitionedPrincipalToInherit = doc->PartitionedPrincipal(); |
8735 | newCsp = doc->GetCsp(); |
8736 | } |
8737 | |
8738 | uint32_t locationChangeFlags = GetSameDocumentNavigationFlags(newURI); |
8739 | |
8740 | // Pass true for aCloneSHChildren, since we're not |
8741 | // changing documents here, so all of our subframes are |
8742 | // still relevant to the new session history entry. |
8743 | // |
8744 | // It also makes OnNewURI(...) set LOCATION_CHANGE_SAME_DOCUMENT |
8745 | // flag on firing onLocationChange(...). |
8746 | // Anyway, aCloneSHChildren param is simply reflecting |
8747 | // doSameDocumentNavigation in this scope. |
8748 | // |
8749 | // Note: we'll actually fire onLocationChange later, in order to preserve |
8750 | // ordering of HistoryCommit() in the parent vs onLocationChange (bug |
8751 | // 1668126) |
8752 | bool locationChangeNeeded = OnNewURI( |
8753 | newURI, nullptr, newURITriggeringPrincipal, newURIPrincipalToInherit, |
8754 | newURIPartitionedPrincipalToInherit, newCsp, true, true); |
8755 | |
8756 | nsCOMPtr<nsIInputStream> postData; |
8757 | nsCOMPtr<nsIReferrerInfo> referrerInfo; |
8758 | uint32_t cacheKey = 0; |
8759 | |
8760 | bool scrollRestorationIsManual = false; |
8761 | if (!mozilla::SessionHistoryInParent()) { |
8762 | if (mOSHE) { |
8763 | /* save current position of scroller(s) (bug 59774) */ |
8764 | mOSHE->SetScrollPosition(scrollPos.x, scrollPos.y); |
8765 | scrollRestorationIsManual = mOSHE->GetScrollRestorationIsManual(); |
8766 | // Get the postdata, page ident and referrer info from the current page, |
8767 | // if the new load is being done via normal means. Note that "normal |
8768 | // means" can be checked for just by checking for LOAD_CMD_NORMAL, given |
8769 | // the loadType and allowScroll check above -- it filters out some |
8770 | // LOAD_CMD_NORMAL cases that we wouldn't want here. |
8771 | if (aLoadState->LoadType() & LOAD_CMD_NORMAL) { |
8772 | postData = mOSHE->GetPostData(); |
8773 | cacheKey = mOSHE->GetCacheKey(); |
8774 | referrerInfo = mOSHE->GetReferrerInfo(); |
8775 | } |
8776 | |
8777 | // Link our new SHEntry to the old SHEntry's back/forward |
8778 | // cache data, since the two SHEntries correspond to the |
8779 | // same document. |
8780 | if (mLSHE) { |
8781 | if (!aLoadState->LoadIsFromSessionHistory()) { |
8782 | // If we're not doing a history load, scroll restoration |
8783 | // should be inherited from the previous session history entry. |
8784 | SetScrollRestorationIsManualOnHistoryEntry(mLSHE, |
8785 | scrollRestorationIsManual); |
8786 | } |
8787 | mLSHE->AdoptBFCacheEntry(mOSHE); |
8788 | } |
8789 | } |
8790 | } else { |
8791 | if (mActiveEntry) { |
8792 | mActiveEntry->SetScrollPosition(scrollPos.x, scrollPos.y); |
8793 | if (mBrowsingContext) { |
8794 | CollectWireframe(); |
8795 | if (XRE_IsParentProcess()) { |
8796 | SessionHistoryEntry* entry = |
8797 | mBrowsingContext->Canonical()->GetActiveSessionHistoryEntry(); |
8798 | if (entry) { |
8799 | entry->SetScrollPosition(scrollPos.x, scrollPos.y); |
8800 | } |
8801 | } else { |
8802 | mozilla::Unused << ContentChild::GetSingleton() |
8803 | ->SendSessionHistoryEntryScrollPosition( |
8804 | mBrowsingContext, scrollPos.x, |
8805 | scrollPos.y); |
8806 | } |
8807 | } |
8808 | } |
8809 | if (mLoadingEntry) { |
8810 | if (!mLoadingEntry->mLoadIsFromSessionHistory) { |
8811 | // If we're not doing a history load, scroll restoration |
8812 | // should be inherited from the previous session history entry. |
8813 | // XXX This needs most probably tweaks once fragment navigation is |
8814 | // fixed to work with session-history-in-parent. |
8815 | SetScrollRestorationIsManualOnHistoryEntry(nullptr, |
8816 | scrollRestorationIsManual); |
8817 | } |
8818 | } |
8819 | } |
8820 | |
8821 | // If we're doing a history load, use its scroll restoration state. |
8822 | if (aLoadState->LoadIsFromSessionHistory()) { |
8823 | if (mozilla::SessionHistoryInParent()) { |
8824 | scrollRestorationIsManual = aLoadState->GetLoadingSessionHistoryInfo() |
8825 | ->mInfo.GetScrollRestorationIsManual(); |
8826 | } else { |
8827 | scrollRestorationIsManual = |
8828 | aLoadState->SHEntry()->GetScrollRestorationIsManual(); |
8829 | } |
8830 | } |
8831 | |
8832 | /* Assign mLSHE to mOSHE. This will either be a new entry created |
8833 | * by OnNewURI() for normal loads or aLoadState->SHEntry() for history |
8834 | * loads. |
8835 | */ |
8836 | if (!mozilla::SessionHistoryInParent()) { |
8837 | if (mLSHE) { |
8838 | SetHistoryEntryAndUpdateBC(Nothing(), Some<nsISHEntry*>(mLSHE)); |
8839 | // Save the postData obtained from the previous page |
8840 | // in to the session history entry created for the |
8841 | // anchor page, so that any history load of the anchor |
8842 | // page will restore the appropriate postData. |
8843 | if (postData) { |
8844 | mOSHE->SetPostData(postData); |
8845 | } |
8846 | |
8847 | // Make sure we won't just repost without hitting the |
8848 | // cache first |
8849 | if (cacheKey != 0) { |
8850 | mOSHE->SetCacheKey(cacheKey); |
8851 | } |
8852 | |
8853 | // As the document has not changed, the referrer info hasn't changed too, |
8854 | // so we can just copy it over. |
8855 | if (referrerInfo) { |
8856 | mOSHE->SetReferrerInfo(referrerInfo); |
8857 | } |
8858 | } |
8859 | |
8860 | /* Set the title for the SH entry for this target url so that |
8861 | * SH menus in go/back/forward buttons won't be empty for this. |
8862 | * Note, this happens on mOSHE (and mActiveEntry in the future) because of |
8863 | * the code above. |
8864 | * Note, when session history lives in the parent process, this does not |
8865 | * update the title there. |
8866 | */ |
8867 | SetTitleOnHistoryEntry(false); |
8868 | } else { |
8869 | if (aLoadState->LoadIsFromSessionHistory()) { |
8870 | 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) |
8871 | 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) |
8872 | ("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) |
8873 | "%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) |
8874 | 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); |
8875 | |
8876 | nsCOMPtr<nsILayoutHistoryState> currentLayoutHistoryState; |
8877 | if (mActiveEntry) { |
8878 | currentLayoutHistoryState = mActiveEntry->GetLayoutHistoryState(); |
8879 | } |
8880 | |
8881 | UniquePtr<SessionHistoryInfo> previousActiveEntry(mActiveEntry.release()); |
8882 | mActiveEntry = MakeUnique<SessionHistoryInfo>(mLoadingEntry->mInfo); |
8883 | if (currentLayoutHistoryState) { |
8884 | // Restore the existing nsILayoutHistoryState object, since it is |
8885 | // possibly being used by the layout. When doing a new load, the |
8886 | // shared state is copied from the existing active entry, so this |
8887 | // special case is needed only with the history loads. |
8888 | mActiveEntry->SetLayoutHistoryState(currentLayoutHistoryState); |
8889 | } |
8890 | |
8891 | if (cacheKey != 0) { |
8892 | mActiveEntry->SetCacheKey(cacheKey); |
8893 | } |
8894 | // We're passing in mCurrentURI, which could be null. SessionHistoryCommit |
8895 | // does require a non-null uri if this is for a refresh load of the same |
8896 | // URI, but in that case mCurrentURI won't be null here. |
8897 | mBrowsingContext->SessionHistoryCommit( |
8898 | *mLoadingEntry, mLoadType, mCurrentURI, previousActiveEntry.get(), |
8899 | true, true, |
8900 | /* No expiration update on the same document loads*/ |
8901 | false, cacheKey); |
8902 | // FIXME Need to set postdata. |
8903 | |
8904 | // Set the title for the SH entry for this target url so that |
8905 | // SH menus in go/back/forward buttons won't be empty for this. |
8906 | // Note, when session history lives in the parent process, this does not |
8907 | // update the title there. |
8908 | SetTitleOnHistoryEntry(false); |
8909 | } else { |
8910 | Maybe<bool> scrollRestorationIsManual; |
8911 | if (mActiveEntry) { |
8912 | scrollRestorationIsManual.emplace( |
8913 | mActiveEntry->GetScrollRestorationIsManual()); |
8914 | |
8915 | // Get the postdata, page ident and referrer info from the current page, |
8916 | // if the new load is being done via normal means. Note that "normal |
8917 | // means" can be checked for just by checking for LOAD_CMD_NORMAL, given |
8918 | // the loadType and allowScroll check above -- it filters out some |
8919 | // LOAD_CMD_NORMAL cases that we wouldn't want here. |
8920 | if (aLoadState->LoadType() & LOAD_CMD_NORMAL) { |
8921 | postData = mActiveEntry->GetPostData(); |
8922 | cacheKey = mActiveEntry->GetCacheKey(); |
8923 | referrerInfo = mActiveEntry->GetReferrerInfo(); |
8924 | } |
8925 | } |
8926 | |
8927 | 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) |
8928 | ("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) |
8929 | 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); |
8930 | if (mActiveEntry) { |
8931 | mActiveEntry = MakeUnique<SessionHistoryInfo>(*mActiveEntry, newURI); |
8932 | } else { |
8933 | mActiveEntry = MakeUnique<SessionHistoryInfo>( |
8934 | newURI, newURITriggeringPrincipal, newURIPrincipalToInherit, |
8935 | newURIPartitionedPrincipalToInherit, newCsp, mContentTypeHint); |
8936 | } |
8937 | |
8938 | // Save the postData obtained from the previous page in to the session |
8939 | // history entry created for the anchor page, so that any history load of |
8940 | // the anchor page will restore the appropriate postData. |
8941 | if (postData) { |
8942 | mActiveEntry->SetPostData(postData); |
8943 | } |
8944 | |
8945 | // Make sure we won't just repost without hitting the |
8946 | // cache first |
8947 | if (cacheKey != 0) { |
8948 | mActiveEntry->SetCacheKey(cacheKey); |
8949 | } |
8950 | |
8951 | // As the document has not changed, the referrer info hasn't changed too, |
8952 | // so we can just copy it over. |
8953 | if (referrerInfo) { |
8954 | mActiveEntry->SetReferrerInfo(referrerInfo); |
8955 | } |
8956 | |
8957 | // Set the title for the SH entry for this target url so that |
8958 | // SH menus in go/back/forward buttons won't be empty for this. |
8959 | mActiveEntry->SetTitle(mTitle); |
8960 | |
8961 | if (scrollRestorationIsManual.isSome()) { |
8962 | mActiveEntry->SetScrollRestorationIsManual( |
8963 | scrollRestorationIsManual.value()); |
8964 | } |
8965 | |
8966 | if (LOAD_TYPE_HAS_FLAGS(mLoadType, LOAD_FLAGS_REPLACE_HISTORY)((mLoadType) & ((LOAD_FLAGS_REPLACE_HISTORY) << 16) )) { |
8967 | mBrowsingContext->ReplaceActiveSessionHistoryEntry(mActiveEntry.get()); |
8968 | } else { |
8969 | mBrowsingContext->IncrementHistoryEntryCountForBrowsingContext(); |
8970 | // FIXME We should probably just compute mChildOffset in the parent |
8971 | // instead of passing it over IPC here. |
8972 | mBrowsingContext->SetActiveSessionHistoryEntry( |
8973 | Some(scrollPos), mActiveEntry.get(), mLoadType, cacheKey); |
8974 | // FIXME Do we need to update mPreviousEntryIndex and mLoadedEntryIndex? |
8975 | } |
8976 | } |
8977 | } |
8978 | |
8979 | if (locationChangeNeeded) { |
8980 | FireOnLocationChange(this, nullptr, newURI, locationChangeFlags); |
8981 | } |
8982 | |
8983 | /* Restore the original LSHE if we were loading something |
8984 | * while same document navigation was initiated. |
8985 | */ |
8986 | SetHistoryEntryAndUpdateBC(Some<nsISHEntry*>(oldLSHE), Nothing()); |
8987 | mLoadingEntry.swap(oldLoadingEntry); |
8988 | |
8989 | /* Set the title for the Global History entry for this anchor url. |
8990 | */ |
8991 | UpdateGlobalHistoryTitle(newURI); |
8992 | |
8993 | SetDocCurrentStateObj(mOSHE, mActiveEntry.get()); |
8994 | |
8995 | // Inform the favicon service that the favicon for oldURI also |
8996 | // applies to newURI. |
8997 | CopyFavicon(currentURI, newURI, UsePrivateBrowsing()); |
8998 | |
8999 | RefPtr<nsGlobalWindowOuter> scriptGlobal = mScriptGlobal; |
9000 | nsCOMPtr<nsPIDOMWindowInner> win = |
9001 | scriptGlobal ? scriptGlobal->GetCurrentInnerWindow() : nullptr; |
9002 | |
9003 | // ScrollToAnchor doesn't necessarily cause us to scroll the window; |
9004 | // the function decides whether a scroll is appropriate based on the |
9005 | // arguments it receives. But even if we don't end up scrolling, |
9006 | // ScrollToAnchor performs other important tasks, such as informing |
9007 | // the presShell that we have a new hash. See bug 680257. |
9008 | nsresult rv = ScrollToAnchor(aState.mCurrentURIHasRef, aState.mNewURIHasRef, |
9009 | aState.mNewHash, aLoadState->LoadType()); |
9010 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 9010); return rv; } } while (false); |
9011 | |
9012 | /* restore previous position of scroller(s), if we're moving |
9013 | * back in history (bug 59774) |
9014 | */ |
9015 | nscoord bx = 0; |
9016 | nscoord by = 0; |
9017 | bool needsScrollPosUpdate = false; |
9018 | if ((mozilla::SessionHistoryInParent() ? !!mActiveEntry : !!mOSHE) && |
9019 | (aLoadState->LoadType() == LOAD_HISTORY || |
9020 | aLoadState->LoadType() == LOAD_RELOAD_NORMAL) && |
9021 | !scrollRestorationIsManual) { |
9022 | needsScrollPosUpdate = true; |
9023 | if (mozilla::SessionHistoryInParent()) { |
9024 | mActiveEntry->GetScrollPosition(&bx, &by); |
9025 | } else { |
9026 | mOSHE->GetScrollPosition(&bx, &by); |
9027 | } |
9028 | } |
9029 | |
9030 | // Dispatch the popstate and hashchange events, as appropriate. |
9031 | // |
9032 | // The event dispatch below can cause us to re-enter script and |
9033 | // destroy the docshell, nulling out mScriptGlobal. Hold a stack |
9034 | // reference to avoid null derefs. See bug 914521. |
9035 | if (win) { |
9036 | // Fire a hashchange event URIs differ, and only in their hashes. |
9037 | bool doHashchange = aState.mSameExceptHashes && |
9038 | (aState.mCurrentURIHasRef != aState.mNewURIHasRef || |
9039 | !aState.mCurrentHash.Equals(aState.mNewHash)); |
9040 | |
9041 | if (aState.mHistoryNavBetweenSameDoc || doHashchange) { |
9042 | win->DispatchSyncPopState(); |
9043 | } |
9044 | |
9045 | if (needsScrollPosUpdate && win->HasActiveDocument()) { |
9046 | SetCurScrollPosEx(bx, by); |
9047 | } |
9048 | |
9049 | if (doHashchange) { |
9050 | // Note that currentURI hasn't changed because it's on the |
9051 | // stack, so we can just use it directly as the old URI. |
9052 | win->DispatchAsyncHashchange(currentURI, newURI); |
9053 | } |
9054 | } |
9055 | |
9056 | return NS_OK; |
9057 | } |
9058 | |
9059 | static bool NavigationShouldTakeFocus(nsDocShell* aDocShell, |
9060 | nsDocShellLoadState* aLoadState) { |
9061 | if (!aLoadState->AllowFocusMove()) { |
9062 | return false; |
9063 | } |
9064 | if (!aLoadState->HasValidUserGestureActivation()) { |
9065 | return false; |
9066 | } |
9067 | const auto& sourceBC = aLoadState->SourceBrowsingContext(); |
9068 | if (!sourceBC || !sourceBC->IsActive()) { |
9069 | // If the navigation didn't come from a foreground tab, then we don't steal |
9070 | // focus. |
9071 | return false; |
9072 | } |
9073 | auto* bc = aDocShell->GetBrowsingContext(); |
9074 | if (sourceBC.get() == bc) { |
9075 | // If it comes from the same tab / frame, don't steal focus either. |
9076 | return false; |
9077 | } |
9078 | auto* fm = nsFocusManager::GetFocusManager(); |
9079 | if (fm && bc->IsActive() && fm->IsInActiveWindow(bc)) { |
9080 | // If we're already on the foreground tab of the foreground window, then we |
9081 | // don't need to do this. This helps to e.g. not steal focus from the |
9082 | // browser chrome unnecessarily. |
9083 | return false; |
9084 | } |
9085 | if (auto* doc = aDocShell->GetExtantDocument()) { |
9086 | if (doc->IsInitialDocument()) { |
9087 | // If we're the initial load for the browsing context, the browser |
9088 | // chrome determines what to focus. This is important because the |
9089 | // browser chrome may want to e.g focus the url-bar |
9090 | return false; |
9091 | } |
9092 | } |
9093 | // Take loadDivertedInBackground into account so the behavior would be the |
9094 | // same as how the tab first opened. |
9095 | return !Preferences::GetBool("browser.tabs.loadDivertedInBackground", false); |
9096 | } |
9097 | |
9098 | uint32_t nsDocShell::GetLoadTypeForFormSubmission( |
9099 | BrowsingContext* aTargetBC, nsDocShellLoadState* aLoadState) { |
9100 | 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()", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 9100); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->IsFormSubmission()" ")"); do { *((volatile int*)__null) = 9100; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
9101 | |
9102 | // https://html.spec.whatwg.org/#form-submission-algorithm |
9103 | // 22. Let historyHandling be "push". |
9104 | // 23. If form document equals targetNavigable's active document, and |
9105 | // form document has not yet completely loaded, then set |
9106 | // historyHandling to "replace". |
9107 | return GetBrowsingContext() == aTargetBC && !mEODForCurrentDocument |
9108 | ? LOAD_NORMAL_REPLACE |
9109 | : LOAD_LINK; |
9110 | } |
9111 | |
9112 | nsresult nsDocShell::InternalLoad(nsDocShellLoadState* aLoadState, |
9113 | Maybe<uint32_t> aCacheKey) { |
9114 | 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!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 9114); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState" ") (" "need a load state!" ")"); do { *((volatile int*)__null ) = 9114; __attribute__((nomerge)) ::abort(); } while (false) ; } } while (false); |
9115 | 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 9116); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->TriggeringPrincipal()" ") (" "need a valid TriggeringPrincipal" ")"); do { *((volatile int*)__null) = 9116; __attribute__((nomerge)) ::abort(); } while (false); } } while (false) |
9116 | "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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 9116); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->TriggeringPrincipal()" ") (" "need a valid TriggeringPrincipal" ")"); do { *((volatile int*)__null) = 9116; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
9117 | |
9118 | if (!aLoadState->TriggeringPrincipal()) { |
9119 | 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 9119); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "InternalLoad needs a valid triggeringPrincipal" ")"); do { * ((volatile int*)__null) = 9119; __attribute__((nomerge)) ::abort (); } while (false); } } while (false); |
9120 | return NS_ERROR_FAILURE; |
9121 | } |
9122 | if (NS_WARN_IF(mBrowsingContext->GetPendingInitialization())NS_warn_if_impl(mBrowsingContext->GetPendingInitialization (), "mBrowsingContext->GetPendingInitialization()", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 9122)) { |
9123 | return NS_ERROR_NOT_AVAILABLE; |
9124 | } |
9125 | |
9126 | const bool shouldTakeFocus = NavigationShouldTakeFocus(this, aLoadState); |
9127 | |
9128 | mOriginalUriString.Truncate(); |
9129 | |
9130 | 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) |
9131 | ("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) |
9132 | 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); |
9133 | |
9134 | 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 , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 9134); return NS_ERROR_INVALID_ARG; } } while (false); |
9135 | |
9136 | // Cancel loads coming from Docshells that are being destroyed. |
9137 | if (mIsBeingDestroyed) { |
9138 | return NS_ERROR_NOT_AVAILABLE; |
9139 | } |
9140 | |
9141 | nsresult rv = EnsureScriptEnvironment(); |
9142 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
9143 | return rv; |
9144 | } |
9145 | |
9146 | // If we have a target to move to, do that now. |
9147 | if (!aLoadState->Target().IsEmpty()) { |
9148 | return PerformRetargeting(aLoadState); |
9149 | } |
9150 | |
9151 | // This is the non-retargeting load path, we've already set the right loadtype |
9152 | // for form submissions in nsDocShell::OnLinkClickSync. |
9153 | if (aLoadState->TargetBrowsingContext().IsNull()) { |
9154 | aLoadState->SetTargetBrowsingContext(GetBrowsingContext()); |
9155 | } |
9156 | |
9157 | 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 9159); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "aLoadState->TargetBrowsingContext() == GetBrowsingContext()" ") (" "Load must be targeting this BrowsingContext" ")"); do { *((volatile int*)__null) = 9159; __attribute__((nomerge)) :: abort(); } while (false); } } while (false) |
9158 | 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 9159); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "aLoadState->TargetBrowsingContext() == GetBrowsingContext()" ") (" "Load must be targeting this BrowsingContext" ")"); do { *((volatile int*)__null) = 9159; __attribute__((nomerge)) :: abort(); } while (false); } } while (false) |
9159 | "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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 9159); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "aLoadState->TargetBrowsingContext() == GetBrowsingContext()" ") (" "Load must be targeting this BrowsingContext" ")"); do { *((volatile int*)__null) = 9159; __attribute__((nomerge)) :: abort(); } while (false); } } while (false); |
9160 | |
9161 | MOZ_TRY(CheckDisallowedJavascriptLoad(aLoadState))do { auto mozTryTempResult_ = ::mozilla::ToResult(CheckDisallowedJavascriptLoad (aLoadState)); if ((__builtin_expect(!!(mozTryTempResult_.isErr ()), 0))) { return mozTryTempResult_.propagateErr(); } } while (0); |
9162 | |
9163 | // If we don't have a target, we're loading into ourselves, and our load |
9164 | // delegate may want to intercept that load. |
9165 | SameDocumentNavigationState sameDocumentNavigationState; |
9166 | bool sameDocument = |
9167 | IsSameDocumentNavigation(aLoadState, sameDocumentNavigationState) && |
9168 | !aLoadState->GetPendingRedirectedChannel(); |
9169 | |
9170 | // Note: We do this check both here and in BrowsingContext:: |
9171 | // LoadURI/InternalLoad, since document-specific sandbox flags are only |
9172 | // available in the process triggering the load, and we don't want the target |
9173 | // process to have to trust the triggering process to do the appropriate |
9174 | // checks for the BrowsingContext's sandbox flags. |
9175 | MOZ_TRY(mBrowsingContext->CheckSandboxFlags(aLoadState))do { auto mozTryTempResult_ = ::mozilla::ToResult(mBrowsingContext ->CheckSandboxFlags(aLoadState)); if ((__builtin_expect(!! (mozTryTempResult_.isErr()), 0))) { return mozTryTempResult_. propagateErr(); } } while (0); |
9176 | |
9177 | NS_ENSURE_STATE(!HasUnloadedParent())do { if ((__builtin_expect(!!(!(!HasUnloadedParent())), 0))) { NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "!HasUnloadedParent()" ") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 9177); return NS_ERROR_UNEXPECTED; } } while (false); |
9178 | |
9179 | rv = CheckLoadingPermissions(); |
9180 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
9181 | return rv; |
9182 | } |
9183 | |
9184 | if (mFiredUnloadEvent) { |
9185 | if (IsOKToLoadURI(aLoadState->URI())) { |
9186 | 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!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 9187); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->Target().IsEmpty()" ") (" "Shouldn't have a window target here!" ")"); do { *((volatile int*)__null) = 9187; __attribute__((nomerge)) ::abort(); } while (false); } } while (false) |
9187 | "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!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 9187); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->Target().IsEmpty()" ") (" "Shouldn't have a window target here!" ")"); do { *((volatile int*)__null) = 9187; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
9188 | |
9189 | // If this is a replace load, make whatever load triggered |
9190 | // the unload event also a replace load, so we don't |
9191 | // create extra history entries. |
9192 | if (LOAD_TYPE_HAS_FLAGS(aLoadState->LoadType(),((aLoadState->LoadType()) & ((LOAD_FLAGS_REPLACE_HISTORY ) << 16)) |
9193 | LOAD_FLAGS_REPLACE_HISTORY)((aLoadState->LoadType()) & ((LOAD_FLAGS_REPLACE_HISTORY ) << 16))) { |
9194 | mLoadType = LOAD_NORMAL_REPLACE; |
9195 | } |
9196 | |
9197 | // Do this asynchronously |
9198 | nsCOMPtr<nsIRunnable> ev = new InternalLoadEvent(this, aLoadState); |
9199 | return Dispatch(ev.forget()); |
9200 | } |
9201 | |
9202 | // Just ignore this load attempt |
9203 | return NS_OK; |
9204 | } |
9205 | |
9206 | // If we are loading a URI that should inherit a security context (basically |
9207 | // javascript: at this point), and the caller has said that principal |
9208 | // inheritance is allowed, there are a few possible cases: |
9209 | // |
9210 | // 1) We are provided with the principal to inherit. In that case, we just use |
9211 | // it. |
9212 | // |
9213 | // 2) The load is coming from some other application. In this case we don't |
9214 | // want to inherit from whatever document we have loaded now, since the |
9215 | // load is unrelated to it. |
9216 | // |
9217 | // 3) It's a load from our application, but does not provide an explicit |
9218 | // principal to inherit. In that case, we want to inherit the principal of |
9219 | // our current document, or of our parent document (if any) if we don't |
9220 | // have a current document. |
9221 | { |
9222 | bool inherits; |
9223 | |
9224 | if (!aLoadState->HasLoadFlags(LOAD_FLAGS_FROM_EXTERNAL) && |
9225 | !aLoadState->PrincipalToInherit() && |
9226 | (aLoadState->HasInternalLoadFlags( |
9227 | INTERNAL_LOAD_FLAGS_INHERIT_PRINCIPAL)) && |
9228 | NS_SUCCEEDED(nsContentUtils::URIInheritsSecurityContext(((bool)(__builtin_expect(!!(!NS_FAILED_impl(nsContentUtils::URIInheritsSecurityContext ( aLoadState->URI(), &inherits))), 1))) |
9229 | aLoadState->URI(), &inherits))((bool)(__builtin_expect(!!(!NS_FAILED_impl(nsContentUtils::URIInheritsSecurityContext ( aLoadState->URI(), &inherits))), 1))) && |
9230 | inherits) { |
9231 | aLoadState->SetPrincipalToInherit(GetInheritedPrincipal(true)); |
9232 | } |
9233 | // If principalToInherit is still null (e.g. if some of the conditions of |
9234 | // were not satisfied), then no inheritance of any sort will happen: the |
9235 | // load will just get a principal based on the URI being loaded. |
9236 | } |
9237 | |
9238 | // If this docshell is owned by a frameloader, make sure to cancel |
9239 | // possible frameloader initialization before loading a new page. |
9240 | nsCOMPtr<nsIDocShellTreeItem> parent = GetInProcessParentDocshell(); |
9241 | if (parent) { |
9242 | RefPtr<Document> doc = parent->GetDocument(); |
9243 | if (doc) { |
9244 | doc->TryCancelFrameLoaderInitialization(this); |
9245 | } |
9246 | } |
9247 | |
9248 | // Before going any further vet loads initiated by external programs. |
9249 | if (aLoadState->HasLoadFlags(LOAD_FLAGS_FROM_EXTERNAL)) { |
9250 | 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" , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 9250); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "aLoadState->LoadType() == LOAD_NORMAL" ")"); do { *((volatile int*)__null) = 9250; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
9251 | |
9252 | // Disallow external chrome: loads targetted at content windows |
9253 | if (SchemeIsChrome(aLoadState->URI())) { |
9254 | NS_WARNING("blocked external chrome: url -- use '--chrome' option")NS_DebugBreak(NS_DEBUG_WARNING, "blocked external chrome: url -- use '--chrome' option" , nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 9254); |
9255 | return NS_ERROR_FAILURE; |
9256 | } |
9257 | |
9258 | // clear the decks to prevent context bleed-through (bug 298255) |
9259 | rv = CreateAboutBlankDocumentViewer(nullptr, nullptr, nullptr, nullptr, |
9260 | /* aIsInitialDocument */ false); |
9261 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
9262 | return NS_ERROR_FAILURE; |
9263 | } |
9264 | } |
9265 | |
9266 | mAllowKeywordFixup = aLoadState->HasInternalLoadFlags( |
9267 | INTERNAL_LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP); |
9268 | mURIResultedInDocument = false; // reset the clock... |
9269 | |
9270 | // See if this is actually a load between two history entries for the same |
9271 | // document. If the process fails, or if we successfully navigate within the |
9272 | // same document, return. |
9273 | if (sameDocument) { |
9274 | nsresult rv = HandleSameDocumentNavigation( |
9275 | aLoadState, sameDocumentNavigationState, sameDocument); |
9276 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 9276); return rv; } } while (false); |
9277 | if (shouldTakeFocus) { |
9278 | mBrowsingContext->Focus(CallerType::System, IgnoreErrors()); |
9279 | } |
9280 | if (sameDocument) { |
9281 | return rv; |
9282 | } |
9283 | } |
9284 | |
9285 | // mDocumentViewer->PermitUnload can destroy |this| docShell, which |
9286 | // causes the next call of CanSavePresentation to crash. |
9287 | // Hold onto |this| until we return, to prevent a crash from happening. |
9288 | // (bug#331040) |
9289 | nsCOMPtr<nsIDocShell> kungFuDeathGrip(this); |
9290 | |
9291 | // Don't init timing for javascript:, since it generally doesn't |
9292 | // actually start a load or anything. If it does, we'll init |
9293 | // timing then, from OnStateChange. |
9294 | |
9295 | // XXXbz mTiming should know what channel it's for, so we don't |
9296 | // need this hackery. |
9297 | const bool isJavaScript = SchemeIsJavascript(aLoadState->URI()); |
9298 | const bool isExternalProtocol = |
9299 | nsContentUtils::IsExternalProtocol(aLoadState->URI()); |
9300 | const bool isDownload = !aLoadState->FileName().IsVoid(); |
9301 | const bool toBeReset = !isJavaScript && MaybeInitTiming(); |
9302 | |
9303 | // FIXME(emilio): Should this be done by javascript: uris? What about external |
9304 | // protocols? |
9305 | if (mTiming && !isDownload) { |
9306 | mTiming->NotifyBeforeUnload(); |
9307 | } |
9308 | // Check if the page doesn't want to be unloaded. The javascript: |
9309 | // protocol handler deals with this for javascript: URLs. |
9310 | // NOTE(emilio): As of this writing, other browsers fire beforeunload for |
9311 | // external protocols, so keep doing that even though they don't return data |
9312 | // and thus we won't really unload this... |
9313 | if (!isJavaScript && !isDownload && |
9314 | !aLoadState->NotifiedBeforeUnloadListeners() && mDocumentViewer) { |
9315 | // Check if request is exempted from HTTPSOnlyMode and if https-first is |
9316 | // enabled, if so it means: |
9317 | // * https-first failed to upgrade request to https |
9318 | // * we already asked for permission to unload and the user accepted |
9319 | // otherwise we wouldn't be here. |
9320 | const bool isPrivateWin = GetOriginAttributes().IsPrivateBrowsing(); |
9321 | const uint32_t loadType = aLoadState->LoadType(); |
9322 | |
9323 | // Check if request is a reload. |
9324 | const bool isHistoryOrReload = |
9325 | loadType == LOAD_RELOAD_NORMAL || |
9326 | loadType == LOAD_RELOAD_BYPASS_CACHE || |
9327 | loadType == LOAD_RELOAD_BYPASS_PROXY || |
9328 | loadType == LOAD_RELOAD_BYPASS_PROXY_AND_CACHE || |
9329 | loadType == LOAD_HISTORY; |
9330 | |
9331 | // If it isn't a reload, the request already failed to be upgraded and |
9332 | // https-first is enabled then don't ask the user again for permission to |
9333 | // unload and just unload. |
9334 | bool okToUnload; |
9335 | if (!isHistoryOrReload && aLoadState->IsExemptFromHTTPSFirstMode() && |
9336 | nsHTTPSOnlyUtils::IsHttpsFirstModeEnabled(isPrivateWin)) { |
9337 | rv = mDocumentViewer->PermitUnload( |
9338 | nsIDocumentViewer::PermitUnloadAction::eDontPromptAndUnload, |
9339 | &okToUnload); |
9340 | } else { |
9341 | rv = mDocumentViewer->PermitUnload(&okToUnload); |
9342 | } |
9343 | |
9344 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && !okToUnload) { |
9345 | // The user chose not to unload the page, interrupt the |
9346 | // load. |
9347 | MaybeResetInitTiming(toBeReset); |
9348 | return NS_OK; |
9349 | } |
9350 | } |
9351 | |
9352 | if (mTiming && !isDownload) { |
9353 | mTiming->NotifyUnloadAccepted(mCurrentURI); |
9354 | } |
9355 | |
9356 | // In e10s, in the parent process, we refuse to load anything other than |
9357 | // "safe" resources that we ship or trust enough to give "special" URLs. |
9358 | // Similar check will be performed by the ParentProcessDocumentChannel if in |
9359 | // use. |
9360 | if (XRE_IsE10sParentProcess() && |
9361 | !DocumentChannel::CanUseDocumentChannel(aLoadState->URI()) && |
9362 | !CanLoadInParentProcess(aLoadState->URI())) { |
9363 | return NS_ERROR_FAILURE; |
9364 | } |
9365 | |
9366 | // Whenever a top-level browsing context is navigated, the user agent MUST |
9367 | // lock the orientation of the document to the document's default |
9368 | // orientation. We don't explicitly check for a top-level browsing context |
9369 | // here because orientation is only set on top-level browsing contexts. |
9370 | if (mBrowsingContext->GetOrientationLock() != hal::ScreenOrientation::None) { |
9371 | 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()", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 9371); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mBrowsingContext->IsTop()" ")"); do { *((volatile int*)__null) = 9371; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
9372 | MOZ_ALWAYS_SUCCEEDS(do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl (mBrowsingContext->SetOrientationLock(hal::ScreenOrientation ::None))), 1)))), 1))) { } else { do { static_assert( mozilla ::detail::AssertionConditionType<decltype(false)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(false))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("false" " (" "NS_SUCCEEDED(mBrowsingContext->SetOrientationLock(hal::ScreenOrientation::None))" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 9373); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false" ") (" "NS_SUCCEEDED(mBrowsingContext->SetOrientationLock(hal::ScreenOrientation::None))" ")"); do { *((volatile int*)__null) = 9373; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) |
9373 | mBrowsingContext->SetOrientationLock(hal::ScreenOrientation::None))do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl (mBrowsingContext->SetOrientationLock(hal::ScreenOrientation ::None))), 1)))), 1))) { } else { do { static_assert( mozilla ::detail::AssertionConditionType<decltype(false)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(false))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("false" " (" "NS_SUCCEEDED(mBrowsingContext->SetOrientationLock(hal::ScreenOrientation::None))" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 9373); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false" ") (" "NS_SUCCEEDED(mBrowsingContext->SetOrientationLock(hal::ScreenOrientation::None))" ")"); do { *((volatile int*)__null) = 9373; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); |
9374 | if (mBrowsingContext->IsActive()) { |
9375 | ScreenOrientation::UpdateActiveOrientationLock( |
9376 | hal::ScreenOrientation::None); |
9377 | } |
9378 | } |
9379 | |
9380 | // Check for saving the presentation here, before calling Stop(). |
9381 | // This is necessary so that we can catch any pending requests. |
9382 | // Since the new request has not been created yet, we pass null for the |
9383 | // new request parameter. |
9384 | // Also pass nullptr for the document, since it doesn't affect the return |
9385 | // value for our purposes here. |
9386 | const bool savePresentation = |
9387 | CanSavePresentation(aLoadState->LoadType(), nullptr, nullptr, |
9388 | /* aReportBFCacheComboTelemetry */ true); |
9389 | |
9390 | // nsDocShell::CanSavePresentation is for non-SHIP version only. Do a |
9391 | // separate check for SHIP so that we know if there are ongoing requests |
9392 | // before calling Stop() below. |
9393 | if (mozilla::SessionHistoryInParent()) { |
9394 | Document* document = GetDocument(); |
9395 | uint32_t flags = 0; |
9396 | if (document && !document->CanSavePresentation(nullptr, flags, true)) { |
9397 | // This forces some flags into the WindowGlobalParent's mBFCacheStatus, |
9398 | // which we'll then use in CanonicalBrowsingContext::AllowedInBFCache, |
9399 | // and in particular we'll store BFCacheStatus::REQUEST if needed. |
9400 | // Also, we want to report all the flags to the parent process here (and |
9401 | // not just BFCacheStatus::NOT_ALLOWED), so that it can update the |
9402 | // telemetry data correctly. |
9403 | document->DisallowBFCaching(flags); |
9404 | } |
9405 | } |
9406 | |
9407 | // Don't stop current network activity for javascript: URL's since they might |
9408 | // not result in any data, and thus nothing should be stopped in those cases. |
9409 | // In the case where they do result in data, the javascript: URL channel takes |
9410 | // care of stopping current network activity. Similarly, downloads don't |
9411 | // unload this document... |
9412 | if (!isJavaScript && !isDownload && !isExternalProtocol) { |
9413 | // Stop any current network activity. |
9414 | // Also stop content if this is a zombie doc. otherwise |
9415 | // the onload will be delayed by other loads initiated in the |
9416 | // background by the first document that |
9417 | // didn't fully load before the next load was initiated. |
9418 | // If not a zombie, don't stop content until data |
9419 | // starts arriving from the new URI... |
9420 | if ((mDocumentViewer && mDocumentViewer->GetPreviousViewer()) || |
9421 | LOAD_TYPE_HAS_FLAGS(aLoadState->LoadType(), LOAD_FLAGS_STOP_CONTENT)((aLoadState->LoadType()) & ((LOAD_FLAGS_STOP_CONTENT) << 16))) { |
9422 | rv = Stop(nsIWebNavigation::STOP_ALL); |
9423 | } else { |
9424 | rv = Stop(nsIWebNavigation::STOP_NETWORK); |
9425 | } |
9426 | |
9427 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
9428 | return rv; |
9429 | } |
9430 | } |
9431 | |
9432 | mLoadType = aLoadState->LoadType(); |
9433 | |
9434 | // aLoadState->SHEntry() should be assigned to mLSHE, only after Stop() has |
9435 | // been called. But when loading an error page, do not clear the |
9436 | // mLSHE for the real page. |
9437 | if (mLoadType != LOAD_ERROR_PAGE) { |
9438 | SetHistoryEntryAndUpdateBC(Some<nsISHEntry*>(aLoadState->SHEntry()), |
9439 | Nothing()); |
9440 | if (aLoadState->LoadIsFromSessionHistory() && |
9441 | !mozilla::SessionHistoryInParent()) { |
9442 | // We're making history navigation or a reload. Make sure our history ID |
9443 | // points to the same ID as SHEntry's docshell ID. |
9444 | nsID historyID = {}; |
9445 | aLoadState->SHEntry()->GetDocshellID(historyID); |
9446 | |
9447 | Unused << mBrowsingContext->SetHistoryID(historyID); |
9448 | } |
9449 | } |
9450 | |
9451 | mSavingOldViewer = savePresentation; |
9452 | |
9453 | // If we have a saved content viewer in history, restore and show it now. |
9454 | if (aLoadState->LoadIsFromSessionHistory() && |
9455 | (mLoadType & LOAD_CMD_HISTORY)) { |
9456 | // https://html.spec.whatwg.org/#history-traversal: |
9457 | // To traverse the history |
9458 | // "If entry has a different Document object than the current entry, then |
9459 | // run the following substeps: Remove any tasks queued by the history |
9460 | // traversal task source..." |
9461 | // Same document object case was handled already above with |
9462 | // HandleSameDocumentNavigation call. |
9463 | RefPtr<ChildSHistory> shistory = GetRootSessionHistory(); |
9464 | if (shistory) { |
9465 | shistory->RemovePendingHistoryNavigations(); |
9466 | } |
9467 | if (!mozilla::SessionHistoryInParent()) { |
9468 | // It's possible that the previous viewer of mDocumentViewer is the |
9469 | // viewer that will end up in aLoadState->SHEntry() when it gets closed. |
9470 | // If that's the case, we need to go ahead and force it into its shentry |
9471 | // so we can restore it. |
9472 | if (mDocumentViewer) { |
9473 | nsCOMPtr<nsIDocumentViewer> prevViewer = |
9474 | mDocumentViewer->GetPreviousViewer(); |
9475 | if (prevViewer) { |
9476 | #ifdef DEBUG1 |
9477 | nsCOMPtr<nsIDocumentViewer> prevPrevViewer = |
9478 | prevViewer->GetPreviousViewer(); |
9479 | NS_ASSERTION(!prevPrevViewer, "Should never have viewer chain here")do { if (!(!prevPrevViewer)) { NS_DebugBreak(NS_DEBUG_ASSERTION , "Should never have viewer chain here", "!prevPrevViewer", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 9479); MOZ_PretendNoReturn(); } } while (0); |
9480 | #endif |
9481 | nsCOMPtr<nsISHEntry> viewerEntry; |
9482 | prevViewer->GetHistoryEntry(getter_AddRefs(viewerEntry)); |
9483 | if (viewerEntry == aLoadState->SHEntry()) { |
9484 | // Make sure this viewer ends up in the right place |
9485 | mDocumentViewer->SetPreviousViewer(nullptr); |
9486 | prevViewer->Destroy(); |
9487 | } |
9488 | } |
9489 | } |
9490 | nsCOMPtr<nsISHEntry> oldEntry = mOSHE; |
9491 | bool restoring; |
9492 | rv = RestorePresentation(aLoadState->SHEntry(), &restoring); |
9493 | if (restoring) { |
9494 | Telemetry::Accumulate(Telemetry::BFCACHE_PAGE_RESTORED, true); |
9495 | return rv; |
9496 | } |
9497 | Telemetry::Accumulate(Telemetry::BFCACHE_PAGE_RESTORED, false); |
9498 | |
9499 | // We failed to restore the presentation, so clean up. |
9500 | // Both the old and new history entries could potentially be in |
9501 | // an inconsistent state. |
9502 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
9503 | if (oldEntry) { |
9504 | oldEntry->SyncPresentationState(); |
9505 | } |
9506 | |
9507 | aLoadState->SHEntry()->SyncPresentationState(); |
9508 | } |
9509 | } |
9510 | } |
9511 | |
9512 | bool isTopLevelDoc = mBrowsingContext->IsTopContent(); |
9513 | |
9514 | OriginAttributes attrs = GetOriginAttributes(); |
9515 | attrs.SetFirstPartyDomain(isTopLevelDoc, aLoadState->URI()); |
9516 | |
9517 | PredictorLearn(aLoadState->URI(), nullptr, |
9518 | nsINetworkPredictor::LEARN_LOAD_TOPLEVEL, attrs); |
9519 | PredictorPredict(aLoadState->URI(), nullptr, |
9520 | nsINetworkPredictor::PREDICT_LOAD, attrs, nullptr); |
9521 | |
9522 | nsCOMPtr<nsIRequest> req; |
9523 | rv = DoURILoad(aLoadState, aCacheKey, getter_AddRefs(req)); |
9524 | |
9525 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) { |
9526 | if (shouldTakeFocus) { |
9527 | mBrowsingContext->Focus(CallerType::System, IgnoreErrors()); |
9528 | } |
9529 | } |
9530 | |
9531 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
9532 | nsCOMPtr<nsIChannel> chan(do_QueryInterface(req)); |
9533 | UnblockEmbedderLoadEventForFailure(); |
9534 | nsCOMPtr<nsIURI> uri = aLoadState->URI(); |
9535 | if (DisplayLoadError(rv, uri, nullptr, chan) && |
9536 | // FIXME: At this point code was using internal load flags, but checking |
9537 | // non-internal load flags? |
9538 | aLoadState->HasLoadFlags(LOAD_FLAGS_ERROR_LOAD_CHANGES_RV)) { |
9539 | return NS_ERROR_LOAD_SHOWED_ERRORPAGE; |
9540 | } |
9541 | |
9542 | // We won't report any error if this is an unknown protocol error. The |
9543 | // reason behind this is that it will allow enumeration of external |
9544 | // protocols if we report an error for each unknown protocol. |
9545 | if (NS_ERROR_UNKNOWN_PROTOCOL == rv) { |
9546 | return NS_OK; |
9547 | } |
9548 | } |
9549 | |
9550 | return rv; |
9551 | } |
9552 | |
9553 | /* static */ |
9554 | bool nsDocShell::CanLoadInParentProcess(nsIURI* aURI) { |
9555 | nsCOMPtr<nsIURI> uri = aURI; |
9556 | // In e10s, in the parent process, we refuse to load anything other than |
9557 | // "safe" resources that we ship or trust enough to give "special" URLs. |
9558 | bool canLoadInParent = false; |
9559 | if (NS_SUCCEEDED(NS_URIChainHasFlags(((bool)(__builtin_expect(!!(!NS_FAILED_impl(NS_URIChainHasFlags ( uri, nsIProtocolHandler::URI_IS_UI_RESOURCE, &canLoadInParent ))), 1))) |
9560 | uri, nsIProtocolHandler::URI_IS_UI_RESOURCE, &canLoadInParent))((bool)(__builtin_expect(!!(!NS_FAILED_impl(NS_URIChainHasFlags ( uri, nsIProtocolHandler::URI_IS_UI_RESOURCE, &canLoadInParent ))), 1))) && |
9561 | canLoadInParent) { |
9562 | // We allow UI resources. |
9563 | return true; |
9564 | } |
9565 | // For about: and extension-based URIs, which don't get |
9566 | // URI_IS_UI_RESOURCE, first remove layers of view-source:, if present. |
9567 | while (uri && uri->SchemeIs("view-source")) { |
9568 | nsCOMPtr<nsINestedURI> nested = do_QueryInterface(uri); |
9569 | if (nested) { |
9570 | nested->GetInnerURI(getter_AddRefs(uri)); |
9571 | } else { |
9572 | break; |
9573 | } |
9574 | } |
9575 | // Allow about: URIs, and allow moz-extension ones if we're running |
9576 | // extension content in the parent process. |
9577 | if (!uri || uri->SchemeIs("about") || |
9578 | (!StaticPrefs::extensions_webextensions_remote() && |
9579 | uri->SchemeIs("moz-extension"))) { |
9580 | return true; |
9581 | } |
9582 | #ifdef MOZ_THUNDERBIRD |
9583 | if (uri->SchemeIs("imap") || uri->SchemeIs("mailbox") || |
9584 | uri->SchemeIs("news") || uri->SchemeIs("nntp") || |
9585 | uri->SchemeIs("snews") || uri->SchemeIs("x-moz-ews")) { |
9586 | return true; |
9587 | } |
9588 | #endif |
9589 | nsAutoCString scheme; |
9590 | uri->GetScheme(scheme); |
9591 | // Allow ext+foo URIs (extension-registered custom protocols). See |
9592 | // https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/protocol_handlers |
9593 | if (StringBeginsWith(scheme, "ext+"_ns) && |
9594 | !StaticPrefs::extensions_webextensions_remote()) { |
9595 | return true; |
9596 | } |
9597 | // Final exception for some legacy automated tests: |
9598 | if (xpc::IsInAutomation() && |
9599 | StaticPrefs::security_allow_unsafe_parent_loads()) { |
9600 | return true; |
9601 | } |
9602 | return false; |
9603 | } |
9604 | |
9605 | nsIPrincipal* nsDocShell::GetInheritedPrincipal( |
9606 | bool aConsiderCurrentDocument, bool aConsiderPartitionedPrincipal) { |
9607 | RefPtr<Document> document; |
9608 | bool inheritedFromCurrent = false; |
9609 | |
9610 | if (aConsiderCurrentDocument && mDocumentViewer) { |
9611 | document = mDocumentViewer->GetDocument(); |
9612 | inheritedFromCurrent = true; |
9613 | } |
9614 | |
9615 | if (!document) { |
9616 | nsCOMPtr<nsIDocShellTreeItem> parentItem; |
9617 | GetInProcessSameTypeParent(getter_AddRefs(parentItem)); |
9618 | if (parentItem) { |
9619 | document = parentItem->GetDocument(); |
9620 | } |
9621 | } |
9622 | |
9623 | if (!document) { |
9624 | if (!aConsiderCurrentDocument) { |
9625 | return nullptr; |
9626 | } |
9627 | |
9628 | // Make sure we end up with _something_ as the principal no matter |
9629 | // what.If this fails, we'll just get a null docViewer and bail. |
9630 | EnsureDocumentViewer(); |
9631 | if (!mDocumentViewer) { |
9632 | return nullptr; |
9633 | } |
9634 | document = mDocumentViewer->GetDocument(); |
9635 | } |
9636 | |
9637 | //-- Get the document's principal |
9638 | if (document) { |
9639 | nsIPrincipal* docPrincipal = aConsiderPartitionedPrincipal |
9640 | ? document->PartitionedPrincipal() |
9641 | : document->NodePrincipal(); |
9642 | |
9643 | // Don't allow loads in typeContent docShells to inherit the system |
9644 | // principal from existing documents. |
9645 | if (inheritedFromCurrent && mItemType == typeContent && |
9646 | docPrincipal->IsSystemPrincipal()) { |
9647 | return nullptr; |
9648 | } |
9649 | |
9650 | return docPrincipal; |
9651 | } |
9652 | |
9653 | return nullptr; |
9654 | } |
9655 | |
9656 | /* static */ nsresult nsDocShell::CreateRealChannelForDocument( |
9657 | nsIChannel** aChannel, nsIURI* aURI, nsILoadInfo* aLoadInfo, |
9658 | nsIInterfaceRequestor* aCallbacks, nsLoadFlags aLoadFlags, |
9659 | const nsAString& aSrcdoc, nsIURI* aBaseURI) { |
9660 | nsCOMPtr<nsIChannel> channel; |
9661 | if (aSrcdoc.IsVoid()) { |
9662 | MOZ_TRY(NS_NewChannelInternal(getter_AddRefs(channel), aURI, aLoadInfo,do { auto mozTryTempResult_ = ::mozilla::ToResult(NS_NewChannelInternal (getter_AddRefs(channel), aURI, aLoadInfo, nullptr, nullptr, aCallbacks , aLoadFlags)); if ((__builtin_expect(!!(mozTryTempResult_.isErr ()), 0))) { return mozTryTempResult_.propagateErr(); } } while (0) |
9663 | nullptr, // PerformanceStoragedo { auto mozTryTempResult_ = ::mozilla::ToResult(NS_NewChannelInternal (getter_AddRefs(channel), aURI, aLoadInfo, nullptr, nullptr, aCallbacks , aLoadFlags)); if ((__builtin_expect(!!(mozTryTempResult_.isErr ()), 0))) { return mozTryTempResult_.propagateErr(); } } while (0) |
9664 | nullptr, // loadGroupdo { auto mozTryTempResult_ = ::mozilla::ToResult(NS_NewChannelInternal (getter_AddRefs(channel), aURI, aLoadInfo, nullptr, nullptr, aCallbacks , aLoadFlags)); if ((__builtin_expect(!!(mozTryTempResult_.isErr ()), 0))) { return mozTryTempResult_.propagateErr(); } } while (0) |
9665 | aCallbacks, aLoadFlags))do { auto mozTryTempResult_ = ::mozilla::ToResult(NS_NewChannelInternal (getter_AddRefs(channel), aURI, aLoadInfo, nullptr, nullptr, aCallbacks , aLoadFlags)); if ((__builtin_expect(!!(mozTryTempResult_.isErr ()), 0))) { return mozTryTempResult_.propagateErr(); } } while (0); |
9666 | |
9667 | if (aBaseURI) { |
9668 | nsCOMPtr<nsIViewSourceChannel> vsc = do_QueryInterface(channel); |
9669 | if (vsc) { |
9670 | MOZ_ALWAYS_SUCCEEDS(vsc->SetBaseURI(aBaseURI))do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl (vsc->SetBaseURI(aBaseURI))), 1)))), 1))) { } else { do { static_assert ( mozilla::detail::AssertionConditionType<decltype(false)> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(false))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("false" " (" "NS_SUCCEEDED(vsc->SetBaseURI(aBaseURI))" ")" , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 9670); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false" ") (" "NS_SUCCEEDED(vsc->SetBaseURI(aBaseURI))" ")"); do { *((volatile int*)__null) = 9670; __attribute__((nomerge)) :: abort(); } while (false); } } while (false); } } while (false ); |
9671 | } |
9672 | } |
9673 | } else if (SchemeIsViewSource(aURI)) { |
9674 | // Instantiate view source handler protocol, if it doesn't exist already. |
9675 | nsCOMPtr<nsIIOService> io(do_GetIOService()); |
9676 | 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", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 9676); AnnotateMozCrashReason("MOZ_ASSERT" "(" "io" ")"); do { *((volatile int*)__null) = 9676; __attribute__((nomerge)) :: abort(); } while (false); } } while (false); |
9677 | nsCOMPtr<nsIProtocolHandler> handler; |
9678 | nsresult rv = |
9679 | io->GetProtocolHandler("view-source", getter_AddRefs(handler)); |
9680 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
9681 | return rv; |
9682 | } |
9683 | |
9684 | nsViewSourceHandler* vsh = nsViewSourceHandler::GetInstance(); |
9685 | if (!vsh) { |
9686 | return NS_ERROR_FAILURE; |
9687 | } |
9688 | |
9689 | MOZ_TRY(vsh->NewSrcdocChannel(aURI, aBaseURI, aSrcdoc, aLoadInfo,do { auto mozTryTempResult_ = ::mozilla::ToResult(vsh->NewSrcdocChannel (aURI, aBaseURI, aSrcdoc, aLoadInfo, getter_AddRefs(channel)) ); if ((__builtin_expect(!!(mozTryTempResult_.isErr()), 0))) { return mozTryTempResult_.propagateErr(); } } while (0) |
9690 | getter_AddRefs(channel)))do { auto mozTryTempResult_ = ::mozilla::ToResult(vsh->NewSrcdocChannel (aURI, aBaseURI, aSrcdoc, aLoadInfo, getter_AddRefs(channel)) ); if ((__builtin_expect(!!(mozTryTempResult_.isErr()), 0))) { return mozTryTempResult_.propagateErr(); } } while (0); |
9691 | } else { |
9692 | MOZ_TRY(NS_NewInputStreamChannelInternal(getter_AddRefs(channel), aURI,do { auto mozTryTempResult_ = ::mozilla::ToResult(NS_NewInputStreamChannelInternal (getter_AddRefs(channel), aURI, aSrcdoc, "text/html"_ns, aLoadInfo , true)); if ((__builtin_expect(!!(mozTryTempResult_.isErr()) , 0))) { return mozTryTempResult_.propagateErr(); } } while ( 0) |
9693 | aSrcdoc, "text/html"_ns, aLoadInfo,do { auto mozTryTempResult_ = ::mozilla::ToResult(NS_NewInputStreamChannelInternal (getter_AddRefs(channel), aURI, aSrcdoc, "text/html"_ns, aLoadInfo , true)); if ((__builtin_expect(!!(mozTryTempResult_.isErr()) , 0))) { return mozTryTempResult_.propagateErr(); } } while ( 0) |
9694 | true))do { auto mozTryTempResult_ = ::mozilla::ToResult(NS_NewInputStreamChannelInternal (getter_AddRefs(channel), aURI, aSrcdoc, "text/html"_ns, aLoadInfo , true)); if ((__builtin_expect(!!(mozTryTempResult_.isErr()) , 0))) { return mozTryTempResult_.propagateErr(); } } while ( 0); |
9695 | nsCOMPtr<nsIInputStreamChannel> isc = do_QueryInterface(channel); |
9696 | 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", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 9696); AnnotateMozCrashReason("MOZ_ASSERT" "(" "isc" ")"); do { *((volatile int*)__null) = 9696; __attribute__((nomerge)) :: abort(); } while (false); } } while (false); |
9697 | isc->SetBaseURI(aBaseURI); |
9698 | } |
9699 | |
9700 | if (aLoadFlags != nsIRequest::LOAD_NORMAL) { |
9701 | nsresult rv = channel->SetLoadFlags(aLoadFlags); |
9702 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 9702); return rv; } } while (false); |
9703 | } |
9704 | |
9705 | channel.forget(aChannel); |
9706 | return NS_OK; |
9707 | } |
9708 | |
9709 | /* static */ bool nsDocShell::CreateAndConfigureRealChannelForLoadState( |
9710 | BrowsingContext* aBrowsingContext, nsDocShellLoadState* aLoadState, |
9711 | LoadInfo* aLoadInfo, nsIInterfaceRequestor* aCallbacks, |
9712 | nsDocShell* aDocShell, const OriginAttributes& aOriginAttributes, |
9713 | nsLoadFlags aLoadFlags, uint32_t aCacheKey, nsresult& aRv, |
9714 | nsIChannel** aChannel) { |
9715 | 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", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 9715); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadInfo" ")" ); do { *((volatile int*)__null) = 9715; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
9716 | |
9717 | nsString srcdoc = VoidString(); |
9718 | bool isSrcdoc = |
9719 | aLoadState->HasInternalLoadFlags(INTERNAL_LOAD_FLAGS_IS_SRCDOC); |
9720 | if (isSrcdoc) { |
9721 | srcdoc = aLoadState->SrcdocData(); |
9722 | } |
9723 | |
9724 | aLoadInfo->SetTriggeringRemoteType( |
9725 | aLoadState->GetEffectiveTriggeringRemoteType()); |
9726 | |
9727 | if (aLoadState->PrincipalToInherit()) { |
9728 | aLoadInfo->SetPrincipalToInherit(aLoadState->PrincipalToInherit()); |
9729 | } |
9730 | aLoadInfo->SetLoadTriggeredFromExternal( |
9731 | aLoadState->HasLoadFlags(LOAD_FLAGS_FROM_EXTERNAL)); |
9732 | aLoadInfo->SetForceAllowDataURI(aLoadState->HasInternalLoadFlags( |
9733 | INTERNAL_LOAD_FLAGS_FORCE_ALLOW_DATA_URI)); |
9734 | aLoadInfo->SetOriginalFrameSrcLoad( |
9735 | aLoadState->HasInternalLoadFlags(INTERNAL_LOAD_FLAGS_ORIGINAL_FRAME_SRC)); |
9736 | aLoadInfo->SetIsNewWindowTarget( |
9737 | aLoadState->HasInternalLoadFlags(INTERNAL_LOAD_FLAGS_FIRST_LOAD)); |
9738 | |
9739 | bool inheritAttrs = false; |
9740 | if (aLoadState->PrincipalToInherit()) { |
9741 | inheritAttrs = nsContentUtils::ChannelShouldInheritPrincipal( |
9742 | aLoadState->PrincipalToInherit(), aLoadState->URI(), |
9743 | true, // aInheritForAboutBlank |
9744 | isSrcdoc); |
9745 | } |
9746 | |
9747 | // Strip the target query parameters before creating the channel. |
9748 | aLoadState->MaybeStripTrackerQueryStrings(aBrowsingContext); |
9749 | |
9750 | OriginAttributes attrs; |
9751 | |
9752 | // Inherit origin attributes from PrincipalToInherit if inheritAttrs is |
9753 | // true. Otherwise we just use the origin attributes from docshell. |
9754 | if (inheritAttrs) { |
9755 | 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." ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 9756); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->PrincipalToInherit()" ") (" "We should have PrincipalToInherit here." ")"); do { * ((volatile int*)__null) = 9756; __attribute__((nomerge)) ::abort (); } while (false); } } while (false) |
9756 | "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." ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 9756); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->PrincipalToInherit()" ") (" "We should have PrincipalToInherit here." ")"); do { * ((volatile int*)__null) = 9756; __attribute__((nomerge)) ::abort (); } while (false); } } while (false); |
9757 | attrs = aLoadState->PrincipalToInherit()->OriginAttributesRef(); |
9758 | // If firstPartyIsolation is not enabled, then PrincipalToInherit should |
9759 | // have the same origin attributes with docshell. |
9760 | 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" , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 9761); AnnotateMozCrashReason("MOZ_ASSERT" "(" "attrs == aOriginAttributes" ")"); do { *((volatile int*)__null) = 9761; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) |
9761 | 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" , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 9761); AnnotateMozCrashReason("MOZ_ASSERT" "(" "attrs == aOriginAttributes" ")"); do { *((volatile int*)__null) = 9761; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); |
9762 | } else { |
9763 | attrs = aOriginAttributes; |
9764 | attrs.SetFirstPartyDomain(IsTopLevelDoc(aBrowsingContext, aLoadInfo), |
9765 | aLoadState->URI()); |
9766 | } |
9767 | |
9768 | aRv = aLoadInfo->SetOriginAttributes(attrs); |
9769 | if (NS_WARN_IF(NS_FAILED(aRv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(aRv )), 0))), "NS_FAILED(aRv)", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 9769)) { |
9770 | return false; |
9771 | } |
9772 | |
9773 | if (aLoadState->GetIsFromProcessingFrameAttributes()) { |
9774 | aLoadInfo->SetIsFromProcessingFrameAttributes(); |
9775 | } |
9776 | |
9777 | // Propagate the IsFormSubmission flag to the loadInfo. |
9778 | if (aLoadState->IsFormSubmission()) { |
9779 | aLoadInfo->SetIsFormSubmission(true); |
9780 | } |
9781 | |
9782 | aLoadInfo->SetUnstrippedURI(aLoadState->GetUnstrippedURI()); |
9783 | |
9784 | nsCOMPtr<nsIChannel> channel; |
9785 | aRv = CreateRealChannelForDocument(getter_AddRefs(channel), aLoadState->URI(), |
9786 | aLoadInfo, aCallbacks, aLoadFlags, srcdoc, |
9787 | aLoadState->BaseURI()); |
9788 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 9788); return false; } } while (false); |
9789 | |
9790 | if (!channel) { |
9791 | return false; |
9792 | } |
9793 | |
9794 | // If the HTTPS-Only mode is enabled, every insecure request gets upgraded to |
9795 | // HTTPS by default. This behavior can be disabled through the loadinfo flag |
9796 | // HTTPS_ONLY_EXEMPT. |
9797 | nsHTTPSOnlyUtils::TestSitePermissionAndPotentiallyAddExemption(channel); |
9798 | |
9799 | // hack |
9800 | nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(channel)); |
9801 | nsCOMPtr<nsIHttpChannelInternal> httpChannelInternal( |
9802 | do_QueryInterface(channel)); |
9803 | nsCOMPtr<nsIURI> referrer; |
9804 | nsIReferrerInfo* referrerInfo = aLoadState->GetReferrerInfo(); |
9805 | if (referrerInfo) { |
9806 | referrerInfo->GetOriginalReferrer(getter_AddRefs(referrer)); |
9807 | } |
9808 | if (httpChannelInternal) { |
9809 | if (aLoadState->HasInternalLoadFlags( |
9810 | INTERNAL_LOAD_FLAGS_FORCE_ALLOW_COOKIES)) { |
9811 | aRv = httpChannelInternal->SetThirdPartyFlags( |
9812 | nsIHttpChannelInternal::THIRD_PARTY_FORCE_ALLOW); |
9813 | 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)))", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 9813); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1)))" ")"); do { *((volatile int*)__null) = 9813; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
9814 | } |
9815 | if (aLoadState->FirstParty()) { |
9816 | aRv = httpChannelInternal->SetDocumentURI(aLoadState->URI()); |
9817 | 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)))", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 9817); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1)))" ")"); do { *((volatile int*)__null) = 9817; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
9818 | } else { |
9819 | aRv = httpChannelInternal->SetDocumentURI(referrer); |
9820 | 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)))", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 9820); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1)))" ")"); do { *((volatile int*)__null) = 9820; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
9821 | } |
9822 | aRv = httpChannelInternal->SetRedirectMode( |
9823 | nsIHttpChannelInternal::REDIRECT_MODE_MANUAL); |
9824 | 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)))", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 9824); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1)))" ")"); do { *((volatile int*)__null) = 9824; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
9825 | } |
9826 | |
9827 | if (httpChannel) { |
9828 | if (aLoadState->HeadersStream()) { |
9829 | aRv = AddHeadersToChannel(aLoadState->HeadersStream(), httpChannel); |
9830 | } |
9831 | // Set the referrer explicitly |
9832 | // Referrer is currenly only set for link clicks here. |
9833 | if (referrerInfo) { |
9834 | aRv = httpChannel->SetReferrerInfo(referrerInfo); |
9835 | 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)))", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 9835); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1)))" ")"); do { *((volatile int*)__null) = 9835; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
9836 | } |
9837 | |
9838 | // Mark the http channel as UrgentStart for top level document loading in |
9839 | // active tab. |
9840 | if (IsUrgentStart(aBrowsingContext, aLoadInfo, aLoadState->LoadType())) { |
9841 | nsCOMPtr<nsIClassOfService> cos(do_QueryInterface(channel)); |
9842 | if (cos) { |
9843 | cos->AddClassFlags(nsIClassOfService::UrgentStart); |
9844 | if (StaticPrefs::dom_document_priority_incremental()) { |
9845 | cos->SetIncremental(true); |
9846 | } |
9847 | } |
9848 | } |
9849 | } |
9850 | |
9851 | channel->SetOriginalURI(aLoadState->OriginalURI() ? aLoadState->OriginalURI() |
9852 | : aLoadState->URI()); |
9853 | |
9854 | const nsACString& typeHint = aLoadState->TypeHint(); |
9855 | if (!typeHint.IsVoid()) { |
9856 | channel->SetContentType(typeHint); |
9857 | } |
9858 | |
9859 | const nsAString& fileName = aLoadState->FileName(); |
9860 | if (!fileName.IsVoid()) { |
9861 | aRv = channel->SetContentDisposition(nsIChannel::DISPOSITION_ATTACHMENT); |
9862 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 9862); return false; } } while (false); |
9863 | if (!fileName.IsEmpty()) { |
9864 | aRv = channel->SetContentDispositionFilename(fileName); |
9865 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 9865); return false; } } while (false); |
9866 | } |
9867 | } |
9868 | |
9869 | if (nsCOMPtr<nsIWritablePropertyBag2> props = do_QueryInterface(channel)) { |
9870 | nsCOMPtr<nsIURI> referrer; |
9871 | nsIReferrerInfo* referrerInfo = aLoadState->GetReferrerInfo(); |
9872 | if (referrerInfo) { |
9873 | referrerInfo->GetOriginalReferrer(getter_AddRefs(referrer)); |
9874 | } |
9875 | // save true referrer for those who need it (e.g. xpinstall whitelisting) |
9876 | // Currently only http and ftp channels support this. |
9877 | props->SetPropertyAsInterface(u"docshell.internalReferrer"_ns, referrer); |
9878 | } |
9879 | |
9880 | nsCOMPtr<nsICacheInfoChannel> cacheChannel(do_QueryInterface(channel)); |
9881 | auto loadType = aLoadState->LoadType(); |
9882 | |
9883 | if (loadType == LOAD_RELOAD_NORMAL && |
9884 | StaticPrefs:: |
9885 | browser_soft_reload_only_force_validate_top_level_document()) { |
9886 | nsCOMPtr<nsICacheInfoChannel> cachingChannel = do_QueryInterface(channel); |
9887 | if (cachingChannel) { |
9888 | cachingChannel->SetForceValidateCacheContent(true); |
9889 | } |
9890 | } |
9891 | |
9892 | // figure out if we need to set the post data stream on the channel... |
9893 | if (aLoadState->PostDataStream()) { |
9894 | if (nsCOMPtr<nsIFormPOSTActionChannel> postChannel = |
9895 | do_QueryInterface(channel)) { |
9896 | // XXX it's a bit of a hack to rewind the postdata stream here but |
9897 | // it has to be done in case the post data is being reused multiple |
9898 | // times. |
9899 | nsCOMPtr<nsISeekableStream> postDataSeekable = |
9900 | do_QueryInterface(aLoadState->PostDataStream()); |
9901 | if (postDataSeekable) { |
9902 | aRv = postDataSeekable->Seek(nsISeekableStream::NS_SEEK_SET, 0); |
9903 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 9903); return false; } } while (false); |
9904 | } |
9905 | |
9906 | // we really need to have a content type associated with this stream!! |
9907 | postChannel->SetUploadStream(aLoadState->PostDataStream(), ""_ns, -1); |
9908 | |
9909 | // Ownership of the stream has transferred to the channel, clear our |
9910 | // reference. |
9911 | aLoadState->SetPostDataStream(nullptr); |
9912 | } |
9913 | |
9914 | /* If there is a valid postdata *and* it is a History Load, |
9915 | * set up the cache key on the channel, to retrieve the |
9916 | * data *only* from the cache. If it is a normal reload, the |
9917 | * cache is free to go to the server for updated postdata. |
9918 | */ |
9919 | if (cacheChannel && aCacheKey != 0) { |
9920 | if (loadType == LOAD_HISTORY || loadType == LOAD_RELOAD_CHARSET_CHANGE) { |
9921 | cacheChannel->SetCacheKey(aCacheKey); |
9922 | uint32_t loadFlags; |
9923 | if (NS_SUCCEEDED(channel->GetLoadFlags(&loadFlags))((bool)(__builtin_expect(!!(!NS_FAILED_impl(channel->GetLoadFlags (&loadFlags))), 1)))) { |
9924 | channel->SetLoadFlags(loadFlags | |
9925 | nsICachingChannel::LOAD_ONLY_FROM_CACHE); |
9926 | } |
9927 | } else if (loadType == LOAD_RELOAD_NORMAL) { |
9928 | cacheChannel->SetCacheKey(aCacheKey); |
9929 | } |
9930 | } |
9931 | } else { |
9932 | /* If there is no postdata, set the cache key on the channel, and |
9933 | * do not set the LOAD_ONLY_FROM_CACHE flag, so that the channel |
9934 | * will be free to get it from net if it is not found in cache. |
9935 | * New cache may use it creatively on CGI pages with GET |
9936 | * method and even on those that say "no-cache" |
9937 | */ |
9938 | if (loadType == LOAD_HISTORY || loadType == LOAD_RELOAD_NORMAL || |
9939 | loadType == LOAD_RELOAD_CHARSET_CHANGE || |
9940 | loadType == LOAD_RELOAD_CHARSET_CHANGE_BYPASS_CACHE || |
9941 | loadType == LOAD_RELOAD_CHARSET_CHANGE_BYPASS_PROXY_AND_CACHE) { |
9942 | if (cacheChannel && aCacheKey != 0) { |
9943 | cacheChannel->SetCacheKey(aCacheKey); |
9944 | } |
9945 | } |
9946 | } |
9947 | |
9948 | if (nsCOMPtr<nsIScriptChannel> scriptChannel = do_QueryInterface(channel)) { |
9949 | // Allow execution against our context if the principals match |
9950 | scriptChannel->SetExecutionPolicy(nsIScriptChannel::EXECUTE_NORMAL); |
9951 | } |
9952 | |
9953 | if (nsCOMPtr<nsITimedChannel> timedChannel = do_QueryInterface(channel)) { |
9954 | timedChannel->SetTimingEnabled(true); |
9955 | |
9956 | nsString initiatorType; |
9957 | switch (aLoadInfo->InternalContentPolicyType()) { |
9958 | case nsIContentPolicy::TYPE_INTERNAL_EMBED: |
9959 | initiatorType = u"embed"_ns; |
9960 | break; |
9961 | case nsIContentPolicy::TYPE_INTERNAL_OBJECT: |
9962 | initiatorType = u"object"_ns; |
9963 | break; |
9964 | default: { |
9965 | const auto& embedderElementType = |
9966 | aBrowsingContext->GetEmbedderElementType(); |
9967 | if (embedderElementType) { |
9968 | initiatorType = *embedderElementType; |
9969 | } |
9970 | break; |
9971 | } |
9972 | } |
9973 | |
9974 | if (!initiatorType.IsEmpty()) { |
9975 | timedChannel->SetInitiatorType(initiatorType); |
9976 | } |
9977 | } |
9978 | |
9979 | nsCOMPtr<nsIURI> rpURI; |
9980 | aLoadInfo->GetResultPrincipalURI(getter_AddRefs(rpURI)); |
9981 | Maybe<nsCOMPtr<nsIURI>> originalResultPrincipalURI; |
9982 | aLoadState->GetMaybeResultPrincipalURI(originalResultPrincipalURI); |
9983 | if (originalResultPrincipalURI && |
9984 | (!aLoadState->KeepResultPrincipalURIIfSet() || !rpURI)) { |
9985 | // Unconditionally override, we want the replay to be equal to what has |
9986 | // been captured. |
9987 | aLoadInfo->SetResultPrincipalURI(originalResultPrincipalURI.ref()); |
9988 | } |
9989 | |
9990 | if (aLoadState->OriginalURI() && aLoadState->LoadReplace()) { |
9991 | // The LOAD_REPLACE flag and its handling here will be removed as part |
9992 | // of bug 1319110. For now preserve its restoration here to not break |
9993 | // any code expecting it being set specially on redirected channels. |
9994 | // If the flag has originally been set to change result of |
9995 | // NS_GetFinalChannelURI it won't have any effect and also won't cause |
9996 | // any harm. |
9997 | uint32_t loadFlags; |
9998 | aRv = channel->GetLoadFlags(&loadFlags); |
9999 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 9999); return false; } } while (false); |
10000 | channel->SetLoadFlags(loadFlags | nsIChannel::LOAD_REPLACE); |
10001 | } |
10002 | |
10003 | nsCOMPtr<nsIContentSecurityPolicy> csp = aLoadState->Csp(); |
10004 | if (csp) { |
10005 | // Navigational requests that are same origin need to be upgraded in case |
10006 | // upgrade-insecure-requests is present. Please note that for document |
10007 | // navigations that bit is re-computed in case we encounter a server |
10008 | // side redirect so the navigation is not same-origin anymore. |
10009 | bool upgradeInsecureRequests = false; |
10010 | csp->GetUpgradeInsecureRequests(&upgradeInsecureRequests); |
10011 | if (upgradeInsecureRequests) { |
10012 | // only upgrade if the navigation is same origin |
10013 | nsCOMPtr<nsIPrincipal> resultPrincipal; |
10014 | aRv = nsContentUtils::GetSecurityManager()->GetChannelResultPrincipal( |
10015 | channel, getter_AddRefs(resultPrincipal)); |
10016 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 10016); return false; } } while (false); |
10017 | if (nsContentSecurityUtils::IsConsideredSameOriginForUIR( |
10018 | aLoadState->TriggeringPrincipal(), resultPrincipal)) { |
10019 | aLoadInfo->SetUpgradeInsecureRequests(true); |
10020 | } |
10021 | } |
10022 | |
10023 | // For document loads we store the CSP that potentially needs to |
10024 | // be inherited by the new document, e.g. in case we are loading |
10025 | // an opaque origin like a data: URI. The actual inheritance |
10026 | // check happens within Document::InitCSP(). |
10027 | // Please create an actual copy of the CSP (do not share the same |
10028 | // reference) otherwise a Meta CSP of an opaque origin will |
10029 | // incorrectly be propagated to the embedding document. |
10030 | RefPtr<nsCSPContext> cspToInherit = new nsCSPContext(); |
10031 | cspToInherit->InitFromOther(static_cast<nsCSPContext*>(csp.get())); |
10032 | aLoadInfo->SetCSPToInherit(cspToInherit); |
10033 | } |
10034 | |
10035 | channel.forget(aChannel); |
10036 | return true; |
10037 | } |
10038 | |
10039 | bool nsDocShell::IsAboutBlankLoadOntoInitialAboutBlank( |
10040 | nsIURI* aURI, bool aInheritPrincipal, nsIPrincipal* aPrincipalToInherit) { |
10041 | return NS_IsAboutBlankAllowQueryAndFragment(aURI) && aInheritPrincipal && |
10042 | (aPrincipalToInherit == GetInheritedPrincipal(false)) && |
10043 | (!mDocumentViewer || !mDocumentViewer->GetDocument() || |
10044 | mDocumentViewer->GetDocument()->IsInitialDocument()); |
10045 | } |
10046 | |
10047 | nsresult nsDocShell::DoURILoad(nsDocShellLoadState* aLoadState, |
10048 | Maybe<uint32_t> aCacheKey, |
10049 | nsIRequest** aRequest) { |
10050 | // Double-check that we're still around to load this URI. |
10051 | if (mIsBeingDestroyed) { |
10052 | // Return NS_OK despite not doing anything to avoid throwing exceptions |
10053 | // from nsLocation::SetHref if the unload handler of the existing page |
10054 | // tears us down. |
10055 | return NS_OK; |
10056 | } |
10057 | |
10058 | nsCOMPtr<nsIURILoader> uriLoader = components::URILoader::Service(); |
10059 | if (NS_WARN_IF(!uriLoader)NS_warn_if_impl(!uriLoader, "!uriLoader", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 10059)) { |
10060 | return NS_ERROR_UNEXPECTED; |
10061 | } |
10062 | |
10063 | // Persist and sync layout history state before we load a new uri, as this |
10064 | // might be our last chance to do so, in the content process. |
10065 | PersistLayoutHistoryState(); |
10066 | SynchronizeLayoutHistoryState(); |
10067 | |
10068 | nsresult rv; |
10069 | nsContentPolicyType contentPolicyType = DetermineContentType(); |
10070 | |
10071 | if (IsSubframe()) { |
10072 | 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 10074); AnnotateMozCrashReason("MOZ_ASSERT" "(" "contentPolicyType == nsIContentPolicy::TYPE_INTERNAL_IFRAME || contentPolicyType == nsIContentPolicy::TYPE_INTERNAL_FRAME" ") (" "DoURILoad thinks this is a frame and InternalLoad does not" ")"); do { *((volatile int*)__null) = 10074; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false) |
10073 | 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 10074); AnnotateMozCrashReason("MOZ_ASSERT" "(" "contentPolicyType == nsIContentPolicy::TYPE_INTERNAL_IFRAME || contentPolicyType == nsIContentPolicy::TYPE_INTERNAL_FRAME" ") (" "DoURILoad thinks this is a frame and InternalLoad does not" ")"); do { *((volatile int*)__null) = 10074; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false) |
10074 | "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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 10074); AnnotateMozCrashReason("MOZ_ASSERT" "(" "contentPolicyType == nsIContentPolicy::TYPE_INTERNAL_IFRAME || contentPolicyType == nsIContentPolicy::TYPE_INTERNAL_FRAME" ") (" "DoURILoad thinks this is a frame and InternalLoad does not" ")"); do { *((volatile int*)__null) = 10074; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
10075 | |
10076 | if (auto* iframe = HTMLIFrameElement::FromNodeOrNull( |
10077 | mBrowsingContext->GetEmbedderElement())) { |
10078 | // Per spec, reload doesn't cacel lazy loading iframes. |
10079 | if (!(aLoadState->LoadType() & LOAD_RELOAD_NORMAL)) { |
10080 | iframe->CancelLazyLoading(true /* aClearLazyLoadState */); |
10081 | } |
10082 | } |
10083 | |
10084 | if (StaticPrefs::dom_block_external_protocol_in_iframes()) { |
10085 | // Only allow URLs able to return data in iframes. |
10086 | if (nsContentUtils::IsExternalProtocol(aLoadState->URI())) { |
10087 | // The context to check user-interaction with for the purposes of |
10088 | // popup-blocking. |
10089 | // |
10090 | // We generally want to check the context that initiated the navigation. |
10091 | WindowContext* sourceWindowContext = [&] { |
10092 | const MaybeDiscardedBrowsingContext& sourceBC = |
10093 | aLoadState->SourceBrowsingContext(); |
10094 | if (!sourceBC.IsNullOrDiscarded()) { |
10095 | if (WindowContext* wc = sourceBC.get()->GetCurrentWindowContext()) { |
10096 | return wc; |
10097 | } |
10098 | } |
10099 | return mBrowsingContext->GetParentWindowContext(); |
10100 | }(); |
10101 | |
10102 | 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" , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 10102); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sourceWindowContext" ")"); do { *((volatile int*)__null) = 10102; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
10103 | // FIXME: We can't check user-interaction against an OOP window. This is |
10104 | // the next best thing we can really do. The load state keeps whether |
10105 | // the navigation had a user interaction in process |
10106 | // (aLoadState->HasValidUserGestureActivation()), but we can't really |
10107 | // consume it, which we want to prevent popup-spamming from the same |
10108 | // click event. |
10109 | WindowContext* context = |
10110 | sourceWindowContext->IsInProcess() |
10111 | ? sourceWindowContext |
10112 | : mBrowsingContext->GetCurrentWindowContext(); |
10113 | const bool popupBlocked = [&] { |
10114 | const bool active = mBrowsingContext->IsActive(); |
10115 | |
10116 | // For same-origin-with-top windows, we grant a single free popup |
10117 | // without user activation, see bug 1680721. |
10118 | // |
10119 | // We consume the flag now even if there's no user activation. |
10120 | const bool hasFreePass = [&] { |
10121 | if (!active || |
10122 | !(context->IsInProcess() && context->SameOriginWithTop())) { |
10123 | return false; |
10124 | } |
10125 | nsGlobalWindowInner* win = |
10126 | context->TopWindowContext()->GetInnerWindow(); |
10127 | return win && win->TryOpenExternalProtocolIframe(); |
10128 | }(); |
10129 | |
10130 | if (context->IsInProcess() && |
10131 | context->ConsumeTransientUserGestureActivation()) { |
10132 | // If the user has interacted with the page, consume it. |
10133 | return false; |
10134 | } |
10135 | |
10136 | // TODO(emilio): Can we remove this check? It seems like what prompted |
10137 | // this code (bug 1514547) should be covered by transient user |
10138 | // activation, see bug 1514547. |
10139 | if (active && |
10140 | PopupBlocker::ConsumeTimerTokenForExternalProtocolIframe()) { |
10141 | return false; |
10142 | } |
10143 | |
10144 | if (sourceWindowContext->CanShowPopup()) { |
10145 | return false; |
10146 | } |
10147 | |
10148 | if (hasFreePass) { |
10149 | return false; |
10150 | } |
10151 | |
10152 | return true; |
10153 | }(); |
10154 | |
10155 | // No error must be returned when iframes are blocked. |
10156 | if (popupBlocked) { |
10157 | nsAutoString message; |
10158 | nsresult rv = nsContentUtils::GetLocalizedString( |
10159 | nsContentUtils::eDOM_PROPERTIES, |
10160 | "ExternalProtocolFrameBlockedNoUserActivation", message); |
10161 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) { |
10162 | nsContentUtils::ReportToConsoleByWindowID( |
10163 | message, nsIScriptError::warningFlag, "DOM"_ns, |
10164 | context->InnerWindowId()); |
10165 | } |
10166 | return NS_OK; |
10167 | } |
10168 | } |
10169 | } |
10170 | |
10171 | // Only allow view-source scheme in top-level docshells. view-source is |
10172 | // the only scheme to which this applies at the moment due to potential |
10173 | // timing attacks to read data from cross-origin iframes. If this widens |
10174 | // we should add a protocol flag for whether the scheme is allowed in |
10175 | // frames and use something like nsNetUtil::NS_URIChainHasFlags. |
10176 | nsCOMPtr<nsIURI> tempURI = aLoadState->URI(); |
10177 | nsCOMPtr<nsINestedURI> nestedURI = do_QueryInterface(tempURI); |
10178 | while (nestedURI) { |
10179 | // view-source should always be an nsINestedURI, loop and check the |
10180 | // scheme on this and all inner URIs that are also nested URIs. |
10181 | if (SchemeIsViewSource(tempURI)) { |
10182 | return NS_ERROR_UNKNOWN_PROTOCOL; |
10183 | } |
10184 | nestedURI->GetInnerURI(getter_AddRefs(tempURI)); |
10185 | nestedURI = do_QueryInterface(tempURI); |
10186 | } |
10187 | } else { |
10188 | 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 10189); AnnotateMozCrashReason("MOZ_ASSERT" "(" "contentPolicyType == nsIContentPolicy::TYPE_DOCUMENT" ") (" "DoURILoad thinks this is a document and InternalLoad does not" ")"); do { *((volatile int*)__null) = 10189; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false) |
10189 | "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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 10189); AnnotateMozCrashReason("MOZ_ASSERT" "(" "contentPolicyType == nsIContentPolicy::TYPE_DOCUMENT" ") (" "DoURILoad thinks this is a document and InternalLoad does not" ")"); do { *((volatile int*)__null) = 10189; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
10190 | } |
10191 | |
10192 | // We want to inherit aLoadState->PrincipalToInherit() when: |
10193 | // 1. ChannelShouldInheritPrincipal returns true. |
10194 | // 2. aLoadState->URI() is not data: URI, or data: URI is not |
10195 | // configured as unique opaque origin. |
10196 | bool inheritPrincipal = false; |
10197 | |
10198 | if (aLoadState->PrincipalToInherit()) { |
10199 | bool isSrcdoc = |
10200 | aLoadState->HasInternalLoadFlags(INTERNAL_LOAD_FLAGS_IS_SRCDOC); |
10201 | bool inheritAttrs = nsContentUtils::ChannelShouldInheritPrincipal( |
10202 | aLoadState->PrincipalToInherit(), aLoadState->URI(), |
10203 | true, // aInheritForAboutBlank |
10204 | isSrcdoc); |
10205 | |
10206 | inheritPrincipal = inheritAttrs && !SchemeIsData(aLoadState->URI()); |
10207 | } |
10208 | |
10209 | // See https://bugzilla.mozilla.org/show_bug.cgi?id=1736570 |
10210 | const bool isAboutBlankLoadOntoInitialAboutBlank = |
10211 | IsAboutBlankLoadOntoInitialAboutBlank(aLoadState->URI(), inheritPrincipal, |
10212 | aLoadState->PrincipalToInherit()); |
10213 | |
10214 | // FIXME We still have a ton of codepaths that don't pass through |
10215 | // DocumentLoadListener, so probably need to create session history info |
10216 | // in more places. |
10217 | if (aLoadState->GetLoadingSessionHistoryInfo()) { |
10218 | SetLoadingSessionHistoryInfo(*aLoadState->GetLoadingSessionHistoryInfo()); |
10219 | } else if (isAboutBlankLoadOntoInitialAboutBlank && |
10220 | mozilla::SessionHistoryInParent()) { |
10221 | // Materialize LoadingSessionHistoryInfo here, because DocumentChannel |
10222 | // loads have it, and later history behavior depends on it existing. |
10223 | UniquePtr<SessionHistoryInfo> entry = MakeUnique<SessionHistoryInfo>( |
10224 | aLoadState->URI(), aLoadState->TriggeringPrincipal(), |
10225 | aLoadState->PrincipalToInherit(), |
10226 | aLoadState->PartitionedPrincipalToInherit(), aLoadState->Csp(), |
10227 | mContentTypeHint); |
10228 | mozilla::dom::LoadingSessionHistoryInfo info(*entry); |
10229 | SetLoadingSessionHistoryInfo(info, true); |
10230 | } |
10231 | |
10232 | // open a channel for the url |
10233 | |
10234 | // If we have a pending channel, use the channel we've already created here. |
10235 | // We don't need to set up load flags for our channel, as it has already been |
10236 | // created. |
10237 | |
10238 | if (nsCOMPtr<nsIChannel> channel = |
10239 | aLoadState->GetPendingRedirectedChannel()) { |
10240 | // If we have a request outparameter, shove our channel into it. |
10241 | if (aRequest) { |
10242 | nsCOMPtr<nsIRequest> outRequest = channel; |
10243 | outRequest.forget(aRequest); |
10244 | } |
10245 | |
10246 | return OpenRedirectedChannel(aLoadState); |
10247 | } |
10248 | |
10249 | // There are two cases we care about: |
10250 | // * Top-level load: In this case, loadingNode is null, but loadingWindow |
10251 | // is our mScriptGlobal. We pass null for loadingPrincipal in this case. |
10252 | // * Subframe load: loadingWindow is null, but loadingNode is the frame |
10253 | // element for the load. loadingPrincipal is the NodePrincipal of the |
10254 | // frame element. |
10255 | nsCOMPtr<nsINode> loadingNode; |
10256 | nsCOMPtr<nsPIDOMWindowOuter> loadingWindow; |
10257 | nsCOMPtr<nsIPrincipal> loadingPrincipal; |
10258 | nsCOMPtr<nsISupports> topLevelLoadingContext; |
10259 | |
10260 | if (contentPolicyType == nsIContentPolicy::TYPE_DOCUMENT) { |
10261 | loadingNode = nullptr; |
10262 | loadingPrincipal = nullptr; |
10263 | loadingWindow = mScriptGlobal; |
10264 | if (XRE_IsContentProcess()) { |
10265 | // In e10s the child process doesn't have access to the element that |
10266 | // contains the browsing context (because that element is in the chrome |
10267 | // process). |
10268 | nsCOMPtr<nsIBrowserChild> browserChild = GetBrowserChild(); |
10269 | topLevelLoadingContext = ToSupports(browserChild); |
10270 | } else { |
10271 | // This is for loading non-e10s tabs and toplevel windows of various |
10272 | // sorts. |
10273 | // For the toplevel window cases, requestingElement will be null. |
10274 | nsCOMPtr<Element> requestingElement = |
10275 | loadingWindow->GetFrameElementInternal(); |
10276 | topLevelLoadingContext = requestingElement; |
10277 | } |
10278 | } else { |
10279 | loadingWindow = nullptr; |
10280 | loadingNode = mScriptGlobal->GetFrameElementInternal(); |
10281 | if (loadingNode) { |
10282 | // If we have a loading node, then use that as our loadingPrincipal. |
10283 | loadingPrincipal = loadingNode->NodePrincipal(); |
10284 | #ifdef DEBUG1 |
10285 | // Get the docshell type for requestingElement. |
10286 | RefPtr<Document> requestingDoc = loadingNode->OwnerDoc(); |
10287 | nsCOMPtr<nsIDocShell> elementDocShell = requestingDoc->GetDocShell(); |
10288 | // requestingElement docshell type = current docshell type. |
10289 | 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 10291); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mItemType == elementDocShell->ItemType()" ") (" "subframes should have the same docshell type as their parent" ")"); do { *((volatile int*)__null) = 10291; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false) |
10290 | 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 10291); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mItemType == elementDocShell->ItemType()" ") (" "subframes should have the same docshell type as their parent" ")"); do { *((volatile int*)__null) = 10291; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false) |
10291 | "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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 10291); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mItemType == elementDocShell->ItemType()" ") (" "subframes should have the same docshell type as their parent" ")"); do { *((volatile int*)__null) = 10291; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
10292 | #endif |
10293 | } else { |
10294 | if (mIsBeingDestroyed) { |
10295 | // If this isn't a top-level load and mScriptGlobal's frame element is |
10296 | // null, then the element got removed from the DOM while we were trying |
10297 | // to load this resource. This docshell is scheduled for destruction |
10298 | // already, so bail out here. |
10299 | return NS_OK; |
10300 | } |
10301 | // If we are not being destroyed and we do not have access to the loading |
10302 | // node, then we are a remote subframe. Set the loading principal |
10303 | // to be a null principal and then set it correctly in the parent. |
10304 | loadingPrincipal = NullPrincipal::Create(GetOriginAttributes(), nullptr); |
10305 | } |
10306 | } |
10307 | |
10308 | if (!aLoadState->TriggeringPrincipal()) { |
10309 | 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 10309); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "DoURILoad needs a valid triggeringPrincipal" ")"); do { *(( volatile int*)__null) = 10309; __attribute__((nomerge)) ::abort (); } while (false); } } while (false); |
10310 | return NS_ERROR_FAILURE; |
10311 | } |
10312 | |
10313 | uint32_t sandboxFlags = mBrowsingContext->GetSandboxFlags(); |
10314 | nsSecurityFlags securityFlags = |
10315 | nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL; |
10316 | |
10317 | if (mLoadType == LOAD_ERROR_PAGE) { |
10318 | securityFlags |= nsILoadInfo::SEC_LOAD_ERROR_PAGE; |
10319 | } |
10320 | |
10321 | if (inheritPrincipal) { |
10322 | securityFlags |= nsILoadInfo::SEC_FORCE_INHERIT_PRINCIPAL; |
10323 | } |
10324 | |
10325 | // Must never have a parent for TYPE_DOCUMENT loads |
10326 | 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()" , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 10327); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mBrowsingContext->GetParent()" ")"); do { *((volatile int*)__null) = 10327; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); } } while (false) |
10327 | !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()" , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 10327); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mBrowsingContext->GetParent()" ")"); do { *((volatile int*)__null) = 10327; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); } } while (false); |
10328 | // Subdocuments must have a parent |
10329 | 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()", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 10330); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mBrowsingContext->GetParent()" ")"); do { *((volatile int*)__null) = 10330; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); } } while (false) |
10330 | 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()", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 10330); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mBrowsingContext->GetParent()" ")"); do { *((volatile int*)__null) = 10330; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); } } while (false); |
10331 | mBrowsingContext->SetTriggeringAndInheritPrincipals( |
10332 | aLoadState->TriggeringPrincipal(), aLoadState->PrincipalToInherit(), |
10333 | aLoadState->GetLoadIdentifier()); |
10334 | RefPtr<LoadInfo> loadInfo = |
10335 | (contentPolicyType == nsIContentPolicy::TYPE_DOCUMENT) |
10336 | ? new LoadInfo(loadingWindow, aLoadState->URI(), |
10337 | aLoadState->TriggeringPrincipal(), |
10338 | topLevelLoadingContext, securityFlags, sandboxFlags) |
10339 | : new LoadInfo(loadingPrincipal, aLoadState->TriggeringPrincipal(), |
10340 | loadingNode, securityFlags, contentPolicyType, |
10341 | Maybe<mozilla::dom::ClientInfo>(), |
10342 | Maybe<mozilla::dom::ServiceWorkerDescriptor>(), |
10343 | sandboxFlags); |
10344 | RefPtr<WindowContext> context = mBrowsingContext->GetCurrentWindowContext(); |
10345 | |
10346 | if (isAboutBlankLoadOntoInitialAboutBlank) { |
10347 | // Match the DocumentChannel case where the default for third-partiness |
10348 | // differs from the default in LoadInfo construction here. |
10349 | // toolkit/components/antitracking/test/browser/browser_aboutblank.js |
10350 | // fails without this. |
10351 | BrowsingContext* top = mBrowsingContext->Top(); |
10352 | if (top == mBrowsingContext) { |
10353 | // If we're at the top, this must be a window.open()ed |
10354 | // window, and we can't be third-party relative to ourselves. |
10355 | loadInfo->SetIsThirdPartyContextToTopWindow(false); |
10356 | } else { |
10357 | if (Document* topDoc = top->GetDocument()) { |
10358 | bool thirdParty = false; |
10359 | mozilla::Unused << topDoc->GetPrincipal()->IsThirdPartyPrincipal( |
10360 | aLoadState->PrincipalToInherit(), &thirdParty); |
10361 | loadInfo->SetIsThirdPartyContextToTopWindow(thirdParty); |
10362 | } else { |
10363 | // If top is in a different process, we have to be third-party relative |
10364 | // to it. |
10365 | loadInfo->SetIsThirdPartyContextToTopWindow(true); |
10366 | } |
10367 | } |
10368 | } |
10369 | |
10370 | if (mLoadType != LOAD_ERROR_PAGE && context && context->IsInProcess()) { |
10371 | if (context->HasValidTransientUserGestureActivation()) { |
10372 | aLoadState->SetHasValidUserGestureActivation(true); |
10373 | aLoadState->SetTextDirectiveUserActivation(true); |
10374 | } |
10375 | if (!aLoadState->TriggeringWindowId()) { |
10376 | aLoadState->SetTriggeringWindowId(context->Id()); |
10377 | } |
10378 | if (!aLoadState->TriggeringStorageAccess()) { |
10379 | Document* contextDoc = context->GetExtantDoc(); |
10380 | if (contextDoc) { |
10381 | aLoadState->SetTriggeringStorageAccess( |
10382 | contextDoc->UsingStorageAccess()); |
10383 | } |
10384 | } |
10385 | } |
10386 | |
10387 | // in case this docshell load was triggered by a valid transient user gesture, |
10388 | // or also the load originates from external, then we pass that information on |
10389 | // to the loadinfo, which allows e.g. setting Sec-Fetch-User request headers. |
10390 | if (aLoadState->HasValidUserGestureActivation() || |
10391 | aLoadState->HasLoadFlags(LOAD_FLAGS_FROM_EXTERNAL)) { |
10392 | loadInfo->SetHasValidUserGestureActivation(true); |
10393 | aLoadState->SetTextDirectiveUserActivation(true); |
10394 | } |
10395 | |
10396 | loadInfo->SetTextDirectiveUserActivation( |
10397 | aLoadState->GetTextDirectiveUserActivation()); |
10398 | |
10399 | loadInfo->SetTriggeringWindowId(aLoadState->TriggeringWindowId()); |
10400 | loadInfo->SetTriggeringStorageAccess(aLoadState->TriggeringStorageAccess()); |
10401 | loadInfo->SetTriggeringSandboxFlags(aLoadState->TriggeringSandboxFlags()); |
10402 | loadInfo->SetIsMetaRefresh(aLoadState->IsMetaRefresh()); |
10403 | |
10404 | uint32_t cacheKey = 0; |
10405 | if (aCacheKey) { |
10406 | cacheKey = *aCacheKey; |
10407 | } else if (mozilla::SessionHistoryInParent()) { |
10408 | if (mLoadingEntry) { |
10409 | cacheKey = mLoadingEntry->mInfo.GetCacheKey(); |
10410 | } else if (mActiveEntry) { // for reload cases |
10411 | cacheKey = mActiveEntry->GetCacheKey(); |
10412 | } |
10413 | } else { |
10414 | if (mLSHE) { |
10415 | cacheKey = mLSHE->GetCacheKey(); |
10416 | } else if (mOSHE) { // for reload cases |
10417 | cacheKey = mOSHE->GetCacheKey(); |
10418 | } |
10419 | } |
10420 | |
10421 | bool uriModified; |
10422 | if (mLSHE || mLoadingEntry) { |
10423 | if (mLoadingEntry) { |
10424 | uriModified = mLoadingEntry->mInfo.GetURIWasModified(); |
10425 | } else { |
10426 | uriModified = mLSHE->GetURIWasModified(); |
10427 | } |
10428 | } else { |
10429 | uriModified = false; |
10430 | } |
10431 | |
10432 | bool isEmbeddingBlockedError = false; |
10433 | if (mFailedChannel) { |
10434 | nsresult status; |
10435 | mFailedChannel->GetStatus(&status); |
10436 | isEmbeddingBlockedError = status == NS_ERROR_XFO_VIOLATION || |
10437 | status == NS_ERROR_CSP_FRAME_ANCESTOR_VIOLATION; |
10438 | } |
10439 | |
10440 | nsLoadFlags loadFlags = aLoadState->CalculateChannelLoadFlags( |
10441 | mBrowsingContext, Some(uriModified), Some(isEmbeddingBlockedError)); |
10442 | |
10443 | nsCOMPtr<nsIChannel> channel; |
10444 | if (DocumentChannel::CanUseDocumentChannel(aLoadState->URI()) && |
10445 | !isAboutBlankLoadOntoInitialAboutBlank) { |
10446 | channel = DocumentChannel::CreateForDocument( |
10447 | aLoadState, loadInfo, loadFlags, this, cacheKey, uriModified, |
10448 | isEmbeddingBlockedError); |
10449 | 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", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 10449); AnnotateMozCrashReason("MOZ_ASSERT" "(" "channel" ")" ); do { *((volatile int*)__null) = 10449; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
10450 | |
10451 | // Disable keyword fixup when using DocumentChannel, since |
10452 | // DocumentLoadListener will handle this for us (in the parent process). |
10453 | mAllowKeywordFixup = false; |
10454 | } else if (!CreateAndConfigureRealChannelForLoadState( |
10455 | mBrowsingContext, aLoadState, loadInfo, this, this, |
10456 | GetOriginAttributes(), loadFlags, cacheKey, rv, |
10457 | getter_AddRefs(channel))) { |
10458 | return rv; |
10459 | } |
10460 | |
10461 | // Make sure to give the caller a channel if we managed to create one |
10462 | // This is important for correct error page/session history interaction |
10463 | if (aRequest) { |
10464 | NS_ADDREF(*aRequest = channel)(*aRequest = channel)->AddRef(); |
10465 | } |
10466 | |
10467 | const nsACString& typeHint = aLoadState->TypeHint(); |
10468 | if (!typeHint.IsVoid()) { |
10469 | mContentTypeHint = typeHint; |
10470 | } else { |
10471 | mContentTypeHint.Truncate(); |
10472 | } |
10473 | |
10474 | // Load attributes depend on load type... |
10475 | if (mLoadType == LOAD_RELOAD_CHARSET_CHANGE) { |
10476 | // Use SetAllowStaleCacheContent (not LOAD_FROM_CACHE flag) since we |
10477 | // only want to force cache load for this channel, not the whole |
10478 | // loadGroup. |
10479 | nsCOMPtr<nsICacheInfoChannel> cachingChannel = do_QueryInterface(channel); |
10480 | if (cachingChannel) { |
10481 | cachingChannel->SetAllowStaleCacheContent(true); |
10482 | } |
10483 | } |
10484 | |
10485 | uint32_t openFlags = |
10486 | nsDocShell::ComputeURILoaderFlags(mBrowsingContext, mLoadType); |
10487 | return OpenInitializedChannel(channel, uriLoader, openFlags); |
10488 | } |
10489 | |
10490 | static nsresult AppendSegmentToString(nsIInputStream* aIn, void* aClosure, |
10491 | const char* aFromRawSegment, |
10492 | uint32_t aToOffset, uint32_t aCount, |
10493 | uint32_t* aWriteCount) { |
10494 | // aFromSegment now contains aCount bytes of data. |
10495 | |
10496 | nsAutoCString* buf = static_cast<nsAutoCString*>(aClosure); |
10497 | buf->Append(aFromRawSegment, aCount); |
10498 | |
10499 | // Indicate that we have consumed all of aFromSegment |
10500 | *aWriteCount = aCount; |
10501 | return NS_OK; |
10502 | } |
10503 | |
10504 | /* static */ nsresult nsDocShell::AddHeadersToChannel( |
10505 | nsIInputStream* aHeadersData, nsIChannel* aGenericChannel) { |
10506 | nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aGenericChannel); |
10507 | NS_ENSURE_STATE(httpChannel)do { if ((__builtin_expect(!!(!(httpChannel)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "httpChannel" ") failed" , nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 10507); return NS_ERROR_UNEXPECTED; } } while (false); |
10508 | |
10509 | uint32_t numRead; |
10510 | nsAutoCString headersString; |
10511 | nsresult rv = aHeadersData->ReadSegments( |
10512 | AppendSegmentToString, &headersString, UINT32_MAX(4294967295U), &numRead); |
10513 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 10513); return rv; } } while (false); |
10514 | |
10515 | // used during the manipulation of the String from the InputStream |
10516 | nsAutoCString headerName; |
10517 | nsAutoCString headerValue; |
10518 | int32_t crlf; |
10519 | int32_t colon; |
10520 | |
10521 | // |
10522 | // Iterate over the headersString: for each "\r\n" delimited chunk, |
10523 | // add the value as a header to the nsIHttpChannel |
10524 | // |
10525 | |
10526 | static const char kWhitespace[] = "\b\t\r\n "; |
10527 | while (true) { |
10528 | crlf = headersString.Find("\r\n"); |
10529 | if (crlf == kNotFound) { |
10530 | return NS_OK; |
10531 | } |
10532 | |
10533 | const nsACString& oneHeader = StringHead(headersString, crlf); |
10534 | |
10535 | colon = oneHeader.FindChar(':'); |
10536 | if (colon == kNotFound) { |
10537 | return NS_ERROR_UNEXPECTED; |
10538 | } |
10539 | |
10540 | headerName = StringHead(oneHeader, colon); |
10541 | headerValue = Substring(oneHeader, colon + 1); |
10542 | |
10543 | headerName.Trim(kWhitespace); |
10544 | headerValue.Trim(kWhitespace); |
10545 | |
10546 | headersString.Cut(0, crlf + 2); |
10547 | |
10548 | // |
10549 | // FINALLY: we can set the header! |
10550 | // |
10551 | |
10552 | rv = httpChannel->SetRequestHeader(headerName, headerValue, true); |
10553 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 10553); return rv; } } while (false); |
10554 | } |
10555 | |
10556 | 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 10556); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: " "oops" ")"); do { *((volatile int *)__null) = 10556; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
10557 | return NS_ERROR_UNEXPECTED; |
10558 | } |
10559 | |
10560 | /* static */ uint32_t nsDocShell::ComputeURILoaderFlags( |
10561 | BrowsingContext* aBrowsingContext, uint32_t aLoadType, |
10562 | bool aIsDocumentLoad) { |
10563 | 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" , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 10563); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aBrowsingContext" ")"); do { *((volatile int*)__null) = 10563; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
10564 | |
10565 | uint32_t openFlags = 0; |
10566 | if (aLoadType == LOAD_LINK) { |
10567 | openFlags |= nsIURILoader::IS_CONTENT_PREFERRED; |
10568 | } |
10569 | if (!aBrowsingContext->GetAllowContentRetargeting()) { |
10570 | openFlags |= nsIURILoader::DONT_RETARGET; |
10571 | } |
10572 | |
10573 | // Unless the pref is set, object/embed loads always specify DONT_RETARGET. |
10574 | // See bug 1868001 for details. |
10575 | if (!aIsDocumentLoad && |
10576 | !StaticPrefs::dom_navigation_object_embed_allow_retargeting()) { |
10577 | openFlags |= nsIURILoader::DONT_RETARGET; |
10578 | } |
10579 | |
10580 | return openFlags; |
10581 | } |
10582 | |
10583 | nsresult nsDocShell::OpenInitializedChannel(nsIChannel* aChannel, |
10584 | nsIURILoader* aURILoader, |
10585 | uint32_t aOpenFlags) { |
10586 | nsresult rv = NS_OK; |
10587 | |
10588 | // If anything fails here, make sure to clear our initial ClientSource. |
10589 | auto cleanupInitialClient = |
10590 | MakeScopeExit([&] { mInitialClientSource.reset(); }); |
10591 | |
10592 | nsCOMPtr<nsPIDOMWindowOuter> win = GetWindow(); |
10593 | NS_ENSURE_TRUE(win, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(win)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING , "NS_ENSURE_TRUE(" "win" ") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 10593); return NS_ERROR_FAILURE; } } while (false); |
10594 | |
10595 | MaybeCreateInitialClientSource(); |
10596 | |
10597 | // Let the client channel helper know if we are using DocumentChannel, |
10598 | // since redirects get handled in the parent process in that case. |
10599 | RefPtr<net::DocumentChannel> docChannel = do_QueryObject(aChannel); |
10600 | if (docChannel && XRE_IsContentProcess()) { |
10601 | // Tell the content process nsDocumentOpenInfo to not try to do |
10602 | // any sort of targeting. |
10603 | aOpenFlags |= nsIURILoader::DONT_RETARGET; |
10604 | } |
10605 | |
10606 | // Since we are loading a document we need to make sure the proper reserved |
10607 | // and initial client data is stored on the nsILoadInfo. The |
10608 | // ClientChannelHelper does this and ensures that it is propagated properly |
10609 | // on redirects. We pass no reserved client here so that the helper will |
10610 | // create the reserved ClientSource if necessary. |
10611 | Maybe<ClientInfo> noReservedClient; |
10612 | if (docChannel) { |
10613 | // When using DocumentChannel, all redirect handling is done in the parent, |
10614 | // so we just need the child variant to watch for the internal redirect |
10615 | // to the final channel. |
10616 | rv = AddClientChannelHelperInChild(aChannel, |
10617 | GetMainThreadSerialEventTarget()); |
10618 | docChannel->SetInitialClientInfo(GetInitialClientInfo()); |
10619 | } else { |
10620 | rv = AddClientChannelHelper(aChannel, std::move(noReservedClient), |
10621 | GetInitialClientInfo(), |
10622 | GetMainThreadSerialEventTarget()); |
10623 | } |
10624 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 10624); return rv; } } while (false); |
10625 | |
10626 | rv = aURILoader->OpenURI(aChannel, aOpenFlags, this); |
10627 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 10627); return rv; } } while (false); |
10628 | |
10629 | // We're about to load a new page and it may take time before necko |
10630 | // gives back any data, so main thread might have a chance to process a |
10631 | // collector slice |
10632 | nsJSContext::MaybeRunNextCollectorSlice(this, JS::GCReason::DOCSHELL); |
10633 | |
10634 | // Success. Keep the initial ClientSource if it exists. |
10635 | cleanupInitialClient.release(); |
10636 | |
10637 | return NS_OK; |
10638 | } |
10639 | |
10640 | nsresult nsDocShell::OpenRedirectedChannel(nsDocShellLoadState* aLoadState) { |
10641 | nsCOMPtr<nsIChannel> channel = aLoadState->GetPendingRedirectedChannel(); |
10642 | 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", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 10642); AnnotateMozCrashReason("MOZ_ASSERT" "(" "channel" ")" ); do { *((volatile int*)__null) = 10642; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
10643 | |
10644 | // If anything fails here, make sure to clear our initial ClientSource. |
10645 | auto cleanupInitialClient = |
10646 | MakeScopeExit([&] { mInitialClientSource.reset(); }); |
10647 | |
10648 | nsCOMPtr<nsPIDOMWindowOuter> win = GetWindow(); |
10649 | NS_ENSURE_TRUE(win, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(win)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING , "NS_ENSURE_TRUE(" "win" ") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 10649); return NS_ERROR_FAILURE; } } while (false); |
10650 | |
10651 | MaybeCreateInitialClientSource(); |
10652 | |
10653 | nsCOMPtr<nsILoadInfo> loadInfo = channel->LoadInfo(); |
10654 | |
10655 | LoadInfo* li = static_cast<LoadInfo*>(loadInfo.get()); |
10656 | if (loadInfo->GetExternalContentPolicyType() == |
10657 | ExtContentPolicy::TYPE_DOCUMENT) { |
10658 | li->UpdateBrowsingContextID(mBrowsingContext->Id()); |
10659 | } else if (loadInfo->GetExternalContentPolicyType() == |
10660 | ExtContentPolicy::TYPE_SUBDOCUMENT) { |
10661 | li->UpdateFrameBrowsingContextID(mBrowsingContext->Id()); |
10662 | } |
10663 | |
10664 | // If we did a process switch, then we should have an existing allocated |
10665 | // ClientInfo, so we just need to allocate a corresponding ClientSource. |
10666 | CreateReservedSourceIfNeeded(channel, GetMainThreadSerialEventTarget()); |
10667 | |
10668 | RefPtr<nsDocumentOpenInfo> loader = |
10669 | new nsDocumentOpenInfo(this, nsIURILoader::DONT_RETARGET, nullptr); |
10670 | channel->SetLoadGroup(mLoadGroup); |
10671 | |
10672 | MOZ_ALWAYS_SUCCEEDS(loader->Prepare())do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl (loader->Prepare())), 1)))), 1))) { } else { do { static_assert ( mozilla::detail::AssertionConditionType<decltype(false)> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(false))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("false" " (" "NS_SUCCEEDED(loader->Prepare())" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 10672); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false" ") (" "NS_SUCCEEDED(loader->Prepare())" ")"); do { *((volatile int*)__null) = 10672; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); } } while (false); |
10673 | |
10674 | nsresult rv = NS_OK; |
10675 | if (XRE_IsParentProcess()) { |
10676 | // If we're in the parent, the we don't have an nsIChildChannel, just |
10677 | // the original channel, which is already open in this process. |
10678 | |
10679 | // DocumentLoadListener expects to get an nsIParentChannel, so |
10680 | // we create a wrapper around the channel and nsIStreamListener |
10681 | // that forwards functionality as needed, and then we register |
10682 | // it under the provided identifier. |
10683 | RefPtr<ParentChannelWrapper> wrapper = |
10684 | new ParentChannelWrapper(channel, loader); |
10685 | wrapper->Register(aLoadState->GetPendingRedirectChannelRegistrarId()); |
10686 | |
10687 | mLoadGroup->AddRequest(channel, nullptr); |
10688 | } else if (nsCOMPtr<nsIChildChannel> childChannel = |
10689 | do_QueryInterface(channel)) { |
10690 | // Our channel was redirected from another process, so doesn't need to |
10691 | // be opened again. However, it does need its listener hooked up |
10692 | // correctly. |
10693 | rv = childChannel->CompleteRedirectSetup(loader); |
10694 | } else { |
10695 | // It's possible for the redirected channel to not implement |
10696 | // nsIChildChannel and be entirely local (like srcdoc). In that case we |
10697 | // can just open the local instance and it will work. |
10698 | rv = channel->AsyncOpen(loader); |
10699 | } |
10700 | if (rv == NS_ERROR_NO_CONTENT) { |
10701 | return NS_OK; |
10702 | } |
10703 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 10703); return rv; } } while (false); |
10704 | |
10705 | // Success. Keep the initial ClientSource if it exists. |
10706 | cleanupInitialClient.release(); |
10707 | return NS_OK; |
10708 | } |
10709 | |
10710 | // https://html.spec.whatwg.org/#scrolling-to-a-fragment |
10711 | nsresult nsDocShell::ScrollToAnchor(bool aCurHasRef, bool aNewHasRef, |
10712 | nsACString& aNewHash, uint32_t aLoadType) { |
10713 | if (!mCurrentURI) { |
10714 | return NS_OK; |
10715 | } |
10716 | |
10717 | RefPtr<PresShell> presShell = GetPresShell(); |
10718 | if (!presShell) { |
10719 | // If we failed to get the shell, or if there is no shell, |
10720 | // nothing left to do here. |
10721 | return NS_OK; |
10722 | } |
10723 | |
10724 | ScrollContainerFrame* rootScroll = presShell->GetRootScrollContainerFrame(); |
10725 | if (rootScroll) { |
10726 | rootScroll->ClearDidHistoryRestore(); |
10727 | } |
10728 | |
10729 | // If it's a load from history, we don't have any anchor jumping to do. |
10730 | // Scrollbar position will be restored by the caller based on positions stored |
10731 | // in session history. |
10732 | bool scroll = aLoadType != LOAD_HISTORY && aLoadType != LOAD_RELOAD_NORMAL; |
10733 | // If the load contains text directives, try to apply them. This may fail if |
10734 | // the load is a same-document load that was initiated before the document was |
10735 | // fully loaded and the target is not yet included in the DOM tree. |
10736 | // For this case, the `uninvokedTextDirectives` are not cleared, so that |
10737 | // `Document::ScrollToRef()` can re-apply the text directive. |
10738 | // `Document::ScrollToRef()` is (presumably) the second "async" call mentioned |
10739 | // in sec. 7.4.2.3.3 in the HTML spec, "Fragment navigations": |
10740 | // https://html.spec.whatwg.org/#scroll-to-fragid:~:text=This%20algorithm%20will%20be%20called%20twice |
10741 | |
10742 | const RefPtr fragmentDirective = GetDocument()->FragmentDirective(); |
10743 | const nsTArray<RefPtr<nsRange>> textDirectiveRanges = |
10744 | fragmentDirective->FindTextFragmentsInDocument(); |
10745 | fragmentDirective->HighlightTextDirectives(textDirectiveRanges); |
10746 | const bool scrollToTextDirective = |
10747 | !textDirectiveRanges.IsEmpty() && |
10748 | fragmentDirective->IsTextDirectiveAllowedToBeScrolledTo(); |
10749 | const RefPtr<nsRange> textDirectiveToScroll = |
10750 | scrollToTextDirective ? textDirectiveRanges[0] : nullptr; |
10751 | |
10752 | // If we have no new anchor, we do not want to scroll, unless there is a |
10753 | // current anchor and we are doing a history load. So return if we have no |
10754 | // new anchor, and there is no current anchor or the load is not a history |
10755 | // load. |
10756 | if ((!aCurHasRef || aLoadType != LOAD_HISTORY) && !aNewHasRef && |
10757 | !scrollToTextDirective) { |
10758 | return NS_OK; |
10759 | } |
10760 | |
10761 | // Both the new and current URIs refer to the same page. We can now |
10762 | // browse to the hash stored in the new URI. |
10763 | |
10764 | if (aNewHash.IsEmpty() && !scrollToTextDirective) { |
10765 | // 2. If fragment is the empty string, then return the special value top of |
10766 | // the document. |
10767 | // |
10768 | // Tell the shell it's at an anchor without scrolling. |
10769 | presShell->GoToAnchor(u""_ns, nullptr, false); |
10770 | |
10771 | if (scroll) { |
10772 | // Scroll to the top of the page. Ignore the return value; failure to |
10773 | // scroll here (e.g. if there is no root scrollframe) is not grounds for |
10774 | // canceling the load! |
10775 | SetCurScrollPosEx(0, 0); |
10776 | } |
10777 | |
10778 | return NS_OK; |
10779 | } |
10780 | |
10781 | // 3. Let potentialIndicatedElement be the result of finding a potential |
10782 | // indicated element given document and fragment. |
10783 | NS_ConvertUTF8toUTF16 uStr(aNewHash); |
10784 | |
10785 | 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" , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 10785); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!uStr.IsEmpty() || scrollToTextDirective" ")"); do { *((volatile int*)__null) = 10785; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
10786 | |
10787 | auto rv = presShell->GoToAnchor(uStr, textDirectiveToScroll, scroll, |
10788 | ScrollFlags::ScrollSmoothAuto); |
10789 | |
10790 | // 4. If potentialIndicatedElement is not null, then return |
10791 | // potentialIndicatedElement. |
10792 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) { |
10793 | return NS_OK; |
10794 | } |
10795 | |
10796 | // 5. Let fragmentBytes be the result of percent-decoding fragment. |
10797 | nsAutoCString fragmentBytes; |
10798 | const bool unescaped = NS_UnescapeURL(aNewHash.Data(), aNewHash.Length(), |
10799 | /* aFlags = */ 0, fragmentBytes); |
10800 | |
10801 | if (!unescaped) { |
10802 | // Another attempt is only necessary if characters were unescaped. |
10803 | return NS_OK; |
10804 | } |
10805 | |
10806 | if (fragmentBytes.IsEmpty()) { |
10807 | // When aNewHash contains "%00", the unescaped string may be empty, and |
10808 | // GoToAnchor asserts if we ask it to scroll to an empty ref. |
10809 | presShell->GoToAnchor(u""_ns, nullptr, false); |
10810 | return NS_OK; |
10811 | } |
10812 | |
10813 | // 6. Let decodedFragment be the result of running UTF-8 decode without BOM on |
10814 | // fragmentBytes. |
10815 | nsAutoString decodedFragment; |
10816 | rv = UTF_8_ENCODING->DecodeWithoutBOMHandling(fragmentBytes, decodedFragment); |
10817 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 10817); return rv; } } while (false); |
10818 | |
10819 | // 7. Set potentialIndicatedElement to the result of finding a potential |
10820 | // indicated element given document and decodedFragment. |
10821 | // |
10822 | // Ignore the return value of GoToAnchor, since it will return an error if |
10823 | // there is no such anchor in the document, which is actually a success |
10824 | // condition for us (we want to update the session history with the new URI no |
10825 | // matter whether we actually scrolled somewhere). |
10826 | presShell->GoToAnchor(decodedFragment, nullptr, scroll, |
10827 | ScrollFlags::ScrollSmoothAuto); |
10828 | |
10829 | return NS_OK; |
10830 | } |
10831 | |
10832 | bool nsDocShell::OnNewURI(nsIURI* aURI, nsIChannel* aChannel, |
10833 | nsIPrincipal* aTriggeringPrincipal, |
10834 | nsIPrincipal* aPrincipalToInherit, |
10835 | nsIPrincipal* aPartitionedPrincipalToInherit, |
10836 | nsIContentSecurityPolicy* aCsp, |
10837 | bool aAddToGlobalHistory, bool aCloneSHChildren) { |
10838 | 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 10838); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aURI" ") (" "uri is null" ")"); do { *((volatile int*)__null) = 10838; __attribute__ ((nomerge)) ::abort(); } while (false); } } while (false); |
10839 | 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 10839); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aChannel || !aTriggeringPrincipal" ") (" "Shouldn't have both set" ")"); do { *((volatile int*) __null) = 10839; __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); |
10840 | |
10841 | 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)" , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 10842); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aPrincipalToInherit || (aPrincipalToInherit && aTriggeringPrincipal)" ")"); do { *((volatile int*)__null) = 10842; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false) |
10842 | (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)" , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 10842); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aPrincipalToInherit || (aPrincipalToInherit && aTriggeringPrincipal)" ")"); do { *((volatile int*)__null) = 10842; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
10843 | |
10844 | #if defined(DEBUG1) |
10845 | if (MOZ_LOG_TEST(gDocShellLog, LogLevel::Debug)(__builtin_expect(!!(mozilla::detail::log_test(gDocShellLog, LogLevel ::Debug)), 0))) { |
10846 | nsAutoCString chanName; |
10847 | if (aChannel) { |
10848 | aChannel->GetName(chanName); |
10849 | } else { |
10850 | chanName.AssignLiteral("<no channel>"); |
10851 | } |
10852 | |
10853 | 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) |
10854 | ("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) |
10855 | 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); |
10856 | } |
10857 | #endif |
10858 | |
10859 | bool equalUri = false; |
10860 | |
10861 | // Get the post data and the HTTP response code from the channel. |
10862 | uint32_t responseStatus = 0; |
10863 | nsCOMPtr<nsIInputStream> inputStream; |
10864 | if (aChannel) { |
10865 | nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(aChannel)); |
10866 | |
10867 | // Check if the HTTPChannel is hiding under a multiPartChannel |
10868 | if (!httpChannel) { |
10869 | GetHttpChannel(aChannel, getter_AddRefs(httpChannel)); |
10870 | } |
10871 | |
10872 | if (httpChannel) { |
10873 | nsCOMPtr<nsIUploadChannel> uploadChannel(do_QueryInterface(httpChannel)); |
10874 | if (uploadChannel) { |
10875 | uploadChannel->GetUploadStream(getter_AddRefs(inputStream)); |
10876 | } |
10877 | |
10878 | // If the response status indicates an error, unlink this session |
10879 | // history entry from any entries sharing its document. |
10880 | nsresult rv = httpChannel->GetResponseStatus(&responseStatus); |
10881 | if (mLSHE && NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && responseStatus >= 400) { |
10882 | mLSHE->AbandonBFCacheEntry(); |
10883 | // FIXME Do the same for mLoadingEntry |
10884 | } |
10885 | } |
10886 | } |
10887 | |
10888 | // Determine if this type of load should update history. |
10889 | bool updateGHistory = ShouldUpdateGlobalHistory(mLoadType); |
10890 | |
10891 | // We don't update session history on reload unless we're loading |
10892 | // an iframe in shift-reload case. |
10893 | bool updateSHistory = mBrowsingContext->ShouldUpdateSessionHistory(mLoadType); |
10894 | |
10895 | // Create SH Entry (mLSHE) only if there is a SessionHistory object in the |
10896 | // root browsing context. |
10897 | // FIXME If session history in the parent is enabled then we only do this if |
10898 | // the session history object is in process, otherwise we can't really |
10899 | // use the mLSHE anyway. Once session history is only stored in the |
10900 | // parent then this code will probably be removed anyway. |
10901 | RefPtr<ChildSHistory> rootSH = GetRootSessionHistory(); |
10902 | if (!rootSH) { |
10903 | updateSHistory = false; |
10904 | updateGHistory = false; // XXX Why global history too? |
10905 | } |
10906 | |
10907 | // Check if the url to be loaded is the same as the one already loaded. |
10908 | if (mCurrentURI) { |
10909 | aURI->Equals(mCurrentURI, &equalUri); |
10910 | } |
10911 | |
10912 | #ifdef DEBUG1 |
10913 | bool shAvailable = (rootSH != nullptr); |
10914 | |
10915 | // XXX This log message is almost useless because |updateSHistory| |
10916 | // and |updateGHistory| are not correct at this point. |
10917 | |
10918 | 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) |
10919 | (" 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) |
10920 | " 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) |
10921 | 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); |
10922 | #endif |
10923 | |
10924 | /* If the url to be loaded is the same as the one already there, |
10925 | * and the original loadType is LOAD_NORMAL, LOAD_LINK, or |
10926 | * LOAD_STOP_CONTENT, set loadType to LOAD_NORMAL_REPLACE so that |
10927 | * AddToSessionHistory() won't mess with the current SHEntry and |
10928 | * if this page has any frame children, it also will be handled |
10929 | * properly. see bug 83684 |
10930 | * |
10931 | * NB: If mOSHE is null but we have a current URI, then it probably |
10932 | * means that we must be at the transient about:blank content viewer; |
10933 | * we should let the normal load continue, since there's nothing to |
10934 | * replace. Sometimes this happens after a session restore (eg process |
10935 | * switch) and mCurrentURI is not about:blank; we assume we can let the load |
10936 | * continue (Bug 1301399). |
10937 | * |
10938 | * XXX Hopefully changing the loadType at this time will not hurt |
10939 | * anywhere. The other way to take care of sequentially repeating |
10940 | * frameset pages is to add new methods to nsIDocShellTreeItem. |
10941 | * Hopefully I don't have to do that. |
10942 | */ |
10943 | if (equalUri && |
10944 | (mozilla::SessionHistoryInParent() ? !!mActiveEntry : !!mOSHE) && |
10945 | (mLoadType == LOAD_NORMAL || mLoadType == LOAD_LINK || |
10946 | mLoadType == LOAD_STOP_CONTENT) && |
10947 | !inputStream) { |
10948 | mLoadType = LOAD_NORMAL_REPLACE; |
10949 | } |
10950 | |
10951 | // If this is a refresh to the currently loaded url, we don't |
10952 | // have to update session or global history. |
10953 | if (mLoadType == LOAD_REFRESH && !inputStream && equalUri) { |
10954 | SetHistoryEntryAndUpdateBC(Some<nsISHEntry*>(mOSHE), Nothing()); |
10955 | } |
10956 | |
10957 | /* If the user pressed shift-reload, cache will create a new cache key |
10958 | * for the page. Save the new cacheKey in Session History. |
10959 | * see bug 90098 |
10960 | */ |
10961 | if (aChannel && IsForceReloadType(mLoadType)) { |
10962 | 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!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 10964); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!updateSHistory || IsSubframe()" ") (" "We shouldn't be updating session history for forced" " reloads unless we're in a newly created iframe!" ")"); do { *((volatile int*)__null) = 10964; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false) |
10963 | "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!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 10964); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!updateSHistory || IsSubframe()" ") (" "We shouldn't be updating session history for forced" " reloads unless we're in a newly created iframe!" ")"); do { *((volatile int*)__null) = 10964; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false) |
10964 | " 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!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 10964); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!updateSHistory || IsSubframe()" ") (" "We shouldn't be updating session history for forced" " reloads unless we're in a newly created iframe!" ")"); do { *((volatile int*)__null) = 10964; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
10965 | |
10966 | nsCOMPtr<nsICacheInfoChannel> cacheChannel(do_QueryInterface(aChannel)); |
10967 | uint32_t cacheKey = 0; |
10968 | // Get the Cache Key and store it in SH. |
10969 | if (cacheChannel) { |
10970 | cacheChannel->GetCacheKey(&cacheKey); |
10971 | } |
10972 | // If we already have a loading history entry, store the new cache key |
10973 | // in it. Otherwise, since we're doing a reload and won't be updating |
10974 | // our history entry, store the cache key in our current history entry. |
10975 | SetCacheKeyOnHistoryEntry(mLSHE ? mLSHE : mOSHE, cacheKey); |
10976 | |
10977 | if (!mozilla::SessionHistoryInParent()) { |
10978 | // Since we're force-reloading, clear all the sub frame history. |
10979 | ClearFrameHistory(mLSHE); |
10980 | ClearFrameHistory(mOSHE); |
10981 | } |
10982 | } |
10983 | |
10984 | if (!mozilla::SessionHistoryInParent()) { |
10985 | // Clear subframe history on refresh. |
10986 | // XXX: history.go(0) won't go this path as mLoadType is LOAD_HISTORY in |
10987 | // this case. One should re-validate after bug 1331865 fixed. |
10988 | if (mLoadType == LOAD_REFRESH) { |
10989 | ClearFrameHistory(mLSHE); |
10990 | ClearFrameHistory(mOSHE); |
10991 | } |
10992 | |
10993 | if (updateSHistory) { |
10994 | // Update session history if necessary... |
10995 | if (!mLSHE && (mItemType == typeContent) && mURIResultedInDocument) { |
10996 | /* This is a fresh page getting loaded for the first time |
10997 | *.Create a Entry for it and add it to SH, if this is the |
10998 | * rootDocShell |
10999 | */ |
11000 | (void)AddToSessionHistory(aURI, aChannel, aTriggeringPrincipal, |
11001 | aPrincipalToInherit, |
11002 | aPartitionedPrincipalToInherit, aCsp, |
11003 | aCloneSHChildren, getter_AddRefs(mLSHE)); |
11004 | } |
11005 | } else if (GetSessionHistory() && mLSHE && mURIResultedInDocument) { |
11006 | // Even if we don't add anything to SHistory, ensure the current index |
11007 | // points to the same SHEntry as our mLSHE. |
11008 | |
11009 | GetSessionHistory()->LegacySHistory()->EnsureCorrectEntryAtCurrIndex( |
11010 | mLSHE); |
11011 | } |
11012 | } |
11013 | |
11014 | // If this is a POST request, we do not want to include this in global |
11015 | // history. |
11016 | if (ShouldAddURIVisit(aChannel) && updateGHistory && aAddToGlobalHistory && |
11017 | !net::ChannelIsPost(aChannel)) { |
11018 | nsCOMPtr<nsIURI> previousURI; |
11019 | uint32_t previousFlags = 0; |
11020 | |
11021 | if (mLoadType & LOAD_CMD_RELOAD) { |
11022 | // On a reload request, we don't set redirecting flags. |
11023 | previousURI = aURI; |
11024 | } else { |
11025 | ExtractLastVisit(aChannel, getter_AddRefs(previousURI), &previousFlags); |
11026 | } |
11027 | |
11028 | AddURIVisit(aURI, previousURI, previousFlags, responseStatus); |
11029 | } |
11030 | |
11031 | // If this was a history load or a refresh, or it was a history load but |
11032 | // later changed to LOAD_NORMAL_REPLACE due to redirection, update the index |
11033 | // in session history. |
11034 | if (!mozilla::SessionHistoryInParent() && rootSH && |
11035 | ((mLoadType & (LOAD_CMD_HISTORY | LOAD_CMD_RELOAD)) || |
11036 | mLoadType == LOAD_NORMAL_REPLACE || mLoadType == LOAD_REFRESH_REPLACE)) { |
11037 | mPreviousEntryIndex = rootSH->Index(); |
11038 | if (!mozilla::SessionHistoryInParent()) { |
11039 | rootSH->LegacySHistory()->UpdateIndex(); |
11040 | } |
11041 | mLoadedEntryIndex = rootSH->Index(); |
11042 | 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) |
11043 | ("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) |
11044 | 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); |
11045 | } |
11046 | |
11047 | // aCloneSHChildren exactly means "we are not loading a new document". |
11048 | uint32_t locationFlags = |
11049 | aCloneSHChildren ? uint32_t(LOCATION_CHANGE_SAME_DOCUMENT) : 0; |
11050 | |
11051 | bool onLocationChangeNeeded = |
11052 | SetCurrentURI(aURI, aChannel, false, |
11053 | /* aIsInitialAboutBlank */ false, locationFlags); |
11054 | // Make sure to store the referrer from the channel, if any |
11055 | nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(aChannel)); |
11056 | if (httpChannel) { |
11057 | mReferrerInfo = httpChannel->GetReferrerInfo(); |
11058 | } |
11059 | return onLocationChangeNeeded; |
11060 | } |
11061 | |
11062 | Maybe<Wireframe> nsDocShell::GetWireframe() { |
11063 | const bool collectWireFrame = |
11064 | mozilla::SessionHistoryInParent() && |
11065 | StaticPrefs::browser_history_collectWireframes() && |
11066 | mBrowsingContext->IsTopContent() && mActiveEntry; |
11067 | |
11068 | if (!collectWireFrame) { |
11069 | return Nothing(); |
11070 | } |
11071 | |
11072 | RefPtr<Document> doc = mDocumentViewer->GetDocument(); |
11073 | Nullable<Wireframe> wireframe; |
11074 | doc->GetWireframeWithoutFlushing(false, wireframe); |
11075 | if (wireframe.IsNull()) { |
11076 | return Nothing(); |
11077 | } |
11078 | return Some(wireframe.Value()); |
11079 | } |
11080 | |
11081 | bool nsDocShell::CollectWireframe() { |
11082 | Maybe<Wireframe> wireframe = GetWireframe(); |
11083 | if (wireframe.isNothing()) { |
11084 | return false; |
11085 | } |
11086 | |
11087 | if (XRE_IsParentProcess()) { |
11088 | SessionHistoryEntry* entry = |
11089 | mBrowsingContext->Canonical()->GetActiveSessionHistoryEntry(); |
11090 | if (entry) { |
11091 | entry->SetWireframe(wireframe); |
11092 | } |
11093 | } else { |
11094 | mozilla::Unused |
11095 | << ContentChild::GetSingleton()->SendSessionHistoryEntryWireframe( |
11096 | mBrowsingContext, wireframe.ref()); |
11097 | } |
11098 | |
11099 | return true; |
11100 | } |
11101 | |
11102 | //***************************************************************************** |
11103 | // nsDocShell: Session History |
11104 | //***************************************************************************** |
11105 | |
11106 | NS_IMETHODIMPnsresult |
11107 | nsDocShell::AddState(JS::Handle<JS::Value> aData, const nsAString& aTitle, |
11108 | const nsAString& aURL, bool aReplace, JSContext* aCx) { |
11109 | 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) |
11110 | ("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) |
11111 | 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) |
11112 | 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); |
11113 | // Implements History.pushState and History.replaceState |
11114 | |
11115 | // Here's what we do, roughly in the order specified by HTML5. The specific |
11116 | // steps we are executing are at |
11117 | // <https://html.spec.whatwg.org/multipage/history.html#dom-history-pushstate> |
11118 | // and |
11119 | // <https://html.spec.whatwg.org/multipage/history.html#url-and-history-update-steps>. |
11120 | // This function basically implements #dom-history-pushstate and |
11121 | // UpdateURLAndHistory implements #url-and-history-update-steps. |
11122 | // |
11123 | // A. Serialize aData using structured clone. This is #dom-history-pushstate |
11124 | // step 5. |
11125 | // B. If the third argument is present, #dom-history-pushstate step 7. |
11126 | // 7.1. Resolve the url, relative to our document. |
11127 | // 7.2. If (a) fails, raise a SECURITY_ERR |
11128 | // 7.4. Compare the resulting absolute URL to the document's address. If |
11129 | // any part of the URLs difer other than the <path>, <query>, and |
11130 | // <fragment> components, raise a SECURITY_ERR and abort. |
11131 | // C. If !aReplace, #url-and-history-update-steps steps 2.1-2.3: |
11132 | // Remove from the session history all entries after the current entry, |
11133 | // as we would after a regular navigation, and save the current |
11134 | // entry's scroll position (bug 590573). |
11135 | // D. #url-and-history-update-steps step 2.4 or step 3. As apropriate, |
11136 | // either add a state object entry to the session history after the |
11137 | // current entry with the following properties, or modify the current |
11138 | // session history entry to set |
11139 | // a. cloned data as the state object, |
11140 | // b. if the third argument was present, the absolute URL found in |
11141 | // step 2 |
11142 | // Also clear the new history entry's POST data (see bug 580069). |
11143 | // E. If aReplace is false (i.e. we're doing a pushState instead of a |
11144 | // replaceState), notify bfcache that we've navigated to a new page. |
11145 | // F. If the third argument is present, set the document's current address |
11146 | // to the absolute URL found in step B. This is |
11147 | // #url-and-history-update-steps step 4. |
11148 | // |
11149 | // It's important that this function not run arbitrary scripts after step A |
11150 | // and before completing step E. For example, if a script called |
11151 | // history.back() before we completed step E, bfcache might destroy an |
11152 | // active content viewer. Since EvictOutOfRangeDocumentViewers at the end of |
11153 | // step E might run script, we can't just put a script blocker around the |
11154 | // critical section. |
11155 | // |
11156 | // Note that we completely ignore the aTitle parameter. |
11157 | |
11158 | nsresult rv; |
11159 | |
11160 | // Don't clobber the load type of an existing network load. |
11161 | AutoRestore<uint32_t> loadTypeResetter(mLoadType); |
11162 | |
11163 | // pushState effectively becomes replaceState when we've started a network |
11164 | // load but haven't adopted its document yet. This mirrors what we do with |
11165 | // changes to the hash at this stage of the game. |
11166 | if (JustStartedNetworkLoad()) { |
11167 | aReplace = true; |
11168 | } |
11169 | |
11170 | RefPtr<Document> document = GetDocument(); |
11171 | NS_ENSURE_TRUE(document, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(document)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "document" ") failed", nullptr , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 11171); return NS_ERROR_FAILURE; } } while (false); |
11172 | |
11173 | // Step A: Serialize aData using structured clone. |
11174 | // https://html.spec.whatwg.org/multipage/history.html#dom-history-pushstate |
11175 | // step 5. |
11176 | nsCOMPtr<nsIStructuredCloneContainer> scContainer; |
11177 | |
11178 | // scContainer->Init might cause arbitrary JS to run, and this code might |
11179 | // navigate the page we're on, potentially to a different origin! (bug |
11180 | // 634834) To protect against this, we abort if our principal changes due |
11181 | // to the InitFromJSVal() call. |
11182 | { |
11183 | RefPtr<Document> origDocument = GetDocument(); |
11184 | if (!origDocument) { |
11185 | return NS_ERROR_DOM_SECURITY_ERR; |
11186 | } |
11187 | nsCOMPtr<nsIPrincipal> origPrincipal = origDocument->NodePrincipal(); |
11188 | |
11189 | scContainer = new nsStructuredCloneContainer(); |
11190 | rv = scContainer->InitFromJSVal(aData, aCx); |
11191 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 11191); return rv; } } while (false); |
11192 | |
11193 | RefPtr<Document> newDocument = GetDocument(); |
11194 | if (!newDocument) { |
11195 | return NS_ERROR_DOM_SECURITY_ERR; |
11196 | } |
11197 | nsCOMPtr<nsIPrincipal> newPrincipal = newDocument->NodePrincipal(); |
11198 | |
11199 | bool principalsEqual = false; |
11200 | origPrincipal->Equals(newPrincipal, &principalsEqual); |
11201 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 11201); return NS_ERROR_DOM_SECURITY_ERR; } } while (false); |
11202 | } |
11203 | |
11204 | // Check that the state object isn't too long. |
11205 | int32_t maxStateObjSize = StaticPrefs::browser_history_maxStateObjectSize(); |
11206 | if (maxStateObjSize < 0) { |
11207 | maxStateObjSize = 0; |
11208 | } |
11209 | |
11210 | uint64_t scSize; |
11211 | rv = scContainer->GetSerializedNBytes(&scSize); |
11212 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 11212); return rv; } } while (false); |
11213 | |
11214 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 11214); return NS_ERROR_ILLEGAL_VALUE; } } while (false); |
11215 | |
11216 | // Step B: Resolve aURL. |
11217 | // https://html.spec.whatwg.org/multipage/history.html#dom-history-pushstate |
11218 | // step 7. |
11219 | bool equalURIs = true; |
11220 | nsCOMPtr<nsIURI> currentURI; |
11221 | if (mCurrentURI) { |
11222 | currentURI = nsIOService::CreateExposableURI(mCurrentURI); |
11223 | } else { |
11224 | currentURI = mCurrentURI; |
11225 | } |
11226 | nsCOMPtr<nsIURI> newURI; |
11227 | if (aURL.Length() == 0) { |
11228 | newURI = currentURI; |
11229 | } else { |
11230 | // 7.1: Resolve aURL relative to mURI |
11231 | |
11232 | nsIURI* docBaseURI = document->GetDocBaseURI(); |
11233 | if (!docBaseURI) { |
11234 | return NS_ERROR_FAILURE; |
11235 | } |
11236 | |
11237 | nsAutoCString spec; |
11238 | docBaseURI->GetSpec(spec); |
11239 | |
11240 | rv = NS_NewURI(getter_AddRefs(newURI), aURL, |
11241 | document->GetDocumentCharacterSet(), docBaseURI); |
11242 | |
11243 | // 7.2: If 2a fails, raise a SECURITY_ERR |
11244 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
11245 | return NS_ERROR_DOM_SECURITY_ERR; |
11246 | } |
11247 | |
11248 | // 7.4 and 7.5: Same-origin check. |
11249 | if (!nsContentUtils::URIIsLocalFile(newURI)) { |
11250 | // In addition to checking that the security manager says that |
11251 | // the new URI has the same origin as our current URI, we also |
11252 | // check that the two URIs have the same userpass. (The |
11253 | // security manager says that |http://foo.com| and |
11254 | // |http://me@foo.com| have the same origin.) currentURI |
11255 | // won't contain the password part of the userpass, so this |
11256 | // means that it's never valid to specify a password in a |
11257 | // pushState or replaceState URI. |
11258 | |
11259 | nsCOMPtr<nsIScriptSecurityManager> secMan = |
11260 | do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID"@mozilla.org/scriptsecuritymanager;1"); |
11261 | NS_ENSURE_TRUE(secMan, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(secMan)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "secMan" ") failed", nullptr , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 11261); return NS_ERROR_FAILURE; } } while (false); |
11262 | |
11263 | // It's very important that we check that newURI is of the same |
11264 | // origin as currentURI, not docBaseURI, because a page can |
11265 | // set docBaseURI arbitrarily to any domain. |
11266 | nsAutoCString currentUserPass, newUserPass; |
11267 | NS_ENSURE_SUCCESS(currentURI->GetUserPass(currentUserPass),do { nsresult __rv = currentURI->GetUserPass(currentUserPass ); if (((bool)(__builtin_expect(!!(NS_FAILED_impl(__rv)), 0)) )) { const char* name = mozilla::GetStaticErrorName(__rv); mozilla ::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "currentURI->GetUserPass(currentUserPass)" , "NS_ERROR_FAILURE", static_cast<uint32_t>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""); NS_DebugBreak (NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 11268); return NS_ERROR_FAILURE; } } while (false) |
11268 | NS_ERROR_FAILURE)do { nsresult __rv = currentURI->GetUserPass(currentUserPass ); if (((bool)(__builtin_expect(!!(NS_FAILED_impl(__rv)), 0)) )) { const char* name = mozilla::GetStaticErrorName(__rv); mozilla ::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "currentURI->GetUserPass(currentUserPass)" , "NS_ERROR_FAILURE", static_cast<uint32_t>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""); NS_DebugBreak (NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 11268); return NS_ERROR_FAILURE; } } while (false); |
11269 | NS_ENSURE_SUCCESS(newURI->GetUserPass(newUserPass), NS_ERROR_FAILURE)do { nsresult __rv = newURI->GetUserPass(newUserPass); if ( ((bool)(__builtin_expect(!!(NS_FAILED_impl(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "newURI->GetUserPass(newUserPass)" , "NS_ERROR_FAILURE", static_cast<uint32_t>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""); NS_DebugBreak (NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 11269); return NS_ERROR_FAILURE; } } while (false); |
11270 | bool isPrivateWin = |
11271 | document->NodePrincipal()->OriginAttributesRef().IsPrivateBrowsing(); |
11272 | if (NS_FAILED(secMan->CheckSameOriginURI(currentURI, newURI, true,((bool)(__builtin_expect(!!(NS_FAILED_impl(secMan->CheckSameOriginURI (currentURI, newURI, true, isPrivateWin))), 0))) |
11273 | isPrivateWin))((bool)(__builtin_expect(!!(NS_FAILED_impl(secMan->CheckSameOriginURI (currentURI, newURI, true, isPrivateWin))), 0))) || |
11274 | !currentUserPass.Equals(newUserPass)) { |
11275 | return NS_ERROR_DOM_SECURITY_ERR; |
11276 | } |
11277 | } else { |
11278 | // It's a file:// URI |
11279 | nsCOMPtr<nsIPrincipal> principal = document->GetPrincipal(); |
11280 | |
11281 | if (!principal || NS_FAILED(principal->CheckMayLoadWithReporting(((bool)(__builtin_expect(!!(NS_FAILED_impl(principal->CheckMayLoadWithReporting ( newURI, false, document->InnerWindowID()))), 0))) |
11282 | newURI, false, document->InnerWindowID()))((bool)(__builtin_expect(!!(NS_FAILED_impl(principal->CheckMayLoadWithReporting ( newURI, false, document->InnerWindowID()))), 0)))) { |
11283 | return NS_ERROR_DOM_SECURITY_ERR; |
11284 | } |
11285 | } |
11286 | |
11287 | if (currentURI) { |
11288 | currentURI->Equals(newURI, &equalURIs); |
11289 | } else { |
11290 | equalURIs = false; |
11291 | } |
11292 | |
11293 | } // end of same-origin check |
11294 | |
11295 | // Step 8: call "URL and history update steps" |
11296 | rv = UpdateURLAndHistory(document, newURI, scContainer, aTitle, aReplace, |
11297 | currentURI, equalURIs); |
11298 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 11298); return rv; } } while (false); |
11299 | |
11300 | return NS_OK; |
11301 | } |
11302 | |
11303 | nsresult nsDocShell::UpdateURLAndHistory(Document* aDocument, nsIURI* aNewURI, |
11304 | nsIStructuredCloneContainer* aData, |
11305 | const nsAString& aTitle, bool aReplace, |
11306 | nsIURI* aCurrentURI, bool aEqualURIs) { |
11307 | // Implements |
11308 | // https://html.spec.whatwg.org/multipage/history.html#url-and-history-update-steps |
11309 | |
11310 | // If we have a pending title change, handle it before creating a new entry. |
11311 | aDocument->DoNotifyPossibleTitleChange(); |
11312 | |
11313 | // Step 2, if aReplace is false: Create a new entry in the session |
11314 | // history. This will erase all SHEntries after the new entry and make this |
11315 | // entry the current one. This operation may modify mOSHE, which we need |
11316 | // later, so we keep a reference here. |
11317 | NS_ENSURE_TRUE(mOSHE || mActiveEntry || aReplace, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(mOSHE || mActiveEntry || aReplace )), 0))) { NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "mOSHE || mActiveEntry || aReplace" ") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 11317); return NS_ERROR_FAILURE; } } while (false); |
11318 | nsCOMPtr<nsISHEntry> oldOSHE = mOSHE; |
11319 | |
11320 | // If this push/replaceState changed the document's current URI and the new |
11321 | // URI differs from the old URI in more than the hash, or if the old |
11322 | // SHEntry's URI was modified in this way by a push/replaceState call |
11323 | // set URIWasModified to true for the current SHEntry (bug 669671). |
11324 | bool sameExceptHashes = true; |
11325 | aNewURI->EqualsExceptRef(aCurrentURI, &sameExceptHashes); |
11326 | bool uriWasModified; |
11327 | if (sameExceptHashes) { |
11328 | if (mozilla::SessionHistoryInParent()) { |
11329 | uriWasModified = mActiveEntry && mActiveEntry->GetURIWasModified(); |
11330 | } else { |
11331 | uriWasModified = oldOSHE && oldOSHE->GetURIWasModified(); |
11332 | } |
11333 | } else { |
11334 | uriWasModified = true; |
11335 | } |
11336 | |
11337 | mLoadType = LOAD_PUSHSTATE; |
11338 | |
11339 | nsCOMPtr<nsISHEntry> newSHEntry; |
11340 | if (!aReplace) { |
11341 | // Step 2. |
11342 | |
11343 | // Step 2.2, "Remove any tasks queued by the history traversal task |
11344 | // source that are associated with any Document objects in the |
11345 | // top-level browsing context's document family." This is very hard in |
11346 | // SessionHistoryInParent since we can't synchronously access the |
11347 | // pending navigations that are already sent to the parent. We can |
11348 | // abort any AsyncGo navigations that are waiting to be sent. If we |
11349 | // send a message to the parent, it would be processed after any |
11350 | // navigations previously sent. So long as we consider the "history |
11351 | // traversal task source" to be the list in this process we match the |
11352 | // spec. If we move the entire list to the parent, we can handle the |
11353 | // aborting of loads there, but we don't have a way to synchronously |
11354 | // remove entries as we do here for non-SHIP. |
11355 | RefPtr<ChildSHistory> shistory = GetRootSessionHistory(); |
11356 | if (shistory) { |
11357 | shistory->RemovePendingHistoryNavigations(); |
11358 | } |
11359 | |
11360 | nsPoint scrollPos = GetCurScrollPos(); |
11361 | |
11362 | bool scrollRestorationIsManual; |
11363 | if (mozilla::SessionHistoryInParent()) { |
11364 | // FIXME Need to save the current scroll position on mActiveEntry. |
11365 | scrollRestorationIsManual = mActiveEntry->GetScrollRestorationIsManual(); |
11366 | } else { |
11367 | // Save the current scroll position (bug 590573). Step 2.3. |
11368 | mOSHE->SetScrollPosition(scrollPos.x, scrollPos.y); |
11369 | |
11370 | scrollRestorationIsManual = mOSHE->GetScrollRestorationIsManual(); |
11371 | } |
11372 | |
11373 | nsCOMPtr<nsIContentSecurityPolicy> csp = aDocument->GetCsp(); |
11374 | |
11375 | if (mozilla::SessionHistoryInParent()) { |
11376 | 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) |
11377 | ("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); |
11378 | |
11379 | nsString title(mActiveEntry->GetTitle()); |
11380 | nsCOMPtr<nsIReferrerInfo> referrerInfo = mActiveEntry->GetReferrerInfo(); |
11381 | |
11382 | UpdateActiveEntry(false, |
11383 | /* aPreviousScrollPos = */ Some(scrollPos), aNewURI, |
11384 | /* aOriginalURI = */ nullptr, |
11385 | /* aReferrerInfo = */ referrerInfo, |
11386 | /* aTriggeringPrincipal = */ aDocument->NodePrincipal(), |
11387 | csp, title, scrollRestorationIsManual, aData, |
11388 | uriWasModified); |
11389 | } else { |
11390 | // Since we're not changing which page we have loaded, pass |
11391 | // true for aCloneChildren. |
11392 | nsresult rv = AddToSessionHistory( |
11393 | aNewURI, nullptr, |
11394 | aDocument->NodePrincipal(), // triggeringPrincipal |
11395 | nullptr, nullptr, csp, true, getter_AddRefs(newSHEntry)); |
11396 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 11396); return rv; } } while (false); |
11397 | |
11398 | NS_ENSURE_TRUE(newSHEntry, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(newSHEntry)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "newSHEntry" ") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 11398); return NS_ERROR_FAILURE; } } while (false); |
11399 | |
11400 | // Session history entries created by pushState inherit scroll restoration |
11401 | // mode from the current entry. |
11402 | newSHEntry->SetScrollRestorationIsManual(scrollRestorationIsManual); |
11403 | |
11404 | // Set the new SHEntry's title (bug 655273). |
11405 | nsString title; |
11406 | mOSHE->GetTitle(title); |
11407 | newSHEntry->SetTitle(title); |
11408 | |
11409 | nsCOMPtr<nsIReferrerInfo> referrerInfo = mOSHE->GetReferrerInfo(); |
11410 | newSHEntry->SetReferrerInfo(referrerInfo); |
11411 | |
11412 | // Link the new SHEntry to the old SHEntry's BFCache entry, since the |
11413 | // two entries correspond to the same document. |
11414 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 11415); return NS_ERROR_FAILURE; } } while (false) |
11415 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 11415); return NS_ERROR_FAILURE; } } while (false); |
11416 | |
11417 | // AddToSessionHistory may not modify mOSHE. In case it doesn't, |
11418 | // we'll just set mOSHE here. |
11419 | mOSHE = newSHEntry; |
11420 | } |
11421 | } else if (mozilla::SessionHistoryInParent()) { |
11422 | 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) |
11423 | ("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) |
11424 | 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); |
11425 | // Setting the resultPrincipalURI to nullptr is fine here: it will cause |
11426 | // NS_GetFinalChannelURI to use the originalURI as the URI, which is aNewURI |
11427 | // in our case. We could also set it to aNewURI, with the same result. |
11428 | // We don't use aTitle here, see bug 544535. |
11429 | nsString title; |
11430 | nsCOMPtr<nsIReferrerInfo> referrerInfo; |
11431 | if (mActiveEntry) { |
11432 | title = mActiveEntry->GetTitle(); |
11433 | referrerInfo = mActiveEntry->GetReferrerInfo(); |
11434 | } else { |
11435 | referrerInfo = nullptr; |
11436 | } |
11437 | UpdateActiveEntry( |
11438 | true, /* aPreviousScrollPos = */ Nothing(), aNewURI, aNewURI, |
11439 | /* aReferrerInfo = */ referrerInfo, aDocument->NodePrincipal(), |
11440 | aDocument->GetCsp(), title, |
11441 | mActiveEntry && mActiveEntry->GetScrollRestorationIsManual(), aData, |
11442 | uriWasModified); |
11443 | } else { |
11444 | // Step 3. |
11445 | newSHEntry = mOSHE; |
11446 | |
11447 | 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); |
11448 | // Since we're not changing which page we have loaded, pass |
11449 | // true for aCloneChildren. |
11450 | if (!newSHEntry) { |
11451 | nsresult rv = AddToSessionHistory( |
11452 | aNewURI, nullptr, |
11453 | aDocument->NodePrincipal(), // triggeringPrincipal |
11454 | nullptr, nullptr, aDocument->GetCsp(), true, |
11455 | getter_AddRefs(newSHEntry)); |
11456 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 11456); return rv; } } while (false); |
11457 | mOSHE = newSHEntry; |
11458 | } |
11459 | |
11460 | nsCOMPtr<nsIReferrerInfo> referrerInfo = mOSHE->GetReferrerInfo(); |
11461 | |
11462 | newSHEntry->SetURI(aNewURI); |
11463 | newSHEntry->SetOriginalURI(aNewURI); |
11464 | // We replaced the URI of the entry, clear the unstripped URI as it |
11465 | // shouldn't be used for reloads anymore. |
11466 | newSHEntry->SetUnstrippedURI(nullptr); |
11467 | // Setting the resultPrincipalURI to nullptr is fine here: it will cause |
11468 | // NS_GetFinalChannelURI to use the originalURI as the URI, which is aNewURI |
11469 | // in our case. We could also set it to aNewURI, with the same result. |
11470 | newSHEntry->SetResultPrincipalURI(nullptr); |
11471 | newSHEntry->SetLoadReplace(false); |
11472 | newSHEntry->SetReferrerInfo(referrerInfo); |
11473 | } |
11474 | |
11475 | if (!mozilla::SessionHistoryInParent()) { |
11476 | // Step 2.4 and 3: Modify new/original session history entry and clear its |
11477 | // POST data, if there is any. |
11478 | newSHEntry->SetStateData(aData); |
11479 | newSHEntry->SetPostData(nullptr); |
11480 | |
11481 | newSHEntry->SetURIWasModified(uriWasModified); |
11482 | |
11483 | // Step E as described at the top of AddState: If aReplace is false, |
11484 | // indicating that we're doing a pushState rather than a replaceState, |
11485 | // notify bfcache that we've added a page to the history so it can evict |
11486 | // content viewers if appropriate. Otherwise call ReplaceEntry so that we |
11487 | // notify nsIHistoryListeners that an entry was replaced. We may not have a |
11488 | // root session history if this call is coming from a document.open() in a |
11489 | // docshell subtree that disables session history. |
11490 | RefPtr<ChildSHistory> rootSH = GetRootSessionHistory(); |
11491 | if (rootSH) { |
11492 | rootSH->LegacySHistory()->EvictDocumentViewersOrReplaceEntry(newSHEntry, |
11493 | aReplace); |
11494 | } |
11495 | } |
11496 | |
11497 | // Step 4: If the document's URI changed, update document's URI and update |
11498 | // global history. |
11499 | // |
11500 | // We need to call FireOnLocationChange so that the browser's address bar |
11501 | // gets updated and the back button is enabled, but we only need to |
11502 | // explicitly call FireOnLocationChange if we're not calling SetCurrentURI, |
11503 | // since SetCurrentURI will call FireOnLocationChange for us. |
11504 | // |
11505 | // Both SetCurrentURI(...) and FireDummyOnLocationChange() pass |
11506 | // nullptr for aRequest param to FireOnLocationChange(...). Such an update |
11507 | // notification is allowed only when we know docshell is not loading a new |
11508 | // document and it requires LOCATION_CHANGE_SAME_DOCUMENT flag. Otherwise, |
11509 | // FireOnLocationChange(...) breaks security UI. |
11510 | // |
11511 | // If the docshell is shutting down, don't update the document URI, as we |
11512 | // can't load into a docshell that is being destroyed. |
11513 | if (!aEqualURIs && !mIsBeingDestroyed) { |
11514 | aDocument->SetDocumentURI(aNewURI); |
11515 | SetCurrentURI(aNewURI, nullptr, /* aFireLocationChange */ true, |
11516 | /* aIsInitialAboutBlank */ false, |
11517 | GetSameDocumentNavigationFlags(aNewURI)); |
11518 | |
11519 | AddURIVisit(aNewURI, aCurrentURI, 0); |
11520 | |
11521 | // AddURIVisit doesn't set the title for the new URI in global history, |
11522 | // so do that here. |
11523 | UpdateGlobalHistoryTitle(aNewURI); |
11524 | |
11525 | // Inform the favicon service that our old favicon applies to this new |
11526 | // URI. |
11527 | CopyFavicon(aCurrentURI, aNewURI, UsePrivateBrowsing()); |
11528 | } else { |
11529 | FireDummyOnLocationChange(); |
11530 | } |
11531 | aDocument->SetStateObject(aData); |
11532 | |
11533 | return NS_OK; |
11534 | } |
11535 | |
11536 | NS_IMETHODIMPnsresult |
11537 | nsDocShell::GetCurrentScrollRestorationIsManual(bool* aIsManual) { |
11538 | if (mozilla::SessionHistoryInParent()) { |
11539 | *aIsManual = mActiveEntry && mActiveEntry->GetScrollRestorationIsManual(); |
11540 | return NS_OK; |
11541 | } |
11542 | |
11543 | *aIsManual = false; |
11544 | if (mOSHE) { |
11545 | return mOSHE->GetScrollRestorationIsManual(aIsManual); |
11546 | } |
11547 | |
11548 | return NS_OK; |
11549 | } |
11550 | |
11551 | NS_IMETHODIMPnsresult |
11552 | nsDocShell::SetCurrentScrollRestorationIsManual(bool aIsManual) { |
11553 | SetScrollRestorationIsManualOnHistoryEntry(mOSHE, aIsManual); |
11554 | |
11555 | return NS_OK; |
11556 | } |
11557 | |
11558 | void nsDocShell::SetScrollRestorationIsManualOnHistoryEntry( |
11559 | nsISHEntry* aSHEntry, bool aIsManual) { |
11560 | if (aSHEntry) { |
11561 | aSHEntry->SetScrollRestorationIsManual(aIsManual); |
11562 | } |
11563 | |
11564 | if (mActiveEntry && mBrowsingContext) { |
11565 | mActiveEntry->SetScrollRestorationIsManual(aIsManual); |
11566 | if (XRE_IsParentProcess()) { |
11567 | SessionHistoryEntry* entry = |
11568 | mBrowsingContext->Canonical()->GetActiveSessionHistoryEntry(); |
11569 | if (entry) { |
11570 | entry->SetScrollRestorationIsManual(aIsManual); |
11571 | } |
11572 | } else { |
11573 | mozilla::Unused << ContentChild::GetSingleton() |
11574 | ->SendSessionHistoryEntryScrollRestorationIsManual( |
11575 | mBrowsingContext, aIsManual); |
11576 | } |
11577 | } |
11578 | } |
11579 | |
11580 | void nsDocShell::SetCacheKeyOnHistoryEntry(nsISHEntry* aSHEntry, |
11581 | uint32_t aCacheKey) { |
11582 | if (aSHEntry) { |
11583 | aSHEntry->SetCacheKey(aCacheKey); |
11584 | } |
11585 | |
11586 | if (mActiveEntry && mBrowsingContext) { |
11587 | mActiveEntry->SetCacheKey(aCacheKey); |
11588 | if (XRE_IsParentProcess()) { |
11589 | SessionHistoryEntry* entry = |
11590 | mBrowsingContext->Canonical()->GetActiveSessionHistoryEntry(); |
11591 | if (entry) { |
11592 | entry->SetCacheKey(aCacheKey); |
11593 | } |
11594 | } else { |
11595 | mozilla::Unused |
11596 | << ContentChild::GetSingleton()->SendSessionHistoryEntryCacheKey( |
11597 | mBrowsingContext, aCacheKey); |
11598 | } |
11599 | } |
11600 | } |
11601 | |
11602 | /* static */ |
11603 | bool nsDocShell::ShouldAddToSessionHistory(nsIURI* aURI, nsIChannel* aChannel) { |
11604 | // I believe none of the about: urls should go in the history. But then |
11605 | // that could just be me... If the intent is only deny about:blank then we |
11606 | // should just do a spec compare, rather than two gets of the scheme and |
11607 | // then the path. -Gagan |
11608 | nsresult rv; |
11609 | nsAutoCString buf; |
11610 | |
11611 | rv = aURI->GetScheme(buf); |
11612 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
11613 | return false; |
11614 | } |
11615 | |
11616 | if (buf.EqualsLiteral("about")) { |
11617 | rv = aURI->GetPathQueryRef(buf); |
11618 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
11619 | return false; |
11620 | } |
11621 | |
11622 | if (buf.EqualsLiteral("blank")) { |
11623 | return false; |
11624 | } |
11625 | // We only want to add about:newtab if it's not privileged, and |
11626 | // if it is not configured to show the blank page. |
11627 | if (buf.EqualsLiteral("newtab")) { |
11628 | if (!StaticPrefs::browser_newtabpage_enabled()) { |
11629 | return false; |
11630 | } |
11631 | |
11632 | NS_ENSURE_TRUE(aChannel, false)do { if ((__builtin_expect(!!(!(aChannel)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aChannel" ") failed", nullptr , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 11632); return false; } } while (false); |
11633 | nsCOMPtr<nsIPrincipal> resultPrincipal; |
11634 | rv = nsContentUtils::GetSecurityManager()->GetChannelResultPrincipal( |
11635 | aChannel, getter_AddRefs(resultPrincipal)); |
11636 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 11636); return false; } } while (false); |
11637 | return !resultPrincipal->IsSystemPrincipal(); |
11638 | } |
11639 | } |
11640 | |
11641 | return true; |
11642 | } |
11643 | |
11644 | nsresult nsDocShell::AddToSessionHistory( |
11645 | nsIURI* aURI, nsIChannel* aChannel, nsIPrincipal* aTriggeringPrincipal, |
11646 | nsIPrincipal* aPrincipalToInherit, |
11647 | nsIPrincipal* aPartitionedPrincipalToInherit, |
11648 | nsIContentSecurityPolicy* aCsp, bool aCloneChildren, |
11649 | nsISHEntry** aNewEntry) { |
11650 | 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 11650); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aURI" ") (" "uri is null" ")"); do { *((volatile int*)__null) = 11650; __attribute__ ((nomerge)) ::abort(); } while (false); } } while (false); |
11651 | 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 11651); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aChannel || !aTriggeringPrincipal" ") (" "Shouldn't have both set" ")"); do { *((volatile int*) __null) = 11651; __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); |
11652 | 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()", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 11652); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "!mozilla::SessionHistoryInParent()" ")"); do { *((volatile int*)__null) = 11652; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
11653 | |
11654 | #if defined(DEBUG1) |
11655 | if (MOZ_LOG_TEST(gDocShellLog, LogLevel::Debug)(__builtin_expect(!!(mozilla::detail::log_test(gDocShellLog, LogLevel ::Debug)), 0))) { |
11656 | nsAutoCString chanName; |
11657 | if (aChannel) { |
11658 | aChannel->GetName(chanName); |
11659 | } else { |
11660 | chanName.AssignLiteral("<no channel>"); |
11661 | } |
11662 | |
11663 | 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) |
11664 | ("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) |
11665 | 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); |
11666 | } |
11667 | #endif |
11668 | |
11669 | nsresult rv = NS_OK; |
11670 | nsCOMPtr<nsISHEntry> entry; |
11671 | |
11672 | /* |
11673 | * If this is a LOAD_FLAGS_REPLACE_HISTORY in a subframe, we use |
11674 | * the existing SH entry in the page and replace the url and |
11675 | * other vitalities. |
11676 | */ |
11677 | if (LOAD_TYPE_HAS_FLAGS(mLoadType, LOAD_FLAGS_REPLACE_HISTORY)((mLoadType) & ((LOAD_FLAGS_REPLACE_HISTORY) << 16) ) && |
11678 | !mBrowsingContext->IsTop()) { |
11679 | // This is a subframe |
11680 | entry = mOSHE; |
11681 | if (entry) { |
11682 | entry->ClearEntry(); |
11683 | } |
11684 | } |
11685 | |
11686 | // Create a new entry if necessary. |
11687 | if (!entry) { |
11688 | entry = new nsSHEntry(); |
11689 | } |
11690 | |
11691 | // Get the post data & referrer |
11692 | nsCOMPtr<nsIInputStream> inputStream; |
11693 | nsCOMPtr<nsIURI> originalURI; |
11694 | nsCOMPtr<nsIURI> resultPrincipalURI; |
11695 | nsCOMPtr<nsIURI> unstrippedURI; |
11696 | bool loadReplace = false; |
11697 | nsCOMPtr<nsIReferrerInfo> referrerInfo; |
11698 | uint32_t cacheKey = 0; |
11699 | nsCOMPtr<nsIPrincipal> triggeringPrincipal = aTriggeringPrincipal; |
11700 | nsCOMPtr<nsIPrincipal> principalToInherit = aPrincipalToInherit; |
11701 | nsCOMPtr<nsIPrincipal> partitionedPrincipalToInherit = |
11702 | aPartitionedPrincipalToInherit; |
11703 | nsCOMPtr<nsIContentSecurityPolicy> csp = aCsp; |
11704 | bool expired = false; // by default the page is not expired |
11705 | bool discardLayoutState = false; |
11706 | nsCOMPtr<nsICacheInfoChannel> cacheChannel; |
11707 | bool userActivation = false; |
11708 | |
11709 | if (aChannel) { |
11710 | cacheChannel = do_QueryInterface(aChannel); |
11711 | |
11712 | /* If there is a caching channel, get the Cache Key and store it |
11713 | * in SH. |
11714 | */ |
11715 | if (cacheChannel) { |
11716 | cacheChannel->GetCacheKey(&cacheKey); |
11717 | } |
11718 | nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(aChannel)); |
11719 | |
11720 | // Check if the httpChannel is hiding under a multipartChannel |
11721 | if (!httpChannel) { |
11722 | GetHttpChannel(aChannel, getter_AddRefs(httpChannel)); |
11723 | } |
11724 | if (httpChannel) { |
11725 | nsCOMPtr<nsIUploadChannel> uploadChannel(do_QueryInterface(httpChannel)); |
11726 | if (uploadChannel) { |
11727 | uploadChannel->GetUploadStream(getter_AddRefs(inputStream)); |
11728 | } |
11729 | httpChannel->GetOriginalURI(getter_AddRefs(originalURI)); |
11730 | uint32_t loadFlags; |
11731 | aChannel->GetLoadFlags(&loadFlags); |
11732 | loadReplace = loadFlags & nsIChannel::LOAD_REPLACE; |
11733 | rv = httpChannel->GetReferrerInfo(getter_AddRefs(referrerInfo)); |
11734 | 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)))", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 11734); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))" ")"); do { *((volatile int*)__null) = 11734; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
11735 | |
11736 | discardLayoutState = ShouldDiscardLayoutState(httpChannel); |
11737 | } |
11738 | |
11739 | nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo(); |
11740 | if (!triggeringPrincipal) { |
11741 | triggeringPrincipal = loadInfo->TriggeringPrincipal(); |
11742 | } |
11743 | if (!csp) { |
11744 | csp = loadInfo->GetCspToInherit(); |
11745 | } |
11746 | |
11747 | loadInfo->GetResultPrincipalURI(getter_AddRefs(resultPrincipalURI)); |
11748 | |
11749 | loadInfo->GetUnstrippedURI(getter_AddRefs(unstrippedURI)); |
11750 | |
11751 | userActivation = loadInfo->GetHasValidUserGestureActivation(); |
11752 | |
11753 | // For now keep storing just the principal in the SHEntry. |
11754 | if (!principalToInherit) { |
11755 | if (loadInfo->GetLoadingSandboxed()) { |
11756 | if (loadInfo->GetLoadingPrincipal()) { |
11757 | principalToInherit = NullPrincipal::CreateWithInheritedAttributes( |
11758 | loadInfo->GetLoadingPrincipal()); |
11759 | } else { |
11760 | // get the OriginAttributes |
11761 | OriginAttributes attrs; |
11762 | loadInfo->GetOriginAttributes(&attrs); |
11763 | principalToInherit = NullPrincipal::Create(attrs); |
11764 | } |
11765 | } else { |
11766 | principalToInherit = loadInfo->PrincipalToInherit(); |
11767 | } |
11768 | } |
11769 | |
11770 | if (!partitionedPrincipalToInherit) { |
11771 | // XXXehsan is it correct to fall back to the principal to inherit in all |
11772 | // cases? For example, what about the cases where we are using the load |
11773 | // info's principal to inherit? Do we need to add a similar concept to |
11774 | // load info for partitioned principal? |
11775 | partitionedPrincipalToInherit = principalToInherit; |
11776 | } |
11777 | } |
11778 | |
11779 | nsAutoString srcdoc; |
11780 | bool srcdocEntry = false; |
11781 | nsCOMPtr<nsIURI> baseURI; |
11782 | |
11783 | nsCOMPtr<nsIInputStreamChannel> inStrmChan = do_QueryInterface(aChannel); |
11784 | if (inStrmChan) { |
11785 | bool isSrcdocChannel; |
11786 | inStrmChan->GetIsSrcdocChannel(&isSrcdocChannel); |
11787 | if (isSrcdocChannel) { |
11788 | inStrmChan->GetSrcdocData(srcdoc); |
11789 | srcdocEntry = true; |
11790 | inStrmChan->GetBaseURI(getter_AddRefs(baseURI)); |
11791 | } else { |
11792 | srcdoc.SetIsVoid(true); |
11793 | } |
11794 | } |
11795 | /* If cache got a 'no-store', ask SH not to store |
11796 | * HistoryLayoutState. By default, SH will set this |
11797 | * flag to true and save HistoryLayoutState. |
11798 | */ |
11799 | bool saveLayoutState = !discardLayoutState; |
11800 | |
11801 | if (cacheChannel) { |
11802 | // Check if the page has expired from cache |
11803 | uint32_t expTime = 0; |
11804 | cacheChannel->GetCacheTokenExpirationTime(&expTime); |
11805 | uint32_t now = PRTimeToSeconds(PR_Now()); |
11806 | if (expTime <= now) { |
11807 | expired = true; |
11808 | } |
11809 | } |
11810 | |
11811 | // Title is set in nsDocShell::SetTitle() |
11812 | entry->Create(aURI, // uri |
11813 | u""_ns, // Title |
11814 | inputStream, // Post data stream |
11815 | cacheKey, // CacheKey |
11816 | mContentTypeHint, // Content-type |
11817 | triggeringPrincipal, // Channel or provided principal |
11818 | principalToInherit, partitionedPrincipalToInherit, csp, |
11819 | HistoryID(), GetCreatedDynamically(), originalURI, |
11820 | resultPrincipalURI, unstrippedURI, loadReplace, referrerInfo, |
11821 | srcdoc, srcdocEntry, baseURI, saveLayoutState, expired, |
11822 | userActivation); |
11823 | |
11824 | if (mBrowsingContext->IsTop() && GetSessionHistory()) { |
11825 | bool shouldPersist = ShouldAddToSessionHistory(aURI, aChannel); |
11826 | Maybe<int32_t> previousEntryIndex; |
11827 | Maybe<int32_t> loadedEntryIndex; |
11828 | rv = GetSessionHistory()->LegacySHistory()->AddToRootSessionHistory( |
11829 | aCloneChildren, mOSHE, mBrowsingContext, entry, mLoadType, |
11830 | shouldPersist, &previousEntryIndex, &loadedEntryIndex); |
11831 | |
11832 | 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 11832); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))" ") (" "Could not add entry to root session history" ")"); do { *((volatile int*)__null) = 11832; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
11833 | if (previousEntryIndex.isSome()) { |
11834 | mPreviousEntryIndex = previousEntryIndex.value(); |
11835 | } |
11836 | if (loadedEntryIndex.isSome()) { |
11837 | mLoadedEntryIndex = loadedEntryIndex.value(); |
11838 | } |
11839 | |
11840 | // aCloneChildren implies that we are retaining the same document, thus we |
11841 | // need to signal to the top WC that the new SHEntry may receive a fresh |
11842 | // user interaction flag. |
11843 | if (aCloneChildren) { |
11844 | WindowContext* topWc = mBrowsingContext->GetTopWindowContext(); |
11845 | if (topWc && !topWc->IsDiscarded()) { |
11846 | MOZ_ALWAYS_SUCCEEDS(topWc->SetSHEntryHasUserInteraction(false))do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl (topWc->SetSHEntryHasUserInteraction(false))), 1)))), 1))) { } else { do { static_assert( mozilla::detail::AssertionConditionType <decltype(false)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("false" " (" "NS_SUCCEEDED(topWc->SetSHEntryHasUserInteraction(false))" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 11846); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false" ") (" "NS_SUCCEEDED(topWc->SetSHEntryHasUserInteraction(false))" ")"); do { *((volatile int*)__null) = 11846; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); } } while (false); |
11847 | } |
11848 | } |
11849 | } else { |
11850 | // This is a subframe, make sure that this new SHEntry will be |
11851 | // marked with user interaction. |
11852 | WindowContext* topWc = mBrowsingContext->GetTopWindowContext(); |
11853 | if (topWc && !topWc->IsDiscarded()) { |
11854 | MOZ_ALWAYS_SUCCEEDS(topWc->SetSHEntryHasUserInteraction(false))do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl (topWc->SetSHEntryHasUserInteraction(false))), 1)))), 1))) { } else { do { static_assert( mozilla::detail::AssertionConditionType <decltype(false)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("false" " (" "NS_SUCCEEDED(topWc->SetSHEntryHasUserInteraction(false))" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 11854); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false" ") (" "NS_SUCCEEDED(topWc->SetSHEntryHasUserInteraction(false))" ")"); do { *((volatile int*)__null) = 11854; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); } } while (false); |
11855 | } |
11856 | if (!mOSHE || !LOAD_TYPE_HAS_FLAGS(mLoadType, LOAD_FLAGS_REPLACE_HISTORY)((mLoadType) & ((LOAD_FLAGS_REPLACE_HISTORY) << 16) )) { |
11857 | rv = AddChildSHEntryToParent(entry, mBrowsingContext->ChildOffset(), |
11858 | aCloneChildren); |
11859 | } |
11860 | } |
11861 | |
11862 | // Return the new SH entry... |
11863 | if (aNewEntry) { |
11864 | *aNewEntry = nullptr; |
11865 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) { |
11866 | entry.forget(aNewEntry); |
11867 | } |
11868 | } |
11869 | |
11870 | return rv; |
11871 | } |
11872 | |
11873 | void nsDocShell::UpdateActiveEntry( |
11874 | bool aReplace, const Maybe<nsPoint>& aPreviousScrollPos, nsIURI* aURI, |
11875 | nsIURI* aOriginalURI, nsIReferrerInfo* aReferrerInfo, |
11876 | nsIPrincipal* aTriggeringPrincipal, nsIContentSecurityPolicy* aCsp, |
11877 | const nsAString& aTitle, bool aScrollRestorationIsManual, |
11878 | nsIStructuredCloneContainer* aData, bool aURIWasModified) { |
11879 | 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()", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 11879); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mozilla::SessionHistoryInParent()" ")"); do { *((volatile int*)__null) = 11879; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
11880 | 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 11880); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aURI" ") (" "uri is null" ")"); do { *((volatile int*)__null) = 11880; __attribute__ ((nomerge)) ::abort(); } while (false); } } while (false); |
11881 | 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 11882); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLoadType == LOAD_PUSHSTATE" ") (" "This code only deals with pushState" ")"); do { *((volatile int*)__null) = 11882; __attribute__((nomerge)) ::abort(); } while (false); } } while (false) |
11882 | "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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 11882); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLoadType == LOAD_PUSHSTATE" ") (" "This code only deals with pushState" ")"); do { *((volatile int*)__null) = 11882; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
11883 | 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", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 11883); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aReplace" ")"); do { *((volatile int*)__null) = 11883; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); } } while (false); |
11884 | |
11885 | 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) |
11886 | ("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) |
11887 | 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); |
11888 | |
11889 | // Even if we're replacing an existing entry we create new a |
11890 | // SessionHistoryInfo. In the parent process we'll keep the existing |
11891 | // SessionHistoryEntry, but just replace its SessionHistoryInfo, that way the |
11892 | // entry keeps identity but its data is replaced. |
11893 | bool replace = aReplace && mActiveEntry; |
11894 | |
11895 | if (!replace) { |
11896 | CollectWireframe(); |
11897 | } |
11898 | |
11899 | if (mActiveEntry) { |
11900 | // Link this entry to the previous active entry. |
11901 | mActiveEntry = MakeUnique<SessionHistoryInfo>(*mActiveEntry, aURI); |
11902 | } else { |
11903 | mActiveEntry = MakeUnique<SessionHistoryInfo>( |
11904 | aURI, aTriggeringPrincipal, nullptr, nullptr, aCsp, mContentTypeHint); |
11905 | } |
11906 | mActiveEntry->SetOriginalURI(aOriginalURI); |
11907 | mActiveEntry->SetUnstrippedURI(nullptr); |
11908 | mActiveEntry->SetReferrerInfo(aReferrerInfo); |
11909 | mActiveEntry->SetTitle(aTitle); |
11910 | mActiveEntry->SetStateData(static_cast<nsStructuredCloneContainer*>(aData)); |
11911 | mActiveEntry->SetURIWasModified(aURIWasModified); |
11912 | mActiveEntry->SetScrollRestorationIsManual(aScrollRestorationIsManual); |
11913 | |
11914 | if (replace) { |
11915 | mBrowsingContext->ReplaceActiveSessionHistoryEntry(mActiveEntry.get()); |
11916 | } else { |
11917 | mBrowsingContext->IncrementHistoryEntryCountForBrowsingContext(); |
11918 | // FIXME We should probably just compute mChildOffset in the parent |
11919 | // instead of passing it over IPC here. |
11920 | mBrowsingContext->SetActiveSessionHistoryEntry( |
11921 | aPreviousScrollPos, mActiveEntry.get(), mLoadType, |
11922 | /* aCacheKey = */ 0); |
11923 | // FIXME Do we need to update mPreviousEntryIndex and mLoadedEntryIndex? |
11924 | } |
11925 | } |
11926 | |
11927 | nsresult nsDocShell::LoadHistoryEntry(nsISHEntry* aEntry, uint32_t aLoadType, |
11928 | bool aUserActivation) { |
11929 | NS_ENSURE_TRUE(aEntry, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(aEntry)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aEntry" ") failed", nullptr , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 11929); return NS_ERROR_FAILURE; } } while (false); |
11930 | |
11931 | nsresult rv; |
11932 | RefPtr<nsDocShellLoadState> loadState; |
11933 | rv = aEntry->CreateLoadInfo(getter_AddRefs(loadState)); |
11934 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 11934); return rv; } } while (false); |
11935 | |
11936 | // Calling CreateAboutBlankDocumentViewer can set mOSHE to null, and if |
11937 | // that's the only thing holding a ref to aEntry that will cause aEntry to |
11938 | // die while we're loading it. So hold a strong ref to aEntry here, just |
11939 | // in case. |
11940 | nsCOMPtr<nsISHEntry> kungFuDeathGrip(aEntry); |
11941 | |
11942 | loadState->SetHasValidUserGestureActivation( |
11943 | loadState->HasValidUserGestureActivation() || aUserActivation); |
11944 | |
11945 | loadState->SetTextDirectiveUserActivation( |
11946 | loadState->GetTextDirectiveUserActivation() || aUserActivation); |
11947 | |
11948 | return LoadHistoryEntry(loadState, aLoadType, aEntry == mOSHE); |
11949 | } |
11950 | |
11951 | nsresult nsDocShell::LoadHistoryEntry(const LoadingSessionHistoryInfo& aEntry, |
11952 | uint32_t aLoadType, |
11953 | bool aUserActivation) { |
11954 | RefPtr<nsDocShellLoadState> loadState = aEntry.CreateLoadInfo(); |
11955 | loadState->SetHasValidUserGestureActivation( |
11956 | loadState->HasValidUserGestureActivation() || aUserActivation); |
11957 | |
11958 | loadState->SetTextDirectiveUserActivation( |
11959 | loadState->GetTextDirectiveUserActivation() || aUserActivation); |
11960 | |
11961 | return LoadHistoryEntry(loadState, aLoadType, aEntry.mLoadingCurrentEntry); |
11962 | } |
11963 | |
11964 | nsresult nsDocShell::LoadHistoryEntry(nsDocShellLoadState* aLoadState, |
11965 | uint32_t aLoadType, |
11966 | bool aLoadingCurrentEntry) { |
11967 | if (!IsNavigationAllowed()) { |
11968 | return NS_OK; |
11969 | } |
11970 | |
11971 | // We are setting load type afterwards so we don't have to |
11972 | // send it in an IPC message |
11973 | aLoadState->SetLoadType(aLoadType); |
11974 | |
11975 | nsresult rv; |
11976 | if (SchemeIsJavascript(aLoadState->URI())) { |
11977 | // We're loading a URL that will execute script from inside asyncOpen. |
11978 | // Replace the current document with about:blank now to prevent |
11979 | // anything from the current document from leaking into any JavaScript |
11980 | // code in the URL. |
11981 | // Don't cache the presentation if we're going to just reload the |
11982 | // current entry. Caching would lead to trying to save the different |
11983 | // content viewers in the same nsISHEntry object. |
11984 | rv = CreateAboutBlankDocumentViewer( |
11985 | aLoadState->PrincipalToInherit(), |
11986 | aLoadState->PartitionedPrincipalToInherit(), nullptr, nullptr, |
11987 | /* aIsInitialDocument */ false, Nothing(), !aLoadingCurrentEntry); |
11988 | |
11989 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
11990 | // The creation of the intermittent about:blank content |
11991 | // viewer failed for some reason (potentially because the |
11992 | // user prevented it). Interrupt the history load. |
11993 | return NS_OK; |
11994 | } |
11995 | |
11996 | if (!aLoadState->TriggeringPrincipal()) { |
11997 | // Ensure that we have a triggeringPrincipal. Otherwise javascript: |
11998 | // URIs will pick it up from the about:blank page we just loaded, |
11999 | // and we don't really want even that in this case. |
12000 | nsCOMPtr<nsIPrincipal> principal = |
12001 | NullPrincipal::Create(GetOriginAttributes()); |
12002 | aLoadState->SetTriggeringPrincipal(principal); |
12003 | } |
12004 | } |
12005 | |
12006 | /* If there is a valid postdata *and* the user pressed |
12007 | * reload or shift-reload, take user's permission before we |
12008 | * repost the data to the server. |
12009 | */ |
12010 | if ((aLoadType & LOAD_CMD_RELOAD) && aLoadState->PostDataStream()) { |
12011 | bool repost; |
12012 | rv = ConfirmRepost(&repost); |
12013 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
12014 | return rv; |
12015 | } |
12016 | |
12017 | // If the user pressed cancel in the dialog, return. We're done here. |
12018 | if (!repost) { |
12019 | return NS_BINDING_ABORTED; |
12020 | } |
12021 | } |
12022 | |
12023 | // If there is no valid triggeringPrincipal, we deny the load |
12024 | 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 12025); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->TriggeringPrincipal()" ") (" "need a valid triggeringPrincipal to load from history" ")"); do { *((volatile int*)__null) = 12025; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false) |
12025 | "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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 12025); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->TriggeringPrincipal()" ") (" "need a valid triggeringPrincipal to load from history" ")"); do { *((volatile int*)__null) = 12025; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
12026 | if (!aLoadState->TriggeringPrincipal()) { |
12027 | return NS_ERROR_FAILURE; |
12028 | } |
12029 | |
12030 | return InternalLoad(aLoadState); // No nsIRequest |
12031 | } |
12032 | |
12033 | NS_IMETHODIMPnsresult |
12034 | nsDocShell::PersistLayoutHistoryState() { |
12035 | nsresult rv = NS_OK; |
12036 | |
12037 | if (mozilla::SessionHistoryInParent() ? !!mActiveEntry : !!mOSHE) { |
12038 | bool scrollRestorationIsManual; |
12039 | if (mozilla::SessionHistoryInParent()) { |
12040 | scrollRestorationIsManual = mActiveEntry->GetScrollRestorationIsManual(); |
12041 | } else { |
12042 | scrollRestorationIsManual = mOSHE->GetScrollRestorationIsManual(); |
12043 | } |
12044 | nsCOMPtr<nsILayoutHistoryState> layoutState; |
12045 | if (RefPtr<PresShell> presShell = GetPresShell()) { |
12046 | rv = presShell->CaptureHistoryState(getter_AddRefs(layoutState)); |
12047 | } else if (scrollRestorationIsManual) { |
12048 | // Even if we don't have layout anymore, we may want to reset the |
12049 | // current scroll state in layout history. |
12050 | GetLayoutHistoryState(getter_AddRefs(layoutState)); |
12051 | } |
12052 | |
12053 | if (scrollRestorationIsManual && layoutState) { |
12054 | layoutState->ResetScrollState(); |
12055 | } |
12056 | } |
12057 | |
12058 | return rv; |
12059 | } |
12060 | |
12061 | void nsDocShell::SwapHistoryEntries(nsISHEntry* aOldEntry, |
12062 | nsISHEntry* aNewEntry) { |
12063 | if (aOldEntry == mOSHE) { |
12064 | mOSHE = aNewEntry; |
12065 | } |
12066 | |
12067 | if (aOldEntry == mLSHE) { |
12068 | mLSHE = aNewEntry; |
12069 | } |
12070 | } |
12071 | |
12072 | void nsDocShell::SetHistoryEntryAndUpdateBC(const Maybe<nsISHEntry*>& aLSHE, |
12073 | const Maybe<nsISHEntry*>& aOSHE) { |
12074 | // We want to hold on to the reference in mLSHE before we update it. |
12075 | // Otherwise, SetHistoryEntry could release the last reference to |
12076 | // the entry while aOSHE is pointing to it. |
12077 | nsCOMPtr<nsISHEntry> deathGripOldLSHE; |
12078 | if (aLSHE.isSome()) { |
12079 | deathGripOldLSHE = SetHistoryEntry(&mLSHE, aLSHE.value()); |
12080 | 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()", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 12080); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLSHE.get() == aLSHE.value()" ")"); do { *((volatile int*)__null) = 12080; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
12081 | } |
12082 | nsCOMPtr<nsISHEntry> deathGripOldOSHE; |
12083 | if (aOSHE.isSome()) { |
12084 | deathGripOldOSHE = SetHistoryEntry(&mOSHE, aOSHE.value()); |
12085 | 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()", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 12085); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mOSHE.get() == aOSHE.value()" ")"); do { *((volatile int*)__null) = 12085; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
12086 | } |
12087 | } |
12088 | |
12089 | already_AddRefed<nsISHEntry> nsDocShell::SetHistoryEntry( |
12090 | nsCOMPtr<nsISHEntry>* aPtr, nsISHEntry* aEntry) { |
12091 | // We need to sync up the docshell and session history trees for |
12092 | // subframe navigation. If the load was in a subframe, we forward up to |
12093 | // the root docshell, which will then recursively sync up all docshells |
12094 | // to their corresponding entries in the new session history tree. |
12095 | // If we don't do this, then we can cache a content viewer on the wrong |
12096 | // cloned entry, and subsequently restore it at the wrong time. |
12097 | RefPtr<BrowsingContext> topBC = mBrowsingContext->Top(); |
12098 | if (topBC->IsDiscarded()) { |
12099 | topBC = nullptr; |
12100 | } |
12101 | RefPtr<BrowsingContext> currBC = |
12102 | mBrowsingContext->IsDiscarded() ? nullptr : mBrowsingContext; |
12103 | if (topBC && *aPtr) { |
12104 | (*aPtr)->SyncTreesForSubframeNavigation(aEntry, topBC, currBC); |
12105 | } |
12106 | nsCOMPtr<nsISHEntry> entry(aEntry); |
12107 | entry.swap(*aPtr); |
12108 | return entry.forget(); |
12109 | } |
12110 | |
12111 | already_AddRefed<ChildSHistory> nsDocShell::GetRootSessionHistory() { |
12112 | RefPtr<ChildSHistory> childSHistory = |
12113 | mBrowsingContext->Top()->GetChildSessionHistory(); |
12114 | return childSHistory.forget(); |
12115 | } |
12116 | |
12117 | nsresult nsDocShell::GetHttpChannel(nsIChannel* aChannel, |
12118 | nsIHttpChannel** aReturn) { |
12119 | NS_ENSURE_ARG_POINTER(aReturn)do { if ((__builtin_expect(!!(!(aReturn)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aReturn" ") failed", nullptr , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 12119); return NS_ERROR_INVALID_POINTER; } } while (false); |
12120 | if (!aChannel) { |
12121 | return NS_ERROR_FAILURE; |
12122 | } |
12123 | |
12124 | nsCOMPtr<nsIMultiPartChannel> multiPartChannel(do_QueryInterface(aChannel)); |
12125 | if (multiPartChannel) { |
12126 | nsCOMPtr<nsIChannel> baseChannel; |
12127 | multiPartChannel->GetBaseChannel(getter_AddRefs(baseChannel)); |
12128 | nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(baseChannel)); |
12129 | *aReturn = httpChannel; |
12130 | NS_IF_ADDREF(*aReturn)ns_if_addref(*aReturn); |
12131 | } |
12132 | return NS_OK; |
12133 | } |
12134 | |
12135 | bool nsDocShell::ShouldDiscardLayoutState(nsIHttpChannel* aChannel) { |
12136 | // By default layout State will be saved. |
12137 | if (!aChannel) { |
12138 | return false; |
12139 | } |
12140 | |
12141 | // figure out if SH should be saving layout state |
12142 | bool noStore = false; |
12143 | Unused << aChannel->IsNoStoreResponse(&noStore); |
12144 | return noStore; |
12145 | } |
12146 | |
12147 | NS_IMETHODIMPnsresult |
12148 | nsDocShell::GetEditor(nsIEditor** aEditor) { |
12149 | NS_ENSURE_ARG_POINTER(aEditor)do { if ((__builtin_expect(!!(!(aEditor)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aEditor" ") failed", nullptr , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 12149); return NS_ERROR_INVALID_POINTER; } } while (false); |
12150 | RefPtr<HTMLEditor> htmlEditor = GetHTMLEditorInternal(); |
12151 | htmlEditor.forget(aEditor); |
12152 | return NS_OK; |
12153 | } |
12154 | |
12155 | NS_IMETHODIMPnsresult |
12156 | nsDocShell::SetEditor(nsIEditor* aEditor) { |
12157 | HTMLEditor* htmlEditor = aEditor ? aEditor->GetAsHTMLEditor() : nullptr; |
12158 | // If TextEditor comes, throw an error. |
12159 | if (aEditor && !htmlEditor) { |
12160 | return NS_ERROR_INVALID_ARG; |
12161 | } |
12162 | return SetHTMLEditorInternal(htmlEditor); |
12163 | } |
12164 | |
12165 | HTMLEditor* nsDocShell::GetHTMLEditorInternal() { |
12166 | return mEditorData ? mEditorData->GetHTMLEditor() : nullptr; |
12167 | } |
12168 | |
12169 | nsresult nsDocShell::SetHTMLEditorInternal(HTMLEditor* aHTMLEditor) { |
12170 | if (!aHTMLEditor && !mEditorData) { |
12171 | return NS_OK; |
12172 | } |
12173 | |
12174 | nsresult rv = EnsureEditorData(); |
12175 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
12176 | return rv; |
12177 | } |
12178 | |
12179 | return mEditorData->SetHTMLEditor(aHTMLEditor); |
12180 | } |
12181 | |
12182 | NS_IMETHODIMPnsresult |
12183 | nsDocShell::GetEditable(bool* aEditable) { |
12184 | NS_ENSURE_ARG_POINTER(aEditable)do { if ((__builtin_expect(!!(!(aEditable)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aEditable" ") failed", nullptr , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 12184); return NS_ERROR_INVALID_POINTER; } } while (false); |
12185 | *aEditable = mEditorData && mEditorData->GetEditable(); |
12186 | return NS_OK; |
12187 | } |
12188 | |
12189 | NS_IMETHODIMPnsresult |
12190 | nsDocShell::GetHasEditingSession(bool* aHasEditingSession) { |
12191 | NS_ENSURE_ARG_POINTER(aHasEditingSession)do { if ((__builtin_expect(!!(!(aHasEditingSession)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aHasEditingSession" ") failed" , nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 12191); return NS_ERROR_INVALID_POINTER; } } while (false); |
12192 | |
12193 | if (mEditorData) { |
12194 | *aHasEditingSession = !!mEditorData->GetEditingSession(); |
12195 | } else { |
12196 | *aHasEditingSession = false; |
12197 | } |
12198 | |
12199 | return NS_OK; |
12200 | } |
12201 | |
12202 | NS_IMETHODIMPnsresult |
12203 | nsDocShell::MakeEditable(bool aInWaitForUriLoad) { |
12204 | nsresult rv = EnsureEditorData(); |
12205 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
12206 | return rv; |
12207 | } |
12208 | |
12209 | return mEditorData->MakeEditable(aInWaitForUriLoad); |
12210 | } |
12211 | |
12212 | /* static */ bool nsDocShell::ShouldAddURIVisit(nsIChannel* aChannel) { |
12213 | bool needToAddURIVisit = true; |
12214 | nsCOMPtr<nsIPropertyBag2> props(do_QueryInterface(aChannel)); |
12215 | if (props) { |
12216 | mozilla::Unused << props->GetPropertyAsBool( |
12217 | u"docshell.needToAddURIVisit"_ns, &needToAddURIVisit); |
12218 | } |
12219 | |
12220 | return needToAddURIVisit; |
12221 | } |
12222 | |
12223 | /* static */ void nsDocShell::ExtractLastVisit( |
12224 | nsIChannel* aChannel, nsIURI** aURI, uint32_t* aChannelRedirectFlags) { |
12225 | nsCOMPtr<nsIPropertyBag2> props(do_QueryInterface(aChannel)); |
12226 | if (!props) { |
12227 | return; |
12228 | } |
12229 | |
12230 | nsresult rv; |
12231 | nsCOMPtr<nsIURI> uri(do_GetProperty(props, u"docshell.previousURI"_ns, &rv)); |
12232 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) { |
12233 | uri.forget(aURI); |
12234 | |
12235 | rv = props->GetPropertyAsUint32(u"docshell.previousFlags"_ns, |
12236 | aChannelRedirectFlags); |
12237 | |
12238 | 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)", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 12240); } } while (false) |
12239 | 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)", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 12240); } } while (false) |
12240 | "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)", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 12240); } } while (false); |
12241 | |
12242 | } else { |
12243 | // There is no last visit for this channel, so this must be the first |
12244 | // link. Link the visit to the referrer of this request, if any. |
12245 | // Treat referrer as null if there is an error getting it. |
12246 | NS_GetReferrerFromChannel(aChannel, aURI); |
12247 | } |
12248 | } |
12249 | |
12250 | void nsDocShell::SaveLastVisit(nsIChannel* aChannel, nsIURI* aURI, |
12251 | uint32_t aChannelRedirectFlags) { |
12252 | nsCOMPtr<nsIWritablePropertyBag2> props(do_QueryInterface(aChannel)); |
12253 | if (!props || !aURI) { |
12254 | return; |
12255 | } |
12256 | |
12257 | props->SetPropertyAsInterface(u"docshell.previousURI"_ns, aURI); |
12258 | props->SetPropertyAsUint32(u"docshell.previousFlags"_ns, |
12259 | aChannelRedirectFlags); |
12260 | } |
12261 | |
12262 | /* static */ void nsDocShell::InternalAddURIVisit( |
12263 | nsIURI* aURI, nsIURI* aPreviousURI, uint32_t aChannelRedirectFlags, |
12264 | uint32_t aResponseStatus, BrowsingContext* aBrowsingContext, |
12265 | nsIWidget* aWidget, uint32_t aLoadType, bool aWasUpgraded) { |
12266 | 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!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 12266); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aURI" ") (" "Visited URI is null!" ")"); do { *((volatile int*)__null) = 12266; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
12267 | 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" ")" , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 12268); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadType != LOAD_ERROR_PAGE && aLoadType != LOAD_BYPASS_HISTORY" ") (" "Do not add error or bypass pages to global history" ")" ); do { *((volatile int*)__null) = 12268; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
12268 | "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" ")" , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 12268); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadType != LOAD_ERROR_PAGE && aLoadType != LOAD_BYPASS_HISTORY" ") (" "Do not add error or bypass pages to global history" ")" ); do { *((volatile int*)__null) = 12268; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
12269 | |
12270 | bool usePrivateBrowsing = false; |
12271 | aBrowsingContext->GetUsePrivateBrowsing(&usePrivateBrowsing); |
12272 | |
12273 | // Only content-type docshells save URI visits. Also don't do |
12274 | // anything here if we're not supposed to use global history. |
12275 | if (!aBrowsingContext->IsContent() || |
12276 | !aBrowsingContext->GetUseGlobalHistory() || usePrivateBrowsing) { |
12277 | return; |
12278 | } |
12279 | |
12280 | nsCOMPtr<IHistory> history = components::History::Service(); |
12281 | |
12282 | if (history) { |
12283 | uint32_t visitURIFlags = 0; |
12284 | |
12285 | if (aBrowsingContext->IsTop()) { |
12286 | visitURIFlags |= IHistory::TOP_LEVEL; |
12287 | } |
12288 | |
12289 | if (aChannelRedirectFlags & nsIChannelEventSink::REDIRECT_TEMPORARY) { |
12290 | visitURIFlags |= IHistory::REDIRECT_TEMPORARY; |
12291 | } else if (aChannelRedirectFlags & |
12292 | nsIChannelEventSink::REDIRECT_PERMANENT) { |
12293 | visitURIFlags |= IHistory::REDIRECT_PERMANENT; |
12294 | } else { |
12295 | 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." ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 12297); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aChannelRedirectFlags" ") (" "One of REDIRECT_TEMPORARY or REDIRECT_PERMANENT must be set " "if any flags in aChannelRedirectFlags is set." ")"); do { * ((volatile int*)__null) = 12297; __attribute__((nomerge)) ::abort (); } while (false); } } while (false) |
12296 | "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." ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 12297); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aChannelRedirectFlags" ") (" "One of REDIRECT_TEMPORARY or REDIRECT_PERMANENT must be set " "if any flags in aChannelRedirectFlags is set." ")"); do { * ((volatile int*)__null) = 12297; __attribute__((nomerge)) ::abort (); } while (false); } } while (false) |
12297 | "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." ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 12297); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aChannelRedirectFlags" ") (" "One of REDIRECT_TEMPORARY or REDIRECT_PERMANENT must be set " "if any flags in aChannelRedirectFlags is set." ")"); do { * ((volatile int*)__null) = 12297; __attribute__((nomerge)) ::abort (); } while (false); } } while (false); |
12298 | } |
12299 | |
12300 | if (aResponseStatus >= 300 && aResponseStatus < 400) { |
12301 | visitURIFlags |= IHistory::REDIRECT_SOURCE; |
12302 | if (aResponseStatus == 301 || aResponseStatus == 308) { |
12303 | visitURIFlags |= IHistory::REDIRECT_SOURCE_PERMANENT; |
12304 | } |
12305 | } |
12306 | // Errors 400-501 and 505 are considered unrecoverable, in the sense a |
12307 | // simple retry attempt by the user is unlikely to solve them. |
12308 | // 408 is special cased, since may actually indicate a temporary |
12309 | // connection problem. |
12310 | else if (aResponseStatus != 408 && |
12311 | ((aResponseStatus >= 400 && aResponseStatus <= 501) || |
12312 | aResponseStatus == 505)) { |
12313 | visitURIFlags |= IHistory::UNRECOVERABLE_ERROR; |
12314 | } |
12315 | |
12316 | if (aWasUpgraded) { |
12317 | visitURIFlags |= |
12318 | IHistory::REDIRECT_SOURCE | IHistory::REDIRECT_SOURCE_UPGRADED; |
12319 | } |
12320 | |
12321 | mozilla::Unused << history->VisitURI(aWidget, aURI, aPreviousURI, |
12322 | visitURIFlags, |
12323 | aBrowsingContext->BrowserId()); |
12324 | } |
12325 | } |
12326 | |
12327 | void nsDocShell::AddURIVisit(nsIURI* aURI, nsIURI* aPreviousURI, |
12328 | uint32_t aChannelRedirectFlags, |
12329 | uint32_t aResponseStatus) { |
12330 | nsPIDOMWindowOuter* outer = GetWindow(); |
12331 | nsCOMPtr<nsIWidget> widget = widget::WidgetUtils::DOMWindowToWidget(outer); |
12332 | |
12333 | InternalAddURIVisit(aURI, aPreviousURI, aChannelRedirectFlags, |
12334 | aResponseStatus, mBrowsingContext, widget, mLoadType, |
12335 | false); |
12336 | } |
12337 | |
12338 | //***************************************************************************** |
12339 | // nsDocShell: Helper Routines |
12340 | //***************************************************************************** |
12341 | |
12342 | NS_IMETHODIMPnsresult |
12343 | nsDocShell::SetLoadType(uint32_t aLoadType) { |
12344 | mLoadType = aLoadType; |
12345 | return NS_OK; |
12346 | } |
12347 | |
12348 | NS_IMETHODIMPnsresult |
12349 | nsDocShell::GetLoadType(uint32_t* aLoadType) { |
12350 | *aLoadType = mLoadType; |
12351 | return NS_OK; |
12352 | } |
12353 | |
12354 | nsresult nsDocShell::ConfirmRepost(bool* aRepost) { |
12355 | if (StaticPrefs::dom_confirm_repost_testing_always_accept()) { |
12356 | *aRepost = true; |
12357 | return NS_OK; |
12358 | } |
12359 | |
12360 | nsCOMPtr<nsIPromptCollection> prompter = |
12361 | do_GetService("@mozilla.org/embedcomp/prompt-collection;1"); |
12362 | if (!prompter) { |
12363 | return NS_ERROR_NOT_AVAILABLE; |
12364 | } |
12365 | |
12366 | return prompter->ConfirmRepost(mBrowsingContext, aRepost); |
12367 | } |
12368 | |
12369 | nsresult nsDocShell::GetPromptAndStringBundle(nsIPrompt** aPrompt, |
12370 | nsIStringBundle** aStringBundle) { |
12371 | NS_ENSURE_SUCCESS(GetInterface(NS_GET_IID(nsIPrompt), (void**)aPrompt),do { nsresult __rv = GetInterface((nsIPrompt::COMTypeInfo< nsIPrompt, void>::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::COMTypeInfo<nsIPrompt, void>::kIID), (void**)aPrompt)" , "NS_ERROR_FAILURE", static_cast<uint32_t>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""); NS_DebugBreak (NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 12372); return NS_ERROR_FAILURE; } } while (false) |
12372 | NS_ERROR_FAILURE)do { nsresult __rv = GetInterface((nsIPrompt::COMTypeInfo< nsIPrompt, void>::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::COMTypeInfo<nsIPrompt, void>::kIID), (void**)aPrompt)" , "NS_ERROR_FAILURE", static_cast<uint32_t>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""); NS_DebugBreak (NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 12372); return NS_ERROR_FAILURE; } } while (false); |
12373 | |
12374 | nsCOMPtr<nsIStringBundleService> stringBundleService = |
12375 | mozilla::components::StringBundle::Service(); |
12376 | NS_ENSURE_TRUE(stringBundleService, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(stringBundleService)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "stringBundleService" ") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 12376); return NS_ERROR_FAILURE; } } while (false); |
12377 | |
12378 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 12380); return NS_ERROR_FAILURE; } } while (false) |
12379 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 12380); return NS_ERROR_FAILURE; } } while (false) |
12380 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 12380); return NS_ERROR_FAILURE; } } while (false); |
12381 | |
12382 | return NS_OK; |
12383 | } |
12384 | |
12385 | ScrollContainerFrame* nsDocShell::GetRootScrollContainerFrame() { |
12386 | PresShell* presShell = GetPresShell(); |
12387 | NS_ENSURE_TRUE(presShell, nullptr)do { if ((__builtin_expect(!!(!(presShell)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "presShell" ") failed", nullptr , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 12387); return nullptr; } } while (false); |
12388 | |
12389 | return presShell->GetRootScrollContainerFrame(); |
12390 | } |
12391 | |
12392 | nsresult nsDocShell::EnsureScriptEnvironment() { |
12393 | if (mScriptGlobal) { |
12394 | return NS_OK; |
12395 | } |
12396 | |
12397 | if (mIsBeingDestroyed) { |
12398 | return NS_ERROR_NOT_AVAILABLE; |
12399 | } |
12400 | |
12401 | #ifdef DEBUG1 |
12402 | NS_ASSERTION(!mInEnsureScriptEnv,do { if (!(!mInEnsureScriptEnv)) { NS_DebugBreak(NS_DEBUG_ASSERTION , "Infinite loop! Calling EnsureScriptEnvironment() from " "within EnsureScriptEnvironment()!" , "!mInEnsureScriptEnv", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 12404); MOZ_PretendNoReturn(); } } while (0) |
12403 | "Infinite loop! Calling EnsureScriptEnvironment() from "do { if (!(!mInEnsureScriptEnv)) { NS_DebugBreak(NS_DEBUG_ASSERTION , "Infinite loop! Calling EnsureScriptEnvironment() from " "within EnsureScriptEnvironment()!" , "!mInEnsureScriptEnv", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 12404); MOZ_PretendNoReturn(); } } while (0) |
12404 | "within EnsureScriptEnvironment()!")do { if (!(!mInEnsureScriptEnv)) { NS_DebugBreak(NS_DEBUG_ASSERTION , "Infinite loop! Calling EnsureScriptEnvironment() from " "within EnsureScriptEnvironment()!" , "!mInEnsureScriptEnv", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 12404); MOZ_PretendNoReturn(); } } while (0); |
12405 | |
12406 | // Yeah, this isn't re-entrant safe, but that's ok since if we |
12407 | // re-enter this method, we'll infinitely loop... |
12408 | AutoRestore<bool> boolSetter(mInEnsureScriptEnv); |
12409 | mInEnsureScriptEnv = true; |
12410 | #endif |
12411 | |
12412 | nsCOMPtr<nsIWebBrowserChrome> browserChrome(do_GetInterface(mTreeOwner)); |
12413 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 12413); return NS_ERROR_NOT_AVAILABLE; } } while (false); |
12414 | |
12415 | uint32_t chromeFlags; |
12416 | browserChrome->GetChromeFlags(&chromeFlags); |
12417 | |
12418 | // If our window is modal and we're not opened as chrome, make |
12419 | // this window a modal content window. |
12420 | mScriptGlobal = nsGlobalWindowOuter::Create(this, mItemType == typeChrome); |
12421 | 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", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 12421); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mScriptGlobal" ")"); do { *((volatile int*)__null) = 12421; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
12422 | |
12423 | // Ensure the script object is set up to run script. |
12424 | return mScriptGlobal->EnsureScriptEnvironment(); |
12425 | } |
12426 | |
12427 | nsresult nsDocShell::EnsureEditorData() { |
12428 | 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" , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 12428); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mIsBeingDestroyed" ")"); do { *((volatile int*)__null) = 12428; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
12429 | |
12430 | bool openDocHasDetachedEditor = mOSHE && mOSHE->HasDetachedEditor(); |
12431 | if (!mEditorData && !mIsBeingDestroyed && !openDocHasDetachedEditor) { |
12432 | // We shouldn't recreate the editor data if it already exists, or |
12433 | // we're shutting down, or we already have a detached editor data |
12434 | // stored in the session history. We should only have one editordata |
12435 | // per docshell. |
12436 | mEditorData = MakeUnique<nsDocShellEditorData>(this); |
12437 | } |
12438 | |
12439 | return mEditorData ? NS_OK : NS_ERROR_NOT_AVAILABLE; |
12440 | } |
12441 | |
12442 | nsresult nsDocShell::EnsureFind() { |
12443 | if (!mFind) { |
12444 | mFind = new nsWebBrowserFind(); |
12445 | } |
12446 | |
12447 | // we promise that the nsIWebBrowserFind that we return has been set |
12448 | // up to point to the focused, or content window, so we have to |
12449 | // set that up each time. |
12450 | |
12451 | nsIScriptGlobalObject* scriptGO = GetScriptGlobalObject(); |
12452 | NS_ENSURE_TRUE(scriptGO, NS_ERROR_UNEXPECTED)do { if ((__builtin_expect(!!(!(scriptGO)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "scriptGO" ") failed", nullptr , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 12452); return NS_ERROR_UNEXPECTED; } } while (false); |
12453 | |
12454 | // default to our window |
12455 | nsCOMPtr<nsPIDOMWindowOuter> ourWindow = do_QueryInterface(scriptGO); |
12456 | nsCOMPtr<nsPIDOMWindowOuter> windowToSearch; |
12457 | nsFocusManager::GetFocusedDescendant(ourWindow, |
12458 | nsFocusManager::eIncludeAllDescendants, |
12459 | getter_AddRefs(windowToSearch)); |
12460 | |
12461 | nsCOMPtr<nsIWebBrowserFindInFrames> findInFrames = do_QueryInterface(mFind); |
12462 | if (!findInFrames) { |
12463 | return NS_ERROR_NO_INTERFACE; |
12464 | } |
12465 | |
12466 | nsresult rv = findInFrames->SetRootSearchFrame(ourWindow); |
12467 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
12468 | return rv; |
12469 | } |
12470 | rv = findInFrames->SetCurrentSearchFrame(windowToSearch); |
12471 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
12472 | return rv; |
12473 | } |
12474 | |
12475 | return NS_OK; |
12476 | } |
12477 | |
12478 | NS_IMETHODIMPnsresult |
12479 | nsDocShell::IsBeingDestroyed(bool* aDoomed) { |
12480 | NS_ENSURE_ARG(aDoomed)do { if ((__builtin_expect(!!(!(aDoomed)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aDoomed" ") failed", nullptr , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 12480); return NS_ERROR_INVALID_ARG; } } while (false); |
12481 | *aDoomed = mIsBeingDestroyed; |
12482 | return NS_OK; |
12483 | } |
12484 | |
12485 | NS_IMETHODIMPnsresult |
12486 | nsDocShell::GetIsExecutingOnLoadHandler(bool* aResult) { |
12487 | NS_ENSURE_ARG(aResult)do { if ((__builtin_expect(!!(!(aResult)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aResult" ") failed", nullptr , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 12487); return NS_ERROR_INVALID_ARG; } } while (false); |
12488 | *aResult = mIsExecutingOnLoadHandler; |
12489 | return NS_OK; |
12490 | } |
12491 | |
12492 | NS_IMETHODIMPnsresult |
12493 | nsDocShell::GetLayoutHistoryState(nsILayoutHistoryState** aLayoutHistoryState) { |
12494 | nsCOMPtr<nsILayoutHistoryState> state; |
12495 | if (mozilla::SessionHistoryInParent()) { |
12496 | if (mActiveEntry) { |
12497 | state = mActiveEntry->GetLayoutHistoryState(); |
12498 | } |
12499 | } else { |
12500 | if (mOSHE) { |
12501 | state = mOSHE->GetLayoutHistoryState(); |
12502 | } |
12503 | } |
12504 | state.forget(aLayoutHistoryState); |
12505 | return NS_OK; |
12506 | } |
12507 | |
12508 | NS_IMETHODIMPnsresult |
12509 | nsDocShell::SetLayoutHistoryState(nsILayoutHistoryState* aLayoutHistoryState) { |
12510 | if (mOSHE) { |
12511 | mOSHE->SetLayoutHistoryState(aLayoutHistoryState); |
12512 | } |
12513 | if (mActiveEntry) { |
12514 | mActiveEntry->SetLayoutHistoryState(aLayoutHistoryState); |
12515 | } |
12516 | return NS_OK; |
12517 | } |
12518 | |
12519 | nsDocShell::InterfaceRequestorProxy::InterfaceRequestorProxy( |
12520 | nsIInterfaceRequestor* aRequestor) { |
12521 | if (aRequestor) { |
12522 | mWeakPtr = do_GetWeakReference(aRequestor); |
12523 | } |
12524 | } |
12525 | |
12526 | nsDocShell::InterfaceRequestorProxy::~InterfaceRequestorProxy() { |
12527 | mWeakPtr = nullptr; |
12528 | } |
12529 | |
12530 | 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 12530); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0" ") (" "illegal refcnt" ")"); do { *((volatile int*)__null) = 12530; __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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 12530); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsDocShell::InterfaceRequestorProxy\" != nullptr" ") (" "Must specify a name" ")"); do { *((volatile int*)__null ) = 12530; __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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 12530); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0" ") (" "dup release" ")"); do { *((volatile int*)__null) = 12530 ; __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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 12530); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsDocShell::InterfaceRequestorProxy\" != nullptr" ") (" "Must specify a name" ")"); do { *((volatile int*)__null ) = 12530; __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" , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 12530); 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((sizeof(table) / sizeof(table [0])) > 1, "need at least 1 interface"); rv = NS_TableDrivenQI (static_cast<void*>(this), aIID, aInstancePtr, table); return rv; } |
12531 | |
12532 | NS_IMETHODIMPnsresult |
12533 | nsDocShell::InterfaceRequestorProxy::GetInterface(const nsIID& aIID, |
12534 | void** aSink) { |
12535 | NS_ENSURE_ARG_POINTER(aSink)do { if ((__builtin_expect(!!(!(aSink)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aSink" ") failed", nullptr , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 12535); return NS_ERROR_INVALID_POINTER; } } while (false); |
12536 | nsCOMPtr<nsIInterfaceRequestor> ifReq = do_QueryReferent(mWeakPtr); |
12537 | if (ifReq) { |
12538 | return ifReq->GetInterface(aIID, aSink); |
12539 | } |
12540 | *aSink = nullptr; |
12541 | return NS_NOINTERFACE; |
12542 | } |
12543 | |
12544 | //***************************************************************************** |
12545 | // nsDocShell::nsIAuthPromptProvider |
12546 | //***************************************************************************** |
12547 | |
12548 | NS_IMETHODIMPnsresult |
12549 | nsDocShell::GetAuthPrompt(uint32_t aPromptReason, const nsIID& aIID, |
12550 | void** aResult) { |
12551 | // a priority prompt request will override a false mAllowAuth setting |
12552 | bool priorityPrompt = (aPromptReason == PROMPT_PROXY); |
12553 | |
12554 | if (!mAllowAuth && !priorityPrompt) { |
12555 | return NS_ERROR_NOT_AVAILABLE; |
12556 | } |
12557 | |
12558 | // we're either allowing auth, or it's a proxy request |
12559 | nsresult rv; |
12560 | nsCOMPtr<nsIPromptFactory> wwatch = |
12561 | do_GetService(NS_WINDOWWATCHER_CONTRACTID"@mozilla.org/embedcomp/window-watcher;1", &rv); |
12562 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 12562); return rv; } } while (false); |
12563 | |
12564 | rv = EnsureScriptEnvironment(); |
12565 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 12565); return rv; } } while (false); |
12566 | |
12567 | // Get the an auth prompter for our window so that the parenting |
12568 | // of the dialogs works as it should when using tabs. |
12569 | |
12570 | return wwatch->GetPrompt(mScriptGlobal, aIID, |
12571 | reinterpret_cast<void**>(aResult)); |
12572 | } |
12573 | |
12574 | //***************************************************************************** |
12575 | // nsDocShell::nsILoadContext |
12576 | //***************************************************************************** |
12577 | |
12578 | NS_IMETHODIMPnsresult |
12579 | nsDocShell::GetAssociatedWindow(mozIDOMWindowProxy** aWindow) { |
12580 | CallGetInterface(this, aWindow); |
12581 | return NS_OK; |
12582 | } |
12583 | |
12584 | NS_IMETHODIMPnsresult |
12585 | nsDocShell::GetTopWindow(mozIDOMWindowProxy** aWindow) { |
12586 | return mBrowsingContext->GetTopWindow(aWindow); |
12587 | } |
12588 | |
12589 | NS_IMETHODIMPnsresult |
12590 | nsDocShell::GetTopFrameElement(Element** aElement) { |
12591 | return mBrowsingContext->GetTopFrameElement(aElement); |
12592 | } |
12593 | |
12594 | NS_IMETHODIMPnsresult |
12595 | nsDocShell::GetUseTrackingProtection(bool* aUseTrackingProtection) { |
12596 | return mBrowsingContext->GetUseTrackingProtection(aUseTrackingProtection); |
12597 | } |
12598 | |
12599 | NS_IMETHODIMPnsresult |
12600 | nsDocShell::SetUseTrackingProtection(bool aUseTrackingProtection) { |
12601 | return mBrowsingContext->SetUseTrackingProtection(aUseTrackingProtection); |
12602 | } |
12603 | |
12604 | NS_IMETHODIMPnsresult |
12605 | nsDocShell::GetIsContent(bool* aIsContent) { |
12606 | *aIsContent = (mItemType == typeContent); |
12607 | return NS_OK; |
12608 | } |
12609 | |
12610 | bool nsDocShell::IsOKToLoadURI(nsIURI* aURI) { |
12611 | 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!" ")" , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 12611); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aURI" ") (" "Must have a URI!" ")"); do { *((volatile int*)__null) = 12611 ; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
12612 | |
12613 | if (!mFiredUnloadEvent) { |
12614 | return true; |
12615 | } |
12616 | |
12617 | if (!mLoadingURI) { |
12618 | return false; |
12619 | } |
12620 | |
12621 | bool isPrivateWin = false; |
12622 | Document* doc = GetDocument(); |
12623 | if (doc) { |
12624 | isPrivateWin = |
12625 | doc->NodePrincipal()->OriginAttributesRef().IsPrivateBrowsing(); |
12626 | } |
12627 | |
12628 | nsCOMPtr<nsIScriptSecurityManager> secMan = |
12629 | do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID"@mozilla.org/scriptsecuritymanager;1"); |
12630 | return secMan && NS_SUCCEEDED(secMan->CheckSameOriginURI(((bool)(__builtin_expect(!!(!NS_FAILED_impl(secMan->CheckSameOriginURI ( aURI, mLoadingURI, false, isPrivateWin))), 1))) |
12631 | aURI, mLoadingURI, false, isPrivateWin))((bool)(__builtin_expect(!!(!NS_FAILED_impl(secMan->CheckSameOriginURI ( aURI, mLoadingURI, false, isPrivateWin))), 1))); |
12632 | } |
12633 | |
12634 | // |
12635 | // Routines for selection and clipboard |
12636 | // |
12637 | nsresult nsDocShell::GetControllerForCommand(const char* aCommand, |
12638 | nsIController** aResult) { |
12639 | NS_ENSURE_ARG_POINTER(aResult)do { if ((__builtin_expect(!!(!(aResult)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aResult" ") failed", nullptr , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 12639); return NS_ERROR_INVALID_POINTER; } } while (false); |
12640 | *aResult = nullptr; |
12641 | |
12642 | NS_ENSURE_TRUE(mScriptGlobal, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(mScriptGlobal)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "mScriptGlobal" ") failed" , nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 12642); return NS_ERROR_FAILURE; } } while (false); |
12643 | |
12644 | nsCOMPtr<nsPIWindowRoot> root = mScriptGlobal->GetTopWindowRoot(); |
12645 | NS_ENSURE_TRUE(root, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(root)), 0))) { NS_DebugBreak( NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "root" ") failed", nullptr , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 12645); return NS_ERROR_FAILURE; } } while (false); |
12646 | |
12647 | return root->GetControllerForCommand(aCommand, false /* for any window */, |
12648 | aResult); |
12649 | } |
12650 | |
12651 | NS_IMETHODIMPnsresult |
12652 | nsDocShell::IsCommandEnabled(const char* aCommand, bool* aResult) { |
12653 | NS_ENSURE_ARG_POINTER(aResult)do { if ((__builtin_expect(!!(!(aResult)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aResult" ") failed", nullptr , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 12653); return NS_ERROR_INVALID_POINTER; } } while (false); |
12654 | *aResult = false; |
12655 | |
12656 | nsresult rv = NS_ERROR_FAILURE; |
12657 | |
12658 | nsCOMPtr<nsIController> controller; |
12659 | rv = GetControllerForCommand(aCommand, getter_AddRefs(controller)); |
12660 | if (controller) { |
12661 | rv = controller->IsCommandEnabled(aCommand, aResult); |
12662 | } |
12663 | |
12664 | return rv; |
12665 | } |
12666 | |
12667 | NS_IMETHODIMPnsresult |
12668 | nsDocShell::DoCommand(const char* aCommand) { |
12669 | nsresult rv = NS_ERROR_FAILURE; |
12670 | |
12671 | nsCOMPtr<nsIController> controller; |
12672 | rv = GetControllerForCommand(aCommand, getter_AddRefs(controller)); |
12673 | if (controller) { |
12674 | rv = controller->DoCommand(aCommand); |
12675 | } |
12676 | |
12677 | return rv; |
12678 | } |
12679 | |
12680 | NS_IMETHODIMPnsresult |
12681 | nsDocShell::DoCommandWithParams(const char* aCommand, |
12682 | nsICommandParams* aParams) { |
12683 | nsCOMPtr<nsIController> controller; |
12684 | nsresult rv = GetControllerForCommand(aCommand, getter_AddRefs(controller)); |
12685 | if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv )), 0))), "NS_FAILED(rv)", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 12685)) { |
12686 | return rv; |
12687 | } |
12688 | |
12689 | nsCOMPtr<nsICommandController> commandController = |
12690 | do_QueryInterface(controller, &rv); |
12691 | if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv )), 0))), "NS_FAILED(rv)", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 12691)) { |
12692 | return rv; |
12693 | } |
12694 | |
12695 | return commandController->DoCommandWithParams(aCommand, aParams); |
12696 | } |
12697 | |
12698 | nsresult nsDocShell::EnsureCommandHandler() { |
12699 | if (!mCommandManager) { |
12700 | if (nsCOMPtr<nsPIDOMWindowOuter> domWindow = GetWindow()) { |
12701 | mCommandManager = new nsCommandManager(domWindow); |
12702 | } |
12703 | } |
12704 | return mCommandManager ? NS_OK : NS_ERROR_FAILURE; |
12705 | } |
12706 | |
12707 | // link handling |
12708 | |
12709 | class OnLinkClickEvent : public Runnable { |
12710 | public: |
12711 | OnLinkClickEvent(nsDocShell* aHandler, nsIContent* aContent, |
12712 | nsDocShellLoadState* aLoadState, bool aNoOpenerImplied, |
12713 | bool aIsTrusted, nsIPrincipal* aTriggeringPrincipal); |
12714 | |
12715 | NS_IMETHODvirtual nsresult Run() override { |
12716 | // We need to set up an AutoJSAPI here for the following reason: When we |
12717 | // do OnLinkClickSync we'll eventually end up in |
12718 | // nsGlobalWindow::OpenInternal which only does popup blocking if |
12719 | // !LegacyIsCallerChromeOrNativeCode(). So we need to fake things so that |
12720 | // we don't look like native code as far as LegacyIsCallerNativeCode() is |
12721 | // concerned. |
12722 | AutoJSAPI jsapi; |
12723 | if (mIsTrusted || jsapi.Init(mContent->OwnerDoc()->GetScopeObject())) { |
12724 | mHandler->OnLinkClickSync(mContent, mLoadState, mNoOpenerImplied, |
12725 | mTriggeringPrincipal); |
12726 | } |
12727 | return NS_OK; |
12728 | } |
12729 | |
12730 | private: |
12731 | RefPtr<nsDocShell> mHandler; |
12732 | nsCOMPtr<nsIContent> mContent; |
12733 | RefPtr<nsDocShellLoadState> mLoadState; |
12734 | nsCOMPtr<nsIPrincipal> mTriggeringPrincipal; |
12735 | bool mNoOpenerImplied; |
12736 | bool mIsTrusted; |
12737 | }; |
12738 | |
12739 | OnLinkClickEvent::OnLinkClickEvent(nsDocShell* aHandler, nsIContent* aContent, |
12740 | nsDocShellLoadState* aLoadState, |
12741 | bool aNoOpenerImplied, bool aIsTrusted, |
12742 | nsIPrincipal* aTriggeringPrincipal) |
12743 | : mozilla::Runnable("OnLinkClickEvent"), |
12744 | mHandler(aHandler), |
12745 | mContent(aContent), |
12746 | mLoadState(aLoadState), |
12747 | mTriggeringPrincipal(aTriggeringPrincipal), |
12748 | mNoOpenerImplied(aNoOpenerImplied), |
12749 | mIsTrusted(aIsTrusted) {} |
12750 | |
12751 | nsresult nsDocShell::OnLinkClick( |
12752 | nsIContent* aContent, nsIURI* aURI, const nsAString& aTargetSpec, |
12753 | const nsAString& aFileName, nsIInputStream* aPostDataStream, |
12754 | nsIInputStream* aHeadersDataStream, bool aIsUserTriggered, bool aIsTrusted, |
12755 | nsIPrincipal* aTriggeringPrincipal, nsIContentSecurityPolicy* aCsp) { |
12756 | #ifndef ANDROID |
12757 | 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 12757); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aTriggeringPrincipal" ") (" "Need a valid triggeringPrincipal" ")"); do { *((volatile int*)__null) = 12757; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
12758 | #endif |
12759 | NS_ASSERTION(NS_IsMainThread(), "wrong thread")do { if (!(NS_IsMainThread())) { NS_DebugBreak(NS_DEBUG_ASSERTION , "wrong thread", "NS_IsMainThread()", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 12759); MOZ_PretendNoReturn(); } } while (0); |
12760 | |
12761 | if (!IsNavigationAllowed() || !IsOKToLoadURI(aURI)) { |
12762 | return NS_OK; |
12763 | } |
12764 | |
12765 | // On history navigation through Back/Forward buttons, don't execute |
12766 | // automatic JavaScript redirection such as |anchorElement.click()| or |
12767 | // |formElement.submit()|. |
12768 | // |
12769 | // XXX |formElement.submit()| bypasses this checkpoint because it calls |
12770 | // nsDocShell::OnLinkClickSync(...) instead. |
12771 | if (ShouldBlockLoadingForBackButton()) { |
12772 | return NS_OK; |
12773 | } |
12774 | |
12775 | if (aContent->IsEditable()) { |
12776 | return NS_OK; |
12777 | } |
12778 | |
12779 | Document* ownerDoc = aContent->OwnerDoc(); |
12780 | if (nsContentUtils::IsExternalProtocol(aURI)) { |
12781 | ownerDoc->EnsureNotEnteringAndExitFullscreen(); |
12782 | } |
12783 | |
12784 | bool noOpenerImplied = false; |
12785 | nsAutoString target(aTargetSpec); |
12786 | if (aFileName.IsVoid() && |
12787 | ShouldOpenInBlankTarget(aTargetSpec, aURI, aContent, aIsUserTriggered)) { |
12788 | target = u"_blank"; |
12789 | if (!aTargetSpec.Equals(target)) { |
12790 | noOpenerImplied = true; |
12791 | } |
12792 | } |
12793 | |
12794 | RefPtr<nsDocShellLoadState> loadState = new nsDocShellLoadState(aURI); |
12795 | loadState->SetTarget(target); |
12796 | loadState->SetFileName(aFileName); |
12797 | loadState->SetPostDataStream(aPostDataStream); |
12798 | loadState->SetHeadersStream(aHeadersDataStream); |
12799 | loadState->SetFirstParty(true); |
12800 | loadState->SetTriggeringPrincipal( |
12801 | aTriggeringPrincipal ? aTriggeringPrincipal : aContent->NodePrincipal()); |
12802 | loadState->SetPrincipalToInherit(aContent->NodePrincipal()); |
12803 | loadState->SetCsp(aCsp ? aCsp : aContent->GetCsp()); |
12804 | loadState->SetAllowFocusMove(UserActivation::IsHandlingUserInput()); |
12805 | |
12806 | const bool hasValidUserGestureActivation = |
12807 | ownerDoc->HasValidTransientUserGestureActivation(); |
12808 | loadState->SetHasValidUserGestureActivation(hasValidUserGestureActivation); |
12809 | loadState->SetTextDirectiveUserActivation( |
12810 | ownerDoc->ConsumeTextDirectiveUserActivation() || |
12811 | hasValidUserGestureActivation); |
12812 | |
12813 | nsCOMPtr<nsIRunnable> ev = |
12814 | new OnLinkClickEvent(this, aContent, loadState, noOpenerImplied, |
12815 | aIsTrusted, aTriggeringPrincipal); |
12816 | return Dispatch(ev.forget()); |
12817 | } |
12818 | |
12819 | bool nsDocShell::ShouldOpenInBlankTarget(const nsAString& aOriginalTarget, |
12820 | nsIURI* aLinkURI, nsIContent* aContent, |
12821 | bool aIsUserTriggered) { |
12822 | if (net::SchemeIsJavascript(aLinkURI)) { |
12823 | return false; |
12824 | } |
12825 | |
12826 | // External links from within app tabs should always open in new tabs |
12827 | // instead of replacing the app tab's page (Bug 575561) |
12828 | // nsIURI.host can throw for non-nsStandardURL nsIURIs. If we fail to |
12829 | // get either host, just return false to use the original target. |
12830 | nsAutoCString linkHost; |
12831 | if (NS_FAILED(aLinkURI->GetHost(linkHost))((bool)(__builtin_expect(!!(NS_FAILED_impl(aLinkURI->GetHost (linkHost))), 0)))) { |
12832 | return false; |
12833 | } |
12834 | |
12835 | // The targetTopLevelLinkClicksToBlank property on BrowsingContext allows |
12836 | // privileged code to change the default targeting behaviour. In particular, |
12837 | // if a user-initiated link click for the (or targetting the) top-level frame |
12838 | // is detected, we default the target to "_blank" to give it a new |
12839 | // top-level BrowsingContext. |
12840 | if (mBrowsingContext->TargetTopLevelLinkClicksToBlank() && aIsUserTriggered && |
12841 | ((aOriginalTarget.IsEmpty() && mBrowsingContext->IsTop()) || |
12842 | aOriginalTarget == u"_top"_ns)) { |
12843 | return true; |
12844 | } |
12845 | |
12846 | // Don't modify non-default targets. |
12847 | if (!aOriginalTarget.IsEmpty()) { |
12848 | return false; |
12849 | } |
12850 | |
12851 | // Only check targets that are in extension panels or app tabs. |
12852 | // (isAppTab will be false for app tab subframes). |
12853 | nsString mmGroup = mBrowsingContext->Top()->GetMessageManagerGroup(); |
12854 | if (!mmGroup.EqualsLiteral("webext-browsers") && |
12855 | !mBrowsingContext->IsAppTab()) { |
12856 | return false; |
12857 | } |
12858 | |
12859 | nsCOMPtr<nsIURI> docURI = aContent->OwnerDoc()->GetDocumentURIObject(); |
12860 | if (!docURI) { |
12861 | return false; |
12862 | } |
12863 | |
12864 | nsAutoCString docHost; |
12865 | if (NS_FAILED(docURI->GetHost(docHost))((bool)(__builtin_expect(!!(NS_FAILED_impl(docURI->GetHost (docHost))), 0)))) { |
12866 | return false; |
12867 | } |
12868 | |
12869 | if (linkHost.Equals(docHost)) { |
12870 | return false; |
12871 | } |
12872 | |
12873 | // Special case: ignore "www" prefix if it is part of host string |
12874 | return linkHost.Length() < docHost.Length() |
12875 | ? !docHost.Equals("www."_ns + linkHost) |
12876 | : !linkHost.Equals("www."_ns + docHost); |
12877 | } |
12878 | |
12879 | static bool ElementCanHaveNoopener(nsIContent* aContent) { |
12880 | // Make sure we are dealing with either an <A>, <AREA>, or <FORM> element in |
12881 | // the HTML, XHTML, or SVG namespace. |
12882 | return aContent->IsAnyOfHTMLElements(nsGkAtoms::a, nsGkAtoms::area, |
12883 | nsGkAtoms::form) || |
12884 | aContent->IsSVGElement(nsGkAtoms::a); |
12885 | } |
12886 | |
12887 | nsresult nsDocShell::OnLinkClickSync(nsIContent* aContent, |
12888 | nsDocShellLoadState* aLoadState, |
12889 | bool aNoOpenerImplied, |
12890 | nsIPrincipal* aTriggeringPrincipal) { |
12891 | if (!IsNavigationAllowed() || !IsOKToLoadURI(aLoadState->URI())) { |
12892 | return NS_OK; |
12893 | } |
12894 | |
12895 | // XXX When the linking node was HTMLFormElement, it is synchronous event. |
12896 | // That is, the caller of this method is not |OnLinkClickEvent::Run()| |
12897 | // but |HTMLFormElement::SubmitSubmission(...)|. |
12898 | if (aContent->IsHTMLElement(nsGkAtoms::form) && |
12899 | ShouldBlockLoadingForBackButton()) { |
12900 | return NS_OK; |
12901 | } |
12902 | |
12903 | if (aContent->IsEditable()) { |
12904 | return NS_OK; |
12905 | } |
12906 | |
12907 | // if the triggeringPrincipal is not passed explicitly, then we |
12908 | // fall back to using doc->NodePrincipal() as the triggeringPrincipal. |
12909 | nsCOMPtr<nsIPrincipal> triggeringPrincipal = |
12910 | aTriggeringPrincipal ? aTriggeringPrincipal : aContent->NodePrincipal(); |
12911 | |
12912 | { |
12913 | // defer to an external protocol handler if necessary... |
12914 | nsCOMPtr<nsIExternalProtocolService> extProtService = |
12915 | do_GetService(NS_EXTERNALPROTOCOLSERVICE_CONTRACTID"@mozilla.org/uriloader/external-protocol-service;1"); |
12916 | if (extProtService) { |
12917 | nsAutoCString scheme; |
12918 | aLoadState->URI()->GetScheme(scheme); |
12919 | if (!scheme.IsEmpty()) { |
12920 | // if the URL scheme does not correspond to an exposed protocol, then |
12921 | // we need to hand this link click over to the external protocol |
12922 | // handler. |
12923 | bool isExposed; |
12924 | nsresult rv = |
12925 | extProtService->IsExposedProtocol(scheme.get(), &isExposed); |
12926 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && !isExposed) { |
12927 | return extProtService->LoadURI( |
12928 | aLoadState->URI(), triggeringPrincipal, nullptr, mBrowsingContext, |
12929 | /* aTriggeredExternally */ |
12930 | false, |
12931 | /* aHasValidUserGestureActivation */ |
12932 | aContent->OwnerDoc()->HasValidTransientUserGestureActivation(), |
12933 | /* aNewWindowTarget */ false); |
12934 | } |
12935 | } |
12936 | } |
12937 | } |
12938 | uint32_t triggeringSandboxFlags = 0; |
12939 | uint64_t triggeringWindowId = 0; |
12940 | bool triggeringStorageAccess = false; |
12941 | if (mBrowsingContext) { |
12942 | triggeringSandboxFlags = aContent->OwnerDoc()->GetSandboxFlags(); |
12943 | triggeringWindowId = aContent->OwnerDoc()->InnerWindowID(); |
12944 | triggeringStorageAccess = aContent->OwnerDoc()->UsingStorageAccess(); |
12945 | } |
12946 | |
12947 | uint32_t flags = INTERNAL_LOAD_FLAGS_NONE; |
12948 | bool elementCanHaveNoopener = ElementCanHaveNoopener(aContent); |
12949 | bool triggeringPrincipalIsSystemPrincipal = |
12950 | aLoadState->TriggeringPrincipal()->IsSystemPrincipal(); |
12951 | if (elementCanHaveNoopener) { |
12952 | 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()" , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 12952); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aContent->IsHTMLElement() || aContent->IsSVGElement()" ")"); do { *((volatile int*)__null) = 12952; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
12953 | nsAutoString relString; |
12954 | aContent->AsElement()->GetAttr(nsGkAtoms::rel, relString); |
12955 | nsWhitespaceTokenizerTemplate<nsContentUtils::IsHTMLWhitespace> tok( |
12956 | relString); |
12957 | |
12958 | bool targetBlank = aLoadState->Target().LowerCaseEqualsLiteral("_blank"); |
12959 | bool explicitOpenerSet = false; |
12960 | |
12961 | // The opener behaviour follows a hierarchy, such that if a higher |
12962 | // priority behaviour is specified, it always takes priority. That |
12963 | // priority is currently: norefrerer > noopener > opener > default |
12964 | |
12965 | while (tok.hasMoreTokens()) { |
12966 | const nsAString& token = tok.nextToken(); |
12967 | if (token.LowerCaseEqualsLiteral("noreferrer")) { |
12968 | flags |= INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER | |
12969 | INTERNAL_LOAD_FLAGS_NO_OPENER; |
12970 | // noreferrer cannot be overwritten by a 'rel=opener'. |
12971 | explicitOpenerSet = true; |
12972 | break; |
12973 | } |
12974 | |
12975 | if (token.LowerCaseEqualsLiteral("noopener")) { |
12976 | flags |= INTERNAL_LOAD_FLAGS_NO_OPENER; |
12977 | explicitOpenerSet = true; |
12978 | } |
12979 | |
12980 | if (targetBlank && StaticPrefs::dom_targetBlankNoOpener_enabled() && |
12981 | token.LowerCaseEqualsLiteral("opener") && !explicitOpenerSet) { |
12982 | explicitOpenerSet = true; |
12983 | } |
12984 | } |
12985 | |
12986 | if (targetBlank && StaticPrefs::dom_targetBlankNoOpener_enabled() && |
12987 | !explicitOpenerSet && !triggeringPrincipalIsSystemPrincipal) { |
12988 | flags |= INTERNAL_LOAD_FLAGS_NO_OPENER; |
12989 | } |
12990 | |
12991 | if (aNoOpenerImplied) { |
12992 | flags |= INTERNAL_LOAD_FLAGS_NO_OPENER; |
12993 | } |
12994 | } |
12995 | |
12996 | // Get the owner document of the link that was clicked, this will be |
12997 | // the document that the link is in, or the last document that the |
12998 | // link was in. From that document, we'll get the URI to use as the |
12999 | // referrer, since the current URI in this docshell may be a |
13000 | // new document that we're in the process of loading. |
13001 | RefPtr<Document> referrerDoc = aContent->OwnerDoc(); |
13002 | |
13003 | // Now check that the referrerDoc's inner window is the current inner |
13004 | // window for mScriptGlobal. If it's not, then we don't want to |
13005 | // follow this link. |
13006 | nsPIDOMWindowInner* referrerInner = referrerDoc->GetInnerWindow(); |
13007 | if (!mScriptGlobal || !referrerInner || |
13008 | mScriptGlobal->GetCurrentInnerWindow() != referrerInner) { |
13009 | // We're no longer the current inner window |
13010 | return NS_OK; |
13011 | } |
13012 | |
13013 | // referrer could be null here in some odd cases, but that's ok, |
13014 | // we'll just load the link w/o sending a referrer in those cases. |
13015 | |
13016 | // If this is an anchor element, grab its type property to use as a hint |
13017 | nsAutoString typeHint; |
13018 | RefPtr<HTMLAnchorElement> anchor = HTMLAnchorElement::FromNode(aContent); |
13019 | if (anchor) { |
13020 | anchor->GetType(typeHint); |
13021 | NS_ConvertUTF16toUTF8 utf8Hint(typeHint); |
13022 | nsAutoCString type, dummy; |
13023 | NS_ParseRequestContentType(utf8Hint, type, dummy); |
13024 | CopyUTF8toUTF16(type, typeHint); |
13025 | } |
13026 | |
13027 | uint32_t loadType = LOAD_LINK; |
13028 | if (aLoadState->IsFormSubmission()) { |
13029 | if (aLoadState->Target().IsEmpty()) { |
13030 | // We set the right load type here for form submissions with an empty |
13031 | // target. Form submission with a non-empty target are handled in |
13032 | // nsDocShell::PerformRetargeting after we've selected the correct target |
13033 | // BC. |
13034 | loadType = GetLoadTypeForFormSubmission(GetBrowsingContext(), aLoadState); |
13035 | } |
13036 | } else { |
13037 | // Link click can be triggered inside an onload handler, and we don't want |
13038 | // to add history entry in this case. |
13039 | bool inOnLoadHandler = false; |
13040 | GetIsExecutingOnLoadHandler(&inOnLoadHandler); |
13041 | if (inOnLoadHandler) { |
13042 | loadType = LOAD_NORMAL_REPLACE; |
13043 | } |
13044 | } |
13045 | |
13046 | nsCOMPtr<nsIReferrerInfo> referrerInfo = |
13047 | elementCanHaveNoopener ? new ReferrerInfo(*aContent->AsElement()) |
13048 | : new ReferrerInfo(*referrerDoc); |
13049 | |
13050 | aLoadState->SetTriggeringSandboxFlags(triggeringSandboxFlags); |
13051 | aLoadState->SetTriggeringWindowId(triggeringWindowId); |
13052 | aLoadState->SetTriggeringStorageAccess(triggeringStorageAccess); |
13053 | aLoadState->SetReferrerInfo(referrerInfo); |
13054 | aLoadState->SetInternalLoadFlags(flags); |
13055 | aLoadState->SetTypeHint(NS_ConvertUTF16toUTF8(typeHint)); |
13056 | aLoadState->SetLoadType(loadType); |
13057 | aLoadState->SetSourceBrowsingContext(mBrowsingContext); |
13058 | |
13059 | nsresult rv = InternalLoad(aLoadState); |
13060 | |
13061 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) { |
13062 | nsPingListener::DispatchPings(this, aContent, aLoadState->URI(), |
13063 | referrerInfo); |
13064 | } |
13065 | |
13066 | return rv; |
13067 | } |
13068 | |
13069 | nsresult nsDocShell::OnOverLink(nsIContent* aContent, nsIURI* aURI, |
13070 | const nsAString& aTargetSpec) { |
13071 | if (aContent->IsEditable()) { |
13072 | return NS_OK; |
13073 | } |
13074 | |
13075 | nsresult rv = NS_ERROR_FAILURE; |
13076 | |
13077 | nsCOMPtr<nsIWebBrowserChrome> browserChrome = do_GetInterface(mTreeOwner); |
13078 | if (!browserChrome) { |
13079 | return rv; |
13080 | } |
13081 | |
13082 | nsCOMPtr<nsIURI> exposableURI = nsIOService::CreateExposableURI(aURI); |
13083 | nsAutoCString spec; |
13084 | rv = exposableURI->GetDisplaySpec(spec); |
13085 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 13085); return rv; } } while (false); |
13086 | |
13087 | NS_ConvertUTF8toUTF16 uStr(spec); |
13088 | |
13089 | PredictorPredict(aURI, mCurrentURI, nsINetworkPredictor::PREDICT_LINK, |
13090 | aContent->NodePrincipal()->OriginAttributesRef(), nullptr); |
13091 | |
13092 | rv = browserChrome->SetLinkStatus(uStr); |
13093 | return rv; |
13094 | } |
13095 | |
13096 | nsresult nsDocShell::OnLeaveLink() { |
13097 | nsCOMPtr<nsIWebBrowserChrome> browserChrome(do_GetInterface(mTreeOwner)); |
13098 | nsresult rv = NS_ERROR_FAILURE; |
13099 | |
13100 | if (browserChrome) { |
13101 | rv = browserChrome->SetLinkStatus(u""_ns); |
13102 | } |
13103 | return rv; |
13104 | } |
13105 | |
13106 | bool nsDocShell::ShouldBlockLoadingForBackButton() { |
13107 | if (!(mLoadType & LOAD_CMD_HISTORY) || |
13108 | UserActivation::IsHandlingUserInput() || |
13109 | !Preferences::GetBool("accessibility.blockjsredirection")) { |
13110 | return false; |
13111 | } |
13112 | |
13113 | bool canGoForward = false; |
13114 | GetCanGoForward(&canGoForward); |
13115 | return canGoForward; |
13116 | } |
13117 | |
13118 | //---------------------------------------------------------------------- |
13119 | // Web Shell Services API |
13120 | |
13121 | // This functions is only called when a new charset is detected in loading a |
13122 | // document. |
13123 | nsresult nsDocShell::CharsetChangeReloadDocument( |
13124 | mozilla::NotNull<const mozilla::Encoding*> aEncoding, int32_t aSource) { |
13125 | // XXX hack. keep the aCharset and aSource wait to pick it up |
13126 | nsCOMPtr<nsIDocumentViewer> viewer; |
13127 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 13127); return NS_ERROR_FAILURE; } } while (false); |
13128 | if (viewer) { |
13129 | int32_t source; |
13130 | Unused << viewer->GetReloadEncodingAndSource(&source); |
13131 | if (aSource > source) { |
13132 | viewer->SetReloadEncodingAndSource(aEncoding, aSource); |
13133 | if (eCharsetReloadRequested != mCharsetReloadState) { |
13134 | mCharsetReloadState = eCharsetReloadRequested; |
13135 | switch (mLoadType) { |
13136 | case LOAD_RELOAD_BYPASS_PROXY_AND_CACHE: |
13137 | return Reload(LOAD_FLAGS_CHARSET_CHANGE | LOAD_FLAGS_BYPASS_CACHE | |
13138 | LOAD_FLAGS_BYPASS_PROXY); |
13139 | case LOAD_RELOAD_BYPASS_CACHE: |
13140 | return Reload(LOAD_FLAGS_CHARSET_CHANGE | LOAD_FLAGS_BYPASS_CACHE); |
13141 | default: |
13142 | return Reload(LOAD_FLAGS_CHARSET_CHANGE); |
13143 | } |
13144 | } |
13145 | } |
13146 | } |
13147 | // return failure if this request is not accepted due to mCharsetReloadState |
13148 | return NS_ERROR_DOCSHELL_REQUEST_REJECTED; |
13149 | } |
13150 | |
13151 | nsresult nsDocShell::CharsetChangeStopDocumentLoad() { |
13152 | if (eCharsetReloadRequested != mCharsetReloadState) { |
13153 | Stop(nsIWebNavigation::STOP_ALL); |
13154 | return NS_OK; |
13155 | } |
13156 | // return failer if this request is not accepted due to mCharsetReloadState |
13157 | return NS_ERROR_DOCSHELL_REQUEST_REJECTED; |
13158 | } |
13159 | |
13160 | NS_IMETHODIMPnsresult nsDocShell::ExitPrintPreview() { |
13161 | #if NS_PRINT_PREVIEW1 |
13162 | nsCOMPtr<nsIWebBrowserPrint> viewer = do_QueryInterface(mDocumentViewer); |
13163 | return viewer->ExitPrintPreview(); |
13164 | #else |
13165 | return NS_OK; |
13166 | #endif |
13167 | } |
13168 | |
13169 | /* [infallible] */ |
13170 | NS_IMETHODIMPnsresult nsDocShell::GetIsTopLevelContentDocShell( |
13171 | bool* aIsTopLevelContentDocShell) { |
13172 | *aIsTopLevelContentDocShell = false; |
13173 | |
13174 | if (mItemType == typeContent) { |
13175 | *aIsTopLevelContentDocShell = mBrowsingContext->IsTopContent(); |
13176 | } |
13177 | |
13178 | return NS_OK; |
13179 | } |
13180 | |
13181 | // Implements nsILoadContext.originAttributes |
13182 | NS_IMETHODIMPnsresult |
13183 | nsDocShell::GetScriptableOriginAttributes(JSContext* aCx, |
13184 | JS::MutableHandle<JS::Value> aVal) { |
13185 | return mBrowsingContext->GetScriptableOriginAttributes(aCx, aVal); |
13186 | } |
13187 | |
13188 | // Implements nsIDocShell.GetOriginAttributes() |
13189 | NS_IMETHODIMPnsresult |
13190 | nsDocShell::GetOriginAttributes(JSContext* aCx, |
13191 | JS::MutableHandle<JS::Value> aVal) { |
13192 | return mBrowsingContext->GetScriptableOriginAttributes(aCx, aVal); |
13193 | } |
13194 | |
13195 | bool nsDocShell::ServiceWorkerAllowedToControlWindow(nsIPrincipal* aPrincipal, |
13196 | nsIURI* aURI) { |
13197 | 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", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 13197); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPrincipal" ")"); do { *((volatile int*)__null) = 13197; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
13198 | 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", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 13198); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aURI" ")") ; do { *((volatile int*)__null) = 13198; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
13199 | |
13200 | if (UsePrivateBrowsing() || mBrowsingContext->GetSandboxFlags()) { |
13201 | return false; |
13202 | } |
13203 | |
13204 | nsCOMPtr<nsIDocShellTreeItem> parent; |
13205 | GetInProcessSameTypeParent(getter_AddRefs(parent)); |
13206 | nsPIDOMWindowOuter* parentOuter = parent ? parent->GetWindow() : nullptr; |
13207 | nsPIDOMWindowInner* parentInner = |
13208 | parentOuter ? parentOuter->GetCurrentInnerWindow() : nullptr; |
13209 | |
13210 | StorageAccess storage = |
13211 | StorageAllowedForNewWindow(aPrincipal, aURI, parentInner); |
13212 | |
13213 | // If the partitioned service worker is enabled, service worker is allowed to |
13214 | // control the window if partition is enabled. |
13215 | if (StaticPrefs::privacy_partition_serviceWorkers() && parentInner) { |
13216 | RefPtr<Document> doc = parentInner->GetExtantDoc(); |
13217 | |
13218 | if (doc && StoragePartitioningEnabled(storage, doc->CookieJarSettings())) { |
13219 | return true; |
13220 | } |
13221 | } |
13222 | |
13223 | return storage == StorageAccess::eAllow; |
13224 | } |
13225 | |
13226 | nsresult nsDocShell::SetOriginAttributes(const OriginAttributes& aAttrs) { |
13227 | 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" , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 13227); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mIsBeingDestroyed" ")"); do { *((volatile int*)__null) = 13227; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
13228 | return mBrowsingContext->SetOriginAttributes(aAttrs); |
13229 | } |
13230 | |
13231 | NS_IMETHODIMPnsresult |
13232 | nsDocShell::ResumeRedirectedLoad(uint64_t aIdentifier, int32_t aHistoryIndex) { |
13233 | RefPtr<nsDocShell> self = this; |
13234 | RefPtr<ChildProcessChannelListener> cpcl = |
13235 | ChildProcessChannelListener::GetSingleton(); |
13236 | |
13237 | // Call into InternalLoad with the pending channel when it is received. |
13238 | cpcl->RegisterCallback( |
13239 | aIdentifier, [self, aHistoryIndex]( |
13240 | nsDocShellLoadState* aLoadState, |
13241 | nsTArray<Endpoint<extensions::PStreamFilterParent>>&& |
13242 | aStreamFilterEndpoints, |
13243 | nsDOMNavigationTiming* aTiming) { |
13244 | 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()" , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 13244); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->GetPendingRedirectedChannel()" ")"); do { *((volatile int*)__null) = 13244; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
13245 | if (NS_WARN_IF(self->mIsBeingDestroyed)NS_warn_if_impl(self->mIsBeingDestroyed, "self->mIsBeingDestroyed" , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 13245)) { |
13246 | aLoadState->GetPendingRedirectedChannel()->CancelWithReason( |
13247 | NS_BINDING_ABORTED, "nsDocShell::mIsBeingDestroyed"_ns); |
13248 | return NS_BINDING_ABORTED; |
13249 | } |
13250 | |
13251 | self->mLoadType = aLoadState->LoadType(); |
13252 | nsCOMPtr<nsIURI> previousURI; |
13253 | uint32_t previousFlags = 0; |
13254 | ExtractLastVisit(aLoadState->GetPendingRedirectedChannel(), |
13255 | getter_AddRefs(previousURI), &previousFlags); |
13256 | self->SaveLastVisit(aLoadState->GetPendingRedirectedChannel(), |
13257 | previousURI, previousFlags); |
13258 | |
13259 | if (aTiming) { |
13260 | self->mTiming = new nsDOMNavigationTiming(self, aTiming); |
13261 | self->mBlankTiming = false; |
13262 | } |
13263 | |
13264 | // If we're performing a history load, locate the correct history entry, |
13265 | // and set the relevant bits on our loadState. |
13266 | if (aHistoryIndex >= 0 && self->GetSessionHistory() && |
13267 | !mozilla::SessionHistoryInParent()) { |
13268 | nsCOMPtr<nsISHistory> legacySHistory = |
13269 | self->GetSessionHistory()->LegacySHistory(); |
13270 | |
13271 | nsCOMPtr<nsISHEntry> entry; |
13272 | nsresult rv = legacySHistory->GetEntryAtIndex(aHistoryIndex, |
13273 | getter_AddRefs(entry)); |
13274 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) { |
13275 | legacySHistory->InternalSetRequestedIndex(aHistoryIndex); |
13276 | aLoadState->SetLoadType(LOAD_HISTORY); |
13277 | aLoadState->SetSHEntry(entry); |
13278 | } |
13279 | } |
13280 | |
13281 | self->InternalLoad(aLoadState); |
13282 | |
13283 | if (aLoadState->GetOriginalURIString().isSome()) { |
13284 | // Save URI string in case it's needed later when |
13285 | // sending to search engine service in EndPageLoad() |
13286 | self->mOriginalUriString = *aLoadState->GetOriginalURIString(); |
13287 | } |
13288 | |
13289 | for (auto& endpoint : aStreamFilterEndpoints) { |
13290 | extensions::StreamFilterParent::Attach( |
13291 | aLoadState->GetPendingRedirectedChannel(), std::move(endpoint)); |
13292 | } |
13293 | |
13294 | // If the channel isn't pending, then it means that InternalLoad |
13295 | // never connected it, and we shouldn't try to continue. This |
13296 | // can happen even if InternalLoad returned NS_OK. |
13297 | bool pending = false; |
13298 | aLoadState->GetPendingRedirectedChannel()->IsPending(&pending); |
13299 | 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", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 13299); MOZ_PretendNoReturn(); } } while (0); |
13300 | if (!pending) { |
13301 | return NS_BINDING_ABORTED; |
13302 | } |
13303 | return NS_OK; |
13304 | }); |
13305 | return NS_OK; |
13306 | } |
13307 | |
13308 | NS_IMETHODIMPnsresult |
13309 | nsDocShell::SetOriginAttributes(JS::Handle<JS::Value> aOriginAttributes, |
13310 | JSContext* aCx) { |
13311 | OriginAttributes attrs; |
13312 | if (!aOriginAttributes.isObject() || !attrs.Init(aCx, aOriginAttributes)) { |
13313 | return NS_ERROR_INVALID_ARG; |
13314 | } |
13315 | |
13316 | return SetOriginAttributes(attrs); |
13317 | } |
13318 | |
13319 | NS_IMETHODIMPnsresult |
13320 | nsDocShell::GetAsyncPanZoomEnabled(bool* aOut) { |
13321 | if (PresShell* presShell = GetPresShell()) { |
13322 | *aOut = presShell->AsyncPanZoomEnabled(); |
13323 | return NS_OK; |
13324 | } |
13325 | |
13326 | // If we don't have a presShell, fall back to the default platform value of |
13327 | // whether or not APZ is enabled. |
13328 | *aOut = gfxPlatform::AsyncPanZoomEnabled(); |
13329 | return NS_OK; |
13330 | } |
13331 | |
13332 | bool nsDocShell::HasUnloadedParent() { |
13333 | for (WindowContext* wc = GetBrowsingContext()->GetParentWindowContext(); wc; |
13334 | wc = wc->GetParentWindowContext()) { |
13335 | if (!wc->IsCurrent() || wc->IsDiscarded() || |
13336 | wc->GetBrowsingContext()->IsDiscarded()) { |
13337 | // If a parent is OOP and the parent WindowContext is no |
13338 | // longer current, we can assume the parent was unloaded. |
13339 | return true; |
13340 | } |
13341 | |
13342 | if (wc->GetBrowsingContext()->IsInProcess() && |
13343 | (!wc->GetBrowsingContext()->GetDocShell() || |
13344 | wc->GetBrowsingContext()->GetDocShell()->GetIsInUnload())) { |
13345 | return true; |
13346 | } |
13347 | } |
13348 | return false; |
13349 | } |
13350 | |
13351 | /* static */ |
13352 | bool nsDocShell::ShouldUpdateGlobalHistory(uint32_t aLoadType) { |
13353 | return !(aLoadType == LOAD_BYPASS_HISTORY || aLoadType == LOAD_ERROR_PAGE || |
13354 | aLoadType & LOAD_CMD_HISTORY); |
13355 | } |
13356 | |
13357 | void nsDocShell::UpdateGlobalHistoryTitle(nsIURI* aURI) { |
13358 | if (!mBrowsingContext->GetUseGlobalHistory() || UsePrivateBrowsing()) { |
13359 | return; |
13360 | } |
13361 | |
13362 | // Global history is interested into sub-frame visits only for link-coloring |
13363 | // purposes, thus title updates are skipped for those. |
13364 | // |
13365 | // Moreover, some iframe documents (such as the ones created via |
13366 | // document.open()) inherit the document uri of the caller, which would cause |
13367 | // us to override a previously set page title with one from the subframe. |
13368 | if (IsSubframe()) { |
13369 | return; |
13370 | } |
13371 | |
13372 | if (nsCOMPtr<IHistory> history = components::History::Service()) { |
13373 | history->SetURITitle(aURI, mTitle); |
13374 | } |
13375 | } |
13376 | |
13377 | bool nsDocShell::IsInvisible() { return mInvisible; } |
13378 | |
13379 | void nsDocShell::SetInvisible(bool aInvisible) { mInvisible = aInvisible; } |
13380 | |
13381 | /* static */ |
13382 | void nsDocShell::MaybeNotifyKeywordSearchLoading(const nsString& aProvider, |
13383 | const nsString& aKeyword) { |
13384 | if (aProvider.IsEmpty()) { |
13385 | return; |
13386 | } |
13387 | nsresult rv; |
13388 | nsCOMPtr<nsISupportsString> isupportsString = |
13389 | do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID"@mozilla.org/supports-string;1", &rv); |
13390 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 13390); return; } } while (false); |
13391 | |
13392 | rv = isupportsString->SetData(aProvider); |
13393 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 13393); return; } } while (false); |
13394 | |
13395 | nsCOMPtr<nsIObserverService> obsSvc = services::GetObserverService(); |
13396 | if (obsSvc) { |
13397 | // Note that "keyword-search" refers to a search via the url |
13398 | // bar, not a bookmarks keyword search. |
13399 | obsSvc->NotifyObservers(isupportsString, "keyword-search", aKeyword.get()); |
13400 | } |
13401 | } |
13402 | |
13403 | NS_IMETHODIMPnsresult |
13404 | nsDocShell::ShouldPrepareForIntercept(nsIURI* aURI, nsIChannel* aChannel, |
13405 | bool* aShouldIntercept) { |
13406 | return mInterceptController->ShouldPrepareForIntercept(aURI, aChannel, |
13407 | aShouldIntercept); |
13408 | } |
13409 | |
13410 | NS_IMETHODIMPnsresult |
13411 | nsDocShell::ChannelIntercepted(nsIInterceptedChannel* aChannel) { |
13412 | return mInterceptController->ChannelIntercepted(aChannel); |
13413 | } |
13414 | |
13415 | bool nsDocShell::InFrameSwap() { |
13416 | RefPtr<nsDocShell> shell = this; |
13417 | do { |
13418 | if (shell->mInFrameSwap) { |
13419 | return true; |
13420 | } |
13421 | shell = shell->GetInProcessParentDocshell(); |
13422 | } while (shell); |
13423 | return false; |
13424 | } |
13425 | |
13426 | UniquePtr<ClientSource> nsDocShell::TakeInitialClientSource() { |
13427 | return std::move(mInitialClientSource); |
13428 | } |
13429 | |
13430 | NS_IMETHODIMPnsresult |
13431 | nsDocShell::GetEditingSession(nsIEditingSession** aEditSession) { |
13432 | if (!NS_SUCCEEDED(EnsureEditorData())((bool)(__builtin_expect(!!(!NS_FAILED_impl(EnsureEditorData( ))), 1)))) { |
13433 | return NS_ERROR_FAILURE; |
13434 | } |
13435 | |
13436 | *aEditSession = do_AddRef(mEditorData->GetEditingSession()).take(); |
13437 | return *aEditSession ? NS_OK : NS_ERROR_FAILURE; |
13438 | } |
13439 | |
13440 | NS_IMETHODIMPnsresult |
13441 | nsDocShell::GetScriptableBrowserChild(nsIBrowserChild** aBrowserChild) { |
13442 | *aBrowserChild = GetBrowserChild().take(); |
13443 | return *aBrowserChild ? NS_OK : NS_ERROR_FAILURE; |
13444 | } |
13445 | |
13446 | already_AddRefed<nsIBrowserChild> nsDocShell::GetBrowserChild() { |
13447 | nsCOMPtr<nsIBrowserChild> tc = do_QueryReferent(mBrowserChild); |
13448 | return tc.forget(); |
13449 | } |
13450 | |
13451 | nsCommandManager* nsDocShell::GetCommandManager() { |
13452 | 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 , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 13452); return nullptr; } } while (false); |
13453 | return mCommandManager; |
13454 | } |
13455 | |
13456 | NS_IMETHODIMP_(void)void |
13457 | nsDocShell::GetOriginAttributes(mozilla::OriginAttributes& aAttrs) { |
13458 | mBrowsingContext->GetOriginAttributes(aAttrs); |
13459 | } |
13460 | |
13461 | HTMLEditor* nsIDocShell::GetHTMLEditor() { |
13462 | nsDocShell* docShell = static_cast<nsDocShell*>(this); |
13463 | return docShell->GetHTMLEditorInternal(); |
13464 | } |
13465 | |
13466 | nsresult nsIDocShell::SetHTMLEditor(HTMLEditor* aHTMLEditor) { |
13467 | nsDocShell* docShell = static_cast<nsDocShell*>(this); |
13468 | return docShell->SetHTMLEditorInternal(aHTMLEditor); |
13469 | } |
13470 | |
13471 | #define MATRIX_LENGTH 20 |
13472 | |
13473 | NS_IMETHODIMPnsresult |
13474 | nsDocShell::SetColorMatrix(const nsTArray<float>& aMatrix) { |
13475 | if (aMatrix.Length() == MATRIX_LENGTH) { |
13476 | mColorMatrix.reset(new gfx::Matrix5x4()); |
13477 | static_assert( |
13478 | MATRIX_LENGTH * sizeof(float) == sizeof(mColorMatrix->components), |
13479 | "Size mismatch for our memcpy"); |
13480 | memcpy(mColorMatrix->components, aMatrix.Elements(), |
13481 | sizeof(mColorMatrix->components)); |
13482 | } else if (aMatrix.Length() == 0) { |
13483 | mColorMatrix.reset(); |
13484 | } else { |
13485 | return NS_ERROR_INVALID_ARG; |
13486 | } |
13487 | |
13488 | PresShell* presShell = GetPresShell(); |
13489 | if (!presShell) { |
13490 | return NS_ERROR_FAILURE; |
13491 | } |
13492 | |
13493 | nsIFrame* frame = presShell->GetRootFrame(); |
13494 | if (!frame) { |
13495 | return NS_ERROR_FAILURE; |
13496 | } |
13497 | |
13498 | frame->SchedulePaint(); |
13499 | |
13500 | return NS_OK; |
13501 | } |
13502 | |
13503 | NS_IMETHODIMPnsresult |
13504 | nsDocShell::GetColorMatrix(nsTArray<float>& aMatrix) { |
13505 | if (mColorMatrix) { |
13506 | aMatrix.SetLength(MATRIX_LENGTH); |
13507 | static_assert( |
13508 | MATRIX_LENGTH * sizeof(float) == sizeof(mColorMatrix->components), |
13509 | "Size mismatch for our memcpy"); |
13510 | memcpy(aMatrix.Elements(), mColorMatrix->components, |
13511 | MATRIX_LENGTH * sizeof(float)); |
13512 | } |
13513 | |
13514 | return NS_OK; |
13515 | } |
13516 | |
13517 | #undef MATRIX_LENGTH |
13518 | |
13519 | NS_IMETHODIMPnsresult |
13520 | nsDocShell::GetIsForceReloading(bool* aForceReload) { |
13521 | *aForceReload = IsForceReloading(); |
13522 | return NS_OK; |
13523 | } |
13524 | |
13525 | bool nsDocShell::IsForceReloading() { return IsForceReloadType(mLoadType); } |
13526 | |
13527 | NS_IMETHODIMPnsresult |
13528 | nsDocShell::GetBrowsingContextXPCOM(BrowsingContext** aBrowsingContext) { |
13529 | *aBrowsingContext = do_AddRef(mBrowsingContext).take(); |
13530 | return NS_OK; |
13531 | } |
13532 | |
13533 | BrowsingContext* nsDocShell::GetBrowsingContext() { return mBrowsingContext; } |
13534 | |
13535 | bool nsDocShell::GetIsAttemptingToNavigate() { |
13536 | // XXXbz the document.open spec says to abort even if there's just a |
13537 | // queued navigation task, sort of. It's not clear whether browsers |
13538 | // actually do that, and we didn't use to do it, so for now let's |
13539 | // not do that. |
13540 | // https://github.com/whatwg/html/issues/3447 tracks the spec side of this. |
13541 | if (mDocumentRequest) { |
13542 | // There's definitely a navigation in progress. |
13543 | return true; |
13544 | } |
13545 | |
13546 | // javascript: channels have slightly weird behavior: they're LOAD_BACKGROUND |
13547 | // until the script runs, which means they're not sending loadgroup |
13548 | // notifications and hence not getting set as mDocumentRequest. Look through |
13549 | // our loadgroup for document-level javascript: loads. |
13550 | if (!mLoadGroup) { |
13551 | return false; |
13552 | } |
13553 | |
13554 | nsCOMPtr<nsISimpleEnumerator> requests; |
13555 | mLoadGroup->GetRequests(getter_AddRefs(requests)); |
13556 | bool hasMore = false; |
13557 | while (NS_SUCCEEDED(requests->HasMoreElements(&hasMore))((bool)(__builtin_expect(!!(!NS_FAILED_impl(requests->HasMoreElements (&hasMore))), 1))) && hasMore) { |
13558 | nsCOMPtr<nsISupports> elem; |
13559 | requests->GetNext(getter_AddRefs(elem)); |
13560 | nsCOMPtr<nsIScriptChannel> scriptChannel(do_QueryInterface(elem)); |
13561 | if (!scriptChannel) { |
13562 | continue; |
13563 | } |
13564 | |
13565 | if (scriptChannel->GetIsDocumentLoad()) { |
13566 | // This is a javascript: load that might lead to a new document, |
13567 | // hence a navigation. |
13568 | return true; |
13569 | } |
13570 | } |
13571 | |
13572 | return mCheckingSessionHistory; |
13573 | } |
13574 | |
13575 | void nsDocShell::SetLoadingSessionHistoryInfo( |
13576 | const mozilla::dom::LoadingSessionHistoryInfo& aLoadingInfo, |
13577 | bool aNeedToReportActiveAfterLoadingBecomesActive) { |
13578 | // FIXME Would like to assert this, but can't yet. |
13579 | // MOZ_ASSERT(!mLoadingEntry); |
13580 | 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) |
13581 | ("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) |
13582 | 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); |
13583 | mLoadingEntry = MakeUnique<LoadingSessionHistoryInfo>(aLoadingInfo); |
13584 | mNeedToReportActiveAfterLoadingBecomesActive = |
13585 | aNeedToReportActiveAfterLoadingBecomesActive; |
13586 | } |
13587 | |
13588 | void nsDocShell::MoveLoadingToActiveEntry(bool aPersist, bool aExpired, |
13589 | uint32_t aCacheKey, |
13590 | nsIURI* aPreviousURI) { |
13591 | 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()", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 13591); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mozilla::SessionHistoryInParent()" ")"); do { *((volatile int*)__null) = 13591; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
13592 | |
13593 | 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) |
13594 | ("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); |
13595 | |
13596 | UniquePtr<SessionHistoryInfo> previousActiveEntry(mActiveEntry.release()); |
13597 | mozilla::UniquePtr<mozilla::dom::LoadingSessionHistoryInfo> loadingEntry; |
13598 | mActiveEntryIsLoadingFromSessionHistory = |
13599 | mLoadingEntry && mLoadingEntry->mLoadIsFromSessionHistory; |
13600 | if (mLoadingEntry) { |
13601 | 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) |
13602 | ("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) |
13603 | "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) |
13604 | 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); |
13605 | mActiveEntry = MakeUnique<SessionHistoryInfo>(mLoadingEntry->mInfo); |
13606 | mLoadingEntry.swap(loadingEntry); |
13607 | if (!mActiveEntryIsLoadingFromSessionHistory) { |
13608 | if (mNeedToReportActiveAfterLoadingBecomesActive) { |
13609 | // Needed to pass various history length WPTs. |
13610 | mBrowsingContext->SetActiveSessionHistoryEntry( |
13611 | mozilla::Nothing(), mActiveEntry.get(), mLoadType, |
13612 | /* aUpdatedCacheKey = */ 0, false); |
13613 | } |
13614 | mBrowsingContext->IncrementHistoryEntryCountForBrowsingContext(); |
13615 | } |
13616 | } |
13617 | mNeedToReportActiveAfterLoadingBecomesActive = false; |
13618 | |
13619 | if (mActiveEntry) { |
13620 | if (aCacheKey != 0) { |
13621 | mActiveEntry->SetCacheKey(aCacheKey); |
13622 | } |
13623 | 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", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 13623); AnnotateMozCrashReason("MOZ_ASSERT" "(" "loadingEntry" ")"); do { *((volatile int*)__null) = 13623; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
13624 | uint32_t loadType = |
13625 | mLoadType == LOAD_ERROR_PAGE ? mFailedLoadType : mLoadType; |
13626 | |
13627 | if (loadingEntry->mLoadId != UINT64_MAX(18446744073709551615UL)) { |
13628 | // We're passing in mCurrentURI, which could be null. SessionHistoryCommit |
13629 | // does require a non-null uri if this is for a refresh load of the same |
13630 | // URI, but in that case mCurrentURI won't be null here. |
13631 | mBrowsingContext->SessionHistoryCommit( |
13632 | *loadingEntry, loadType, aPreviousURI, previousActiveEntry.get(), |
13633 | aPersist, false, aExpired, aCacheKey); |
13634 | } |
13635 | } |
13636 | } |
13637 | |
13638 | static bool IsFaviconLoad(nsIRequest* aRequest) { |
13639 | nsCOMPtr<nsIChannel> channel = do_QueryInterface(aRequest); |
13640 | if (!channel) { |
13641 | return false; |
13642 | } |
13643 | |
13644 | nsCOMPtr<nsILoadInfo> li = channel->LoadInfo(); |
13645 | return li && li->InternalContentPolicyType() == |
13646 | nsIContentPolicy::TYPE_INTERNAL_IMAGE_FAVICON; |
13647 | } |
13648 | |
13649 | void nsDocShell::RecordSingleChannelId(bool aStartRequest, |
13650 | nsIRequest* aRequest) { |
13651 | // Ignore favicon loads, they don't need to block caching. |
13652 | if (IsFaviconLoad(aRequest)) { |
13653 | return; |
13654 | } |
13655 | |
13656 | 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" , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 13656); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mRequestForBlockingFromBFCacheCount > 0" ")"); do { *((volatile int*)__null) = 13656; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); } } while (false); |
13657 | |
13658 | mRequestForBlockingFromBFCacheCount += aStartRequest ? 1 : -1; |
13659 | |
13660 | if (mBrowsingContext->GetCurrentWindowContext()) { |
13661 | // We have three states: no request, one request with an id and |
13662 | // eiher one request without an id or multiple requests. Nothing() is no |
13663 | // request, Some(non-zero) is one request with an id and Some(0) is one |
13664 | // request without an id or multiple requests. |
13665 | Maybe<uint64_t> singleChannelId; |
13666 | if (mRequestForBlockingFromBFCacheCount > 1) { |
13667 | singleChannelId = Some(0); |
13668 | } else if (mRequestForBlockingFromBFCacheCount == 1) { |
13669 | nsCOMPtr<nsIIdentChannel> identChannel; |
13670 | if (aStartRequest) { |
13671 | identChannel = do_QueryInterface(aRequest); |
13672 | } else { |
13673 | // aChannel is the channel that's being removed, but we need to check if |
13674 | // the remaining channel in the loadgroup has an id. |
13675 | nsCOMPtr<nsISimpleEnumerator> requests; |
13676 | mLoadGroup->GetRequests(getter_AddRefs(requests)); |
13677 | for (const auto& request : SimpleEnumerator<nsIRequest>(requests)) { |
13678 | if (!IsFaviconLoad(request) && |
13679 | !!(identChannel = do_QueryInterface(request))) { |
13680 | break; |
13681 | } |
13682 | } |
13683 | } |
13684 | |
13685 | if (identChannel) { |
13686 | singleChannelId = Some(identChannel->ChannelId()); |
13687 | } else { |
13688 | singleChannelId = Some(0); |
13689 | } |
13690 | } else { |
13691 | 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" , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 13691); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mRequestForBlockingFromBFCacheCount == 0" ")"); do { *((volatile int*)__null) = 13691; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
13692 | singleChannelId = Nothing(); |
13693 | } |
13694 | |
13695 | if (MOZ_UNLIKELY(MOZ_LOG_TEST(gSHIPBFCacheLog, LogLevel::Verbose))(__builtin_expect(!!((__builtin_expect(!!(mozilla::detail::log_test (gSHIPBFCacheLog, LogLevel::Verbose)), 0))), 0))) { |
13696 | nsAutoCString uri("[no uri]"); |
13697 | if (mCurrentURI) { |
13698 | uri = mCurrentURI->GetSpecOrDefault(); |
13699 | } |
13700 | if (singleChannelId.isNothing()) { |
13701 | 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) |
13702 | ("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) |
13703 | "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) |
13704 | 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); |
13705 | } else if (singleChannelId.value() == 0) { |
13706 | 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) |
13707 | ("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) |
13708 | "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) |
13709 | 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); |
13710 | } else { |
13711 | 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) |
13712 | ("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) |
13713 | " 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) |
13714 | 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); |
13715 | } |
13716 | } |
13717 | |
13718 | if (mSingleChannelId != singleChannelId) { |
13719 | mSingleChannelId = singleChannelId; |
13720 | WindowGlobalChild* wgc = |
13721 | mBrowsingContext->GetCurrentWindowContext()->GetWindowGlobalChild(); |
13722 | if (wgc) { |
13723 | wgc->SendSetSingleChannelId(singleChannelId); |
13724 | } |
13725 | } |
13726 | } |
13727 | } |
13728 | |
13729 | NS_IMETHODIMPnsresult |
13730 | nsDocShell::OnStartRequest(nsIRequest* aRequest) { |
13731 | if (MOZ_UNLIKELY(MOZ_LOG_TEST(gSHIPBFCacheLog, LogLevel::Verbose))(__builtin_expect(!!((__builtin_expect(!!(mozilla::detail::log_test (gSHIPBFCacheLog, LogLevel::Verbose)), 0))), 0))) { |
13732 | nsAutoCString uri("[no uri]"); |
13733 | if (mCurrentURI) { |
13734 | uri = mCurrentURI->GetSpecOrDefault(); |
13735 | } |
13736 | nsAutoCString name; |
13737 | aRequest->GetName(name); |
13738 | 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) |
13739 | ("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); |
13740 | } |
13741 | RecordSingleChannelId(true, aRequest); |
13742 | return nsDocLoader::OnStartRequest(aRequest); |
13743 | } |
13744 | |
13745 | NS_IMETHODIMPnsresult |
13746 | nsDocShell::OnStopRequest(nsIRequest* aRequest, nsresult aStatusCode) { |
13747 | if (MOZ_UNLIKELY(MOZ_LOG_TEST(gSHIPBFCacheLog, LogLevel::Verbose))(__builtin_expect(!!((__builtin_expect(!!(mozilla::detail::log_test (gSHIPBFCacheLog, LogLevel::Verbose)), 0))), 0))) { |
13748 | nsAutoCString uri("[no uri]"); |
13749 | if (mCurrentURI) { |
13750 | uri = mCurrentURI->GetSpecOrDefault(); |
13751 | } |
13752 | nsAutoCString name; |
13753 | aRequest->GetName(name); |
13754 | 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) |
13755 | 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) |
13756 | ("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); |
13757 | } |
13758 | RecordSingleChannelId(false, aRequest); |
13759 | return nsDocLoader::OnStopRequest(aRequest, aStatusCode); |
13760 | } |
13761 | |
13762 | void nsDocShell::MaybeDisconnectChildListenersOnPageHide() { |
13763 | 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()" , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 13763); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "XRE_IsContentProcess()" ")"); do { *((volatile int*)__null) = 13763; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
13764 | |
13765 | if (mChannelToDisconnectOnPageHide != 0 && mLoadGroup) { |
13766 | nsCOMPtr<nsISimpleEnumerator> requests; |
13767 | mLoadGroup->GetRequests(getter_AddRefs(requests)); |
13768 | for (const auto& request : SimpleEnumerator<nsIRequest>(requests)) { |
13769 | RefPtr<DocumentChannel> channel = do_QueryObject(request); |
13770 | if (channel && channel->ChannelId() == mChannelToDisconnectOnPageHide) { |
13771 | static_cast<DocumentChannelChild*>(channel.get()) |
13772 | ->DisconnectChildListeners(NS_BINDING_ABORTED, NS_BINDING_ABORTED); |
13773 | } |
13774 | } |
13775 | mChannelToDisconnectOnPageHide = 0; |
13776 | } |
13777 | } |