File: | var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp |
Warning: | line 3422, 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 | SetCurrentURI(doc->GetDocumentURI(), channel, |
1333 | /* aFireOnLocationChange */ true, |
1334 | /* aIsInitialAboutBlank */ false, |
1335 | /* aLocationFlags */ 0); |
1336 | mLoadGroup->RemoveRequest(channel, nullptr, NS_OK); |
1337 | mIsRestoringDocument = false; |
1338 | } |
1339 | RefPtr<PresShell> presShell = GetPresShell(); |
1340 | if (presShell) { |
1341 | presShell->Thaw(false); |
1342 | } |
1343 | |
1344 | if (inner) { |
1345 | inner->FireDelayedDOMEvents(false); |
1346 | } |
1347 | } |
1348 | } else if (!mFiredUnloadEvent) { |
1349 | // XXXBFCache check again that the page can enter bfcache. |
1350 | // XXXBFCache should mTiming->NotifyUnloadEventStart()/End() be called here? |
1351 | |
1352 | if (mRefreshURIList) { |
1353 | RefreshURIToQueue(); |
1354 | mBFCachedRefreshURIList = std::move(mRefreshURIList); |
1355 | } else { |
1356 | // If Stop was called, the list was moved to mSavedRefreshURIList after |
1357 | // calling SuspendRefreshURIs, which calls RefreshURIToQueue. |
1358 | mBFCachedRefreshURIList = std::move(mSavedRefreshURIList); |
1359 | } |
1360 | |
1361 | mFiredUnloadEvent = true; |
1362 | viewer->PageHide(false); |
1363 | |
1364 | RefPtr<PresShell> presShell = GetPresShell(); |
1365 | if (presShell) { |
1366 | presShell->Freeze(false); |
1367 | } |
1368 | } |
1369 | } |
1370 | |
1371 | nsresult nsDocShell::Dispatch(already_AddRefed<nsIRunnable>&& aRunnable) { |
1372 | nsCOMPtr<nsIRunnable> runnable(aRunnable); |
1373 | if (NS_WARN_IF(!GetWindow())NS_warn_if_impl(!GetWindow(), "!GetWindow()", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 1373)) { |
1374 | // Window should only be unavailable after destroyed. |
1375 | 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" , 1375); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mIsBeingDestroyed" ")"); do { *((volatile int*)__null) = 1375; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1376 | return NS_ERROR_FAILURE; |
1377 | } |
1378 | return SchedulerGroup::Dispatch(runnable.forget()); |
1379 | } |
1380 | |
1381 | NS_IMETHODIMPnsresult |
1382 | nsDocShell::DispatchLocationChangeEvent() { |
1383 | return Dispatch(NewRunnableMethod("nsDocShell::FireDummyOnLocationChange", |
1384 | this, |
1385 | &nsDocShell::FireDummyOnLocationChange)); |
1386 | } |
1387 | |
1388 | NS_IMETHODIMPnsresult |
1389 | nsDocShell::StartDelayedAutoplayMediaComponents() { |
1390 | RefPtr<nsPIDOMWindowOuter> outerWindow = GetWindow(); |
1391 | if (outerWindow) { |
1392 | outerWindow->ActivateMediaComponents(); |
1393 | } |
1394 | return NS_OK; |
1395 | } |
1396 | |
1397 | bool nsDocShell::MaybeInitTiming() { |
1398 | if (mTiming && !mBlankTiming) { |
1399 | return false; |
1400 | } |
1401 | |
1402 | bool canBeReset = false; |
1403 | |
1404 | if (mScriptGlobal && mBlankTiming) { |
1405 | nsPIDOMWindowInner* innerWin = mScriptGlobal->GetCurrentInnerWindow(); |
1406 | if (innerWin && innerWin->GetPerformance()) { |
1407 | mTiming = innerWin->GetPerformance()->GetDOMTiming(); |
1408 | mBlankTiming = false; |
1409 | } |
1410 | } |
1411 | |
1412 | if (!mTiming) { |
1413 | mTiming = new nsDOMNavigationTiming(this); |
1414 | canBeReset = true; |
1415 | } |
1416 | |
1417 | mTiming->NotifyNavigationStart( |
1418 | mBrowsingContext->IsActive() |
1419 | ? nsDOMNavigationTiming::DocShellState::eActive |
1420 | : nsDOMNavigationTiming::DocShellState::eInactive); |
1421 | |
1422 | return canBeReset; |
1423 | } |
1424 | |
1425 | void nsDocShell::MaybeResetInitTiming(bool aReset) { |
1426 | if (aReset) { |
1427 | mTiming = nullptr; |
1428 | } |
1429 | } |
1430 | |
1431 | nsDOMNavigationTiming* nsDocShell::GetNavigationTiming() const { |
1432 | return mTiming; |
1433 | } |
1434 | |
1435 | nsPresContext* nsDocShell::GetEldestPresContext() { |
1436 | nsIDocumentViewer* viewer = mDocumentViewer; |
1437 | while (viewer) { |
1438 | nsIDocumentViewer* prevViewer = viewer->GetPreviousViewer(); |
1439 | if (!prevViewer) { |
1440 | return viewer->GetPresContext(); |
1441 | } |
1442 | viewer = prevViewer; |
1443 | } |
1444 | |
1445 | return nullptr; |
1446 | } |
1447 | |
1448 | nsPresContext* nsDocShell::GetPresContext() { |
1449 | if (!mDocumentViewer) { |
1450 | return nullptr; |
1451 | } |
1452 | |
1453 | return mDocumentViewer->GetPresContext(); |
1454 | } |
1455 | |
1456 | PresShell* nsDocShell::GetPresShell() { |
1457 | nsPresContext* presContext = GetPresContext(); |
1458 | return presContext ? presContext->GetPresShell() : nullptr; |
1459 | } |
1460 | |
1461 | PresShell* nsDocShell::GetEldestPresShell() { |
1462 | nsPresContext* presContext = GetEldestPresContext(); |
1463 | |
1464 | if (presContext) { |
1465 | return presContext->GetPresShell(); |
1466 | } |
1467 | |
1468 | return nullptr; |
1469 | } |
1470 | |
1471 | NS_IMETHODIMPnsresult |
1472 | nsDocShell::GetDocViewer(nsIDocumentViewer** aDocumentViewer) { |
1473 | 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" , 1473); return NS_ERROR_INVALID_POINTER; } } while (false); |
1474 | |
1475 | *aDocumentViewer = mDocumentViewer; |
1476 | NS_IF_ADDREF(*aDocumentViewer)ns_if_addref(*aDocumentViewer); |
1477 | return NS_OK; |
1478 | } |
1479 | |
1480 | NS_IMETHODIMPnsresult |
1481 | nsDocShell::GetOuterWindowID(uint64_t* aWindowID) { |
1482 | *aWindowID = mContentWindowID; |
1483 | return NS_OK; |
1484 | } |
1485 | |
1486 | NS_IMETHODIMPnsresult |
1487 | nsDocShell::SetChromeEventHandler(EventTarget* aChromeEventHandler) { |
1488 | mChromeEventHandler = aChromeEventHandler; |
1489 | |
1490 | if (mScriptGlobal) { |
1491 | mScriptGlobal->SetChromeEventHandler(mChromeEventHandler); |
1492 | } |
1493 | |
1494 | return NS_OK; |
1495 | } |
1496 | |
1497 | NS_IMETHODIMPnsresult |
1498 | nsDocShell::GetChromeEventHandler(EventTarget** aChromeEventHandler) { |
1499 | 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" , 1499); return NS_ERROR_INVALID_POINTER; } } while (false); |
1500 | RefPtr<EventTarget> handler = mChromeEventHandler; |
1501 | handler.forget(aChromeEventHandler); |
1502 | return NS_OK; |
1503 | } |
1504 | |
1505 | NS_IMETHODIMPnsresult |
1506 | nsDocShell::SetCurrentURIForSessionStore(nsIURI* aURI) { |
1507 | // Note that securityUI will set STATE_IS_INSECURE, even if |
1508 | // the scheme of |aURI| is "https". |
1509 | SetCurrentURI(aURI, nullptr, |
1510 | /* aFireOnLocationChange */ |
1511 | true, |
1512 | /* aIsInitialAboutBlank */ |
1513 | false, |
1514 | /* aLocationFlags */ |
1515 | nsIWebProgressListener::LOCATION_CHANGE_SESSION_STORE); |
1516 | return NS_OK; |
1517 | } |
1518 | |
1519 | bool nsDocShell::SetCurrentURI(nsIURI* aURI, nsIRequest* aRequest, |
1520 | bool aFireOnLocationChange, |
1521 | bool aIsInitialAboutBlank, |
1522 | uint32_t aLocationFlags) { |
1523 | 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" , 1523); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mIsBeingDestroyed" ")"); do { *((volatile int*)__null) = 1523; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1524 | |
1525 | 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) |
1526 | ("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) |
1527 | 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); |
1528 | |
1529 | // We don't want to send a location change when we're displaying an error |
1530 | // page, and we don't want to change our idea of "current URI" either |
1531 | if (mLoadType == LOAD_ERROR_PAGE) { |
1532 | return false; |
1533 | } |
1534 | |
1535 | bool uriIsEqual = false; |
1536 | if (!mCurrentURI || !aURI || |
1537 | NS_FAILED(mCurrentURI->Equals(aURI, &uriIsEqual))((bool)(__builtin_expect(!!(NS_FAILED_impl(mCurrentURI->Equals (aURI, &uriIsEqual))), 0))) || !uriIsEqual) { |
1538 | mTitleValidForCurrentURI = false; |
1539 | } |
1540 | |
1541 | SetCurrentURIInternal(aURI); |
1542 | |
1543 | #ifdef DEBUG1 |
1544 | mLastOpenedURI = aURI; |
1545 | #endif |
1546 | |
1547 | if (!NS_IsAboutBlank(mCurrentURI)) { |
1548 | mHasLoadedNonBlankURI = true; |
1549 | } |
1550 | |
1551 | // Don't fire onLocationChange when creating a subframe's initial about:blank |
1552 | // document, as this can happen when it's not safe for us to run script. |
1553 | if (aIsInitialAboutBlank && !mHasLoadedNonBlankURI && |
1554 | !mBrowsingContext->IsTop()) { |
1555 | 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" , 1555); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aRequest && aLocationFlags == 0" ")"); do { *((volatile int*)__null) = 1555; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1556 | return false; |
1557 | } |
1558 | |
1559 | 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" , 1559); AnnotateMozCrashReason("MOZ_ASSERT" "(" "nsContentUtils::IsSafeToRunScript()" ")"); do { *((volatile int*)__null) = 1559; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1560 | |
1561 | if (aFireOnLocationChange) { |
1562 | FireOnLocationChange(this, aRequest, aURI, aLocationFlags); |
1563 | } |
1564 | return !aFireOnLocationChange; |
1565 | } |
1566 | |
1567 | void nsDocShell::SetCurrentURIInternal(nsIURI* aURI) { |
1568 | mCurrentURI = aURI; |
1569 | if (mBrowsingContext) { |
1570 | mBrowsingContext->ClearCachedValuesOfLocations(); |
1571 | } |
1572 | } |
1573 | |
1574 | NS_IMETHODIMPnsresult |
1575 | nsDocShell::GetCharset(nsACString& aCharset) { |
1576 | aCharset.Truncate(); |
1577 | |
1578 | PresShell* presShell = GetPresShell(); |
1579 | 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" , 1579); return NS_ERROR_FAILURE; } } while (false); |
1580 | Document* doc = presShell->GetDocument(); |
1581 | 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" , 1581); return NS_ERROR_FAILURE; } } while (false); |
1582 | doc->GetDocumentCharacterSet()->Name(aCharset); |
1583 | return NS_OK; |
1584 | } |
1585 | |
1586 | NS_IMETHODIMPnsresult |
1587 | nsDocShell::ForceEncodingDetection() { |
1588 | nsCOMPtr<nsIDocumentViewer> viewer; |
1589 | GetDocViewer(getter_AddRefs(viewer)); |
1590 | if (!viewer) { |
1591 | return NS_OK; |
1592 | } |
1593 | |
1594 | Document* doc = viewer->GetDocument(); |
1595 | if (!doc || doc->WillIgnoreCharsetOverride()) { |
1596 | return NS_OK; |
1597 | } |
1598 | |
1599 | mForcedAutodetection = true; |
1600 | |
1601 | nsIURI* url = doc->GetOriginalURI(); |
1602 | bool isFileURL = url && SchemeIsFile(url); |
1603 | |
1604 | int32_t charsetSource = doc->GetDocumentCharacterSetSource(); |
1605 | auto encoding = doc->GetDocumentCharacterSet(); |
1606 | // AsHTMLDocument is valid, because we called |
1607 | // WillIgnoreCharsetOverride() above. |
1608 | if (doc->AsHTMLDocument()->IsPlainText()) { |
1609 | switch (charsetSource) { |
1610 | case kCharsetFromInitialAutoDetectionASCII: |
1611 | // Deliberately no final version |
1612 | 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); |
1613 | Telemetry::AccumulateCategorical( |
1614 | Telemetry::LABELS_ENCODING_OVERRIDE_SITUATION_TEXT::UnlabeledAscii); |
1615 | break; |
1616 | case kCharsetFromInitialAutoDetectionWouldNotHaveBeenUTF8Generic: |
1617 | case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8Generic: |
1618 | case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8GenericInitialWasASCII: |
1619 | case kCharsetFromInitialAutoDetectionWouldNotHaveBeenUTF8Content: |
1620 | case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8Content: |
1621 | case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8ContentInitialWasASCII: |
1622 | 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); |
1623 | Telemetry::AccumulateCategorical( |
1624 | Telemetry::LABELS_ENCODING_OVERRIDE_SITUATION_TEXT:: |
1625 | UnlabeledNonUtf8); |
1626 | break; |
1627 | case kCharsetFromInitialAutoDetectionWouldNotHaveBeenUTF8DependedOnTLD: |
1628 | case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8DependedOnTLD: |
1629 | case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8DependedOnTLDInitialWasASCII: |
1630 | 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); |
1631 | Telemetry::AccumulateCategorical( |
1632 | Telemetry::LABELS_ENCODING_OVERRIDE_SITUATION_TEXT:: |
1633 | UnlabeledNonUtf8TLD); |
1634 | break; |
1635 | case kCharsetFromInitialAutoDetectionWouldHaveBeenUTF8: |
1636 | case kCharsetFromFinalAutoDetectionWouldHaveBeenUTF8InitialWasASCII: |
1637 | 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); |
1638 | Telemetry::AccumulateCategorical( |
1639 | Telemetry::LABELS_ENCODING_OVERRIDE_SITUATION_TEXT::UnlabeledUtf8); |
1640 | break; |
1641 | case kCharsetFromChannel: |
1642 | if (encoding == UTF_8_ENCODING) { |
1643 | 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); |
1644 | Telemetry::AccumulateCategorical( |
1645 | Telemetry::LABELS_ENCODING_OVERRIDE_SITUATION_TEXT::ChannelUtf8); |
1646 | } else { |
1647 | 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); |
1648 | Telemetry::AccumulateCategorical( |
1649 | Telemetry::LABELS_ENCODING_OVERRIDE_SITUATION_TEXT:: |
1650 | ChannelNonUtf8); |
1651 | } |
1652 | break; |
1653 | default: |
1654 | 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); |
1655 | Telemetry::AccumulateCategorical( |
1656 | Telemetry::LABELS_ENCODING_OVERRIDE_SITUATION_TEXT::Bug); |
1657 | break; |
1658 | } |
1659 | } else { |
1660 | switch (charsetSource) { |
1661 | case kCharsetFromInitialAutoDetectionASCII: |
1662 | // Deliberately no final version |
1663 | 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); |
1664 | Telemetry::AccumulateCategorical( |
1665 | Telemetry::LABELS_ENCODING_OVERRIDE_SITUATION_HTML::UnlabeledAscii); |
1666 | break; |
1667 | case kCharsetFromInitialAutoDetectionWouldNotHaveBeenUTF8Generic: |
1668 | case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8Generic: |
1669 | case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8GenericInitialWasASCII: |
1670 | case kCharsetFromInitialAutoDetectionWouldNotHaveBeenUTF8Content: |
1671 | case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8Content: |
1672 | case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8ContentInitialWasASCII: |
1673 | LOGCHARSETMENU(("HTML:UnlabeledNonUtf8"))do { const ::mozilla::LogModule* moz_real_module = gCharsetMenuLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print (moz_real_module, mozilla::LogLevel::Debug, "HTML:UnlabeledNonUtf8" ); } } while (0); |
1674 | Telemetry::AccumulateCategorical( |
1675 | Telemetry::LABELS_ENCODING_OVERRIDE_SITUATION_HTML:: |
1676 | UnlabeledNonUtf8); |
1677 | break; |
1678 | case kCharsetFromInitialAutoDetectionWouldNotHaveBeenUTF8DependedOnTLD: |
1679 | case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8DependedOnTLD: |
1680 | case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8DependedOnTLDInitialWasASCII: |
1681 | 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); |
1682 | Telemetry::AccumulateCategorical( |
1683 | Telemetry::LABELS_ENCODING_OVERRIDE_SITUATION_HTML:: |
1684 | UnlabeledNonUtf8TLD); |
1685 | break; |
1686 | case kCharsetFromInitialAutoDetectionWouldHaveBeenUTF8: |
1687 | case kCharsetFromFinalAutoDetectionWouldHaveBeenUTF8InitialWasASCII: |
1688 | 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); |
1689 | Telemetry::AccumulateCategorical( |
1690 | Telemetry::LABELS_ENCODING_OVERRIDE_SITUATION_HTML::UnlabeledUtf8); |
1691 | break; |
1692 | case kCharsetFromChannel: |
1693 | if (encoding == UTF_8_ENCODING) { |
1694 | 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); |
1695 | Telemetry::AccumulateCategorical( |
1696 | Telemetry::LABELS_ENCODING_OVERRIDE_SITUATION_HTML::ChannelUtf8); |
1697 | } else { |
1698 | 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); |
1699 | Telemetry::AccumulateCategorical( |
1700 | Telemetry::LABELS_ENCODING_OVERRIDE_SITUATION_HTML:: |
1701 | ChannelNonUtf8); |
1702 | } |
1703 | break; |
1704 | case kCharsetFromXmlDeclaration: |
1705 | case kCharsetFromMetaTag: |
1706 | if (isFileURL) { |
1707 | 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); |
1708 | Telemetry::AccumulateCategorical( |
1709 | Telemetry::LABELS_ENCODING_OVERRIDE_SITUATION_HTML::LocalLabeled); |
1710 | } else if (encoding == UTF_8_ENCODING) { |
1711 | 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); |
1712 | Telemetry::AccumulateCategorical( |
1713 | Telemetry::LABELS_ENCODING_OVERRIDE_SITUATION_HTML::InternalUtf8); |
1714 | } else { |
1715 | 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); |
1716 | Telemetry::AccumulateCategorical( |
1717 | Telemetry::LABELS_ENCODING_OVERRIDE_SITUATION_HTML:: |
1718 | InternalNonUtf8); |
1719 | } |
1720 | break; |
1721 | default: |
1722 | 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); |
1723 | Telemetry::AccumulateCategorical( |
1724 | Telemetry::LABELS_ENCODING_OVERRIDE_SITUATION_HTML::Bug); |
1725 | break; |
1726 | } |
1727 | } |
1728 | return NS_OK; |
1729 | } |
1730 | |
1731 | void nsDocShell::SetParentCharset(const Encoding*& aCharset, |
1732 | int32_t aCharsetSource, |
1733 | nsIPrincipal* aPrincipal) { |
1734 | mParentCharset = aCharset; |
1735 | mParentCharsetSource = aCharsetSource; |
1736 | mParentCharsetPrincipal = aPrincipal; |
1737 | } |
1738 | |
1739 | void nsDocShell::GetParentCharset(const Encoding*& aCharset, |
1740 | int32_t* aCharsetSource, |
1741 | nsIPrincipal** aPrincipal) { |
1742 | aCharset = mParentCharset; |
1743 | *aCharsetSource = mParentCharsetSource; |
1744 | NS_IF_ADDREF(*aPrincipal = mParentCharsetPrincipal)ns_if_addref(*aPrincipal = mParentCharsetPrincipal); |
1745 | } |
1746 | |
1747 | NS_IMETHODIMPnsresult |
1748 | nsDocShell::GetHasTrackingContentBlocked(Promise** aPromise) { |
1749 | 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" , 1749); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPromise" ")" ); do { *((volatile int*)__null) = 1749; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1750 | |
1751 | ErrorResult rv; |
1752 | RefPtr<Document> doc(GetDocument()); |
1753 | RefPtr<Promise> retPromise = Promise::Create(doc->GetOwnerGlobal(), rv); |
1754 | 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" , 1754)) { |
1755 | return rv.StealNSResult(); |
1756 | } |
1757 | |
1758 | // Retrieve the document's content blocking events from the parent process. |
1759 | RefPtr<Document::GetContentBlockingEventsPromise> promise = |
1760 | doc->GetContentBlockingEvents(); |
1761 | if (promise) { |
1762 | promise->Then( |
1763 | GetCurrentSerialEventTarget(), __func__, |
1764 | [retPromise](const Document::GetContentBlockingEventsPromise:: |
1765 | ResolveOrRejectValue& aValue) { |
1766 | if (aValue.IsResolve()) { |
1767 | bool has = aValue.ResolveValue() & |
1768 | nsIWebProgressListener::STATE_BLOCKED_TRACKING_CONTENT; |
1769 | retPromise->MaybeResolve(has); |
1770 | } else { |
1771 | retPromise->MaybeResolve(false); |
1772 | } |
1773 | }); |
1774 | } else { |
1775 | retPromise->MaybeResolve(false); |
1776 | } |
1777 | |
1778 | retPromise.forget(aPromise); |
1779 | return NS_OK; |
1780 | } |
1781 | |
1782 | NS_IMETHODIMPnsresult |
1783 | nsDocShell::GetCssErrorReportingEnabled(bool* aEnabled) { |
1784 | 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" , 1784); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aEnabled" ")" ); do { *((volatile int*)__null) = 1784; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1785 | *aEnabled = mCSSErrorReportingEnabled; |
1786 | return NS_OK; |
1787 | } |
1788 | |
1789 | NS_IMETHODIMPnsresult |
1790 | nsDocShell::SetCssErrorReportingEnabled(bool aEnabled) { |
1791 | mCSSErrorReportingEnabled = aEnabled; |
1792 | return NS_OK; |
1793 | } |
1794 | |
1795 | NS_IMETHODIMPnsresult |
1796 | nsDocShell::GetUsePrivateBrowsing(bool* aUsePrivateBrowsing) { |
1797 | 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" , 1797); return NS_ERROR_INVALID_POINTER; } } while (false); |
1798 | return mBrowsingContext->GetUsePrivateBrowsing(aUsePrivateBrowsing); |
1799 | } |
1800 | |
1801 | void nsDocShell::NotifyPrivateBrowsingChanged() { |
1802 | 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" , 1802); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mIsBeingDestroyed" ")"); do { *((volatile int*)__null) = 1802; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1803 | |
1804 | nsTObserverArray<nsWeakPtr>::ForwardIterator iter(mPrivacyObservers); |
1805 | while (iter.HasMore()) { |
1806 | nsWeakPtr ref = iter.GetNext(); |
1807 | nsCOMPtr<nsIPrivacyTransitionObserver> obs = do_QueryReferent(ref); |
1808 | if (!obs) { |
1809 | iter.Remove(); |
1810 | } else { |
1811 | obs->PrivateModeChanged(UsePrivateBrowsing()); |
1812 | } |
1813 | } |
1814 | } |
1815 | |
1816 | NS_IMETHODIMPnsresult |
1817 | nsDocShell::SetUsePrivateBrowsing(bool aUsePrivateBrowsing) { |
1818 | return mBrowsingContext->SetUsePrivateBrowsing(aUsePrivateBrowsing); |
1819 | } |
1820 | |
1821 | NS_IMETHODIMPnsresult |
1822 | nsDocShell::SetPrivateBrowsing(bool aUsePrivateBrowsing) { |
1823 | return mBrowsingContext->SetPrivateBrowsing(aUsePrivateBrowsing); |
1824 | } |
1825 | |
1826 | NS_IMETHODIMPnsresult |
1827 | nsDocShell::GetHasLoadedNonBlankURI(bool* aResult) { |
1828 | 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" , 1828); return NS_ERROR_INVALID_POINTER; } } while (false); |
1829 | |
1830 | *aResult = mHasLoadedNonBlankURI; |
1831 | return NS_OK; |
1832 | } |
1833 | |
1834 | NS_IMETHODIMPnsresult |
1835 | nsDocShell::GetUseRemoteTabs(bool* aUseRemoteTabs) { |
1836 | 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" , 1836); return NS_ERROR_INVALID_POINTER; } } while (false); |
1837 | return mBrowsingContext->GetUseRemoteTabs(aUseRemoteTabs); |
1838 | } |
1839 | |
1840 | NS_IMETHODIMPnsresult |
1841 | nsDocShell::SetRemoteTabs(bool aUseRemoteTabs) { |
1842 | return mBrowsingContext->SetRemoteTabs(aUseRemoteTabs); |
1843 | } |
1844 | |
1845 | NS_IMETHODIMPnsresult |
1846 | nsDocShell::GetUseRemoteSubframes(bool* aUseRemoteSubframes) { |
1847 | 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" , 1847); return NS_ERROR_INVALID_POINTER; } } while (false); |
1848 | return mBrowsingContext->GetUseRemoteSubframes(aUseRemoteSubframes); |
1849 | } |
1850 | |
1851 | NS_IMETHODIMPnsresult |
1852 | nsDocShell::SetRemoteSubframes(bool aUseRemoteSubframes) { |
1853 | return mBrowsingContext->SetRemoteSubframes(aUseRemoteSubframes); |
1854 | } |
1855 | |
1856 | NS_IMETHODIMPnsresult |
1857 | nsDocShell::AddWeakPrivacyTransitionObserver( |
1858 | nsIPrivacyTransitionObserver* aObserver) { |
1859 | nsWeakPtr weakObs = do_GetWeakReference(aObserver); |
1860 | if (!weakObs) { |
1861 | return NS_ERROR_NOT_AVAILABLE; |
1862 | } |
1863 | mPrivacyObservers.AppendElement(weakObs); |
1864 | return NS_OK; |
1865 | } |
1866 | |
1867 | NS_IMETHODIMPnsresult |
1868 | nsDocShell::AddWeakReflowObserver(nsIReflowObserver* aObserver) { |
1869 | nsWeakPtr weakObs = do_GetWeakReference(aObserver); |
1870 | if (!weakObs) { |
1871 | return NS_ERROR_FAILURE; |
1872 | } |
1873 | mReflowObservers.AppendElement(weakObs); |
1874 | return NS_OK; |
1875 | } |
1876 | |
1877 | NS_IMETHODIMPnsresult |
1878 | nsDocShell::RemoveWeakReflowObserver(nsIReflowObserver* aObserver) { |
1879 | nsWeakPtr obs = do_GetWeakReference(aObserver); |
1880 | return mReflowObservers.RemoveElement(obs) ? NS_OK : NS_ERROR_FAILURE; |
1881 | } |
1882 | |
1883 | NS_IMETHODIMPnsresult |
1884 | nsDocShell::NotifyReflowObservers(bool aInterruptible, |
1885 | DOMHighResTimeStamp aStart, |
1886 | DOMHighResTimeStamp aEnd) { |
1887 | nsTObserverArray<nsWeakPtr>::ForwardIterator iter(mReflowObservers); |
1888 | while (iter.HasMore()) { |
1889 | nsWeakPtr ref = iter.GetNext(); |
1890 | nsCOMPtr<nsIReflowObserver> obs = do_QueryReferent(ref); |
1891 | if (!obs) { |
1892 | iter.Remove(); |
1893 | } else if (aInterruptible) { |
1894 | obs->ReflowInterruptible(aStart, aEnd); |
1895 | } else { |
1896 | obs->Reflow(aStart, aEnd); |
1897 | } |
1898 | } |
1899 | return NS_OK; |
1900 | } |
1901 | |
1902 | NS_IMETHODIMPnsresult |
1903 | nsDocShell::GetAllowMetaRedirects(bool* aReturn) { |
1904 | 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" , 1904); return NS_ERROR_INVALID_POINTER; } } while (false); |
1905 | |
1906 | *aReturn = mAllowMetaRedirects; |
1907 | return NS_OK; |
1908 | } |
1909 | |
1910 | NS_IMETHODIMPnsresult |
1911 | nsDocShell::SetAllowMetaRedirects(bool aValue) { |
1912 | mAllowMetaRedirects = aValue; |
1913 | return NS_OK; |
1914 | } |
1915 | |
1916 | NS_IMETHODIMPnsresult |
1917 | nsDocShell::GetAllowSubframes(bool* aAllowSubframes) { |
1918 | 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" , 1918); return NS_ERROR_INVALID_POINTER; } } while (false); |
1919 | |
1920 | *aAllowSubframes = mAllowSubframes; |
1921 | return NS_OK; |
1922 | } |
1923 | |
1924 | NS_IMETHODIMPnsresult |
1925 | nsDocShell::SetAllowSubframes(bool aAllowSubframes) { |
1926 | mAllowSubframes = aAllowSubframes; |
1927 | return NS_OK; |
1928 | } |
1929 | |
1930 | NS_IMETHODIMPnsresult |
1931 | nsDocShell::GetAllowImages(bool* aAllowImages) { |
1932 | 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" , 1932); return NS_ERROR_INVALID_POINTER; } } while (false); |
1933 | |
1934 | *aAllowImages = mAllowImages; |
1935 | return NS_OK; |
1936 | } |
1937 | |
1938 | NS_IMETHODIMPnsresult |
1939 | nsDocShell::SetAllowImages(bool aAllowImages) { |
1940 | mAllowImages = aAllowImages; |
1941 | return NS_OK; |
1942 | } |
1943 | |
1944 | NS_IMETHODIMPnsresult |
1945 | nsDocShell::GetAllowMedia(bool* aAllowMedia) { |
1946 | *aAllowMedia = mAllowMedia; |
1947 | return NS_OK; |
1948 | } |
1949 | |
1950 | NS_IMETHODIMPnsresult |
1951 | nsDocShell::SetAllowMedia(bool aAllowMedia) { |
1952 | mAllowMedia = aAllowMedia; |
1953 | |
1954 | // Mute or unmute audio contexts attached to the inner window. |
1955 | if (mScriptGlobal) { |
1956 | if (nsPIDOMWindowInner* innerWin = mScriptGlobal->GetCurrentInnerWindow()) { |
1957 | if (aAllowMedia) { |
1958 | innerWin->UnmuteAudioContexts(); |
1959 | } else { |
1960 | innerWin->MuteAudioContexts(); |
1961 | } |
1962 | } |
1963 | } |
1964 | |
1965 | return NS_OK; |
1966 | } |
1967 | |
1968 | NS_IMETHODIMPnsresult |
1969 | nsDocShell::GetAllowDNSPrefetch(bool* aAllowDNSPrefetch) { |
1970 | *aAllowDNSPrefetch = mAllowDNSPrefetch; |
1971 | return NS_OK; |
1972 | } |
1973 | |
1974 | NS_IMETHODIMPnsresult |
1975 | nsDocShell::SetAllowDNSPrefetch(bool aAllowDNSPrefetch) { |
1976 | mAllowDNSPrefetch = aAllowDNSPrefetch; |
1977 | return NS_OK; |
1978 | } |
1979 | |
1980 | NS_IMETHODIMPnsresult |
1981 | nsDocShell::GetAllowWindowControl(bool* aAllowWindowControl) { |
1982 | *aAllowWindowControl = mAllowWindowControl; |
1983 | return NS_OK; |
1984 | } |
1985 | |
1986 | NS_IMETHODIMPnsresult |
1987 | nsDocShell::SetAllowWindowControl(bool aAllowWindowControl) { |
1988 | mAllowWindowControl = aAllowWindowControl; |
1989 | return NS_OK; |
1990 | } |
1991 | |
1992 | NS_IMETHODIMPnsresult |
1993 | nsDocShell::GetAllowContentRetargeting(bool* aAllowContentRetargeting) { |
1994 | *aAllowContentRetargeting = mBrowsingContext->GetAllowContentRetargeting(); |
1995 | return NS_OK; |
1996 | } |
1997 | |
1998 | NS_IMETHODIMPnsresult |
1999 | nsDocShell::SetAllowContentRetargeting(bool aAllowContentRetargeting) { |
2000 | BrowsingContext::Transaction txn; |
2001 | txn.SetAllowContentRetargeting(aAllowContentRetargeting); |
2002 | txn.SetAllowContentRetargetingOnChildren(aAllowContentRetargeting); |
2003 | return txn.Commit(mBrowsingContext); |
2004 | } |
2005 | |
2006 | NS_IMETHODIMPnsresult |
2007 | nsDocShell::GetAllowContentRetargetingOnChildren( |
2008 | bool* aAllowContentRetargetingOnChildren) { |
2009 | *aAllowContentRetargetingOnChildren = |
2010 | mBrowsingContext->GetAllowContentRetargetingOnChildren(); |
2011 | return NS_OK; |
2012 | } |
2013 | |
2014 | NS_IMETHODIMPnsresult |
2015 | nsDocShell::SetAllowContentRetargetingOnChildren( |
2016 | bool aAllowContentRetargetingOnChildren) { |
2017 | return mBrowsingContext->SetAllowContentRetargetingOnChildren( |
2018 | aAllowContentRetargetingOnChildren); |
2019 | } |
2020 | |
2021 | NS_IMETHODIMPnsresult |
2022 | nsDocShell::GetMayEnableCharacterEncodingMenu( |
2023 | bool* aMayEnableCharacterEncodingMenu) { |
2024 | *aMayEnableCharacterEncodingMenu = false; |
2025 | if (!mDocumentViewer) { |
2026 | return NS_OK; |
2027 | } |
2028 | Document* doc = mDocumentViewer->GetDocument(); |
2029 | if (!doc) { |
2030 | return NS_OK; |
2031 | } |
2032 | if (doc->WillIgnoreCharsetOverride()) { |
2033 | return NS_OK; |
2034 | } |
2035 | |
2036 | *aMayEnableCharacterEncodingMenu = true; |
2037 | return NS_OK; |
2038 | } |
2039 | |
2040 | NS_IMETHODIMPnsresult |
2041 | nsDocShell::GetAllDocShellsInSubtree(int32_t aItemType, |
2042 | DocShellEnumeratorDirection aDirection, |
2043 | nsTArray<RefPtr<nsIDocShell>>& aResult) { |
2044 | aResult.Clear(); |
2045 | |
2046 | nsDocShellEnumerator docShellEnum( |
2047 | (aDirection == ENUMERATE_FORWARDS) |
2048 | ? nsDocShellEnumerator::EnumerationDirection::Forwards |
2049 | : nsDocShellEnumerator::EnumerationDirection::Backwards, |
2050 | aItemType, *this); |
2051 | |
2052 | nsresult rv = docShellEnum.BuildDocShellArray(aResult); |
2053 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
2054 | return rv; |
2055 | } |
2056 | |
2057 | return NS_OK; |
2058 | } |
2059 | |
2060 | NS_IMETHODIMPnsresult |
2061 | nsDocShell::GetAppType(AppType* aAppType) { |
2062 | *aAppType = mAppType; |
2063 | return NS_OK; |
2064 | } |
2065 | |
2066 | NS_IMETHODIMPnsresult |
2067 | nsDocShell::SetAppType(AppType aAppType) { |
2068 | mAppType = aAppType; |
2069 | return NS_OK; |
2070 | } |
2071 | |
2072 | NS_IMETHODIMPnsresult |
2073 | nsDocShell::GetAllowAuth(bool* aAllowAuth) { |
2074 | *aAllowAuth = mAllowAuth; |
2075 | return NS_OK; |
2076 | } |
2077 | |
2078 | NS_IMETHODIMPnsresult |
2079 | nsDocShell::SetAllowAuth(bool aAllowAuth) { |
2080 | mAllowAuth = aAllowAuth; |
2081 | return NS_OK; |
2082 | } |
2083 | |
2084 | NS_IMETHODIMPnsresult |
2085 | nsDocShell::GetZoom(float* aZoom) { |
2086 | 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" , 2086); return NS_ERROR_INVALID_POINTER; } } while (false); |
2087 | *aZoom = 1.0f; |
2088 | return NS_OK; |
2089 | } |
2090 | |
2091 | NS_IMETHODIMPnsresult |
2092 | nsDocShell::SetZoom(float aZoom) { return NS_ERROR_NOT_IMPLEMENTED; } |
2093 | |
2094 | NS_IMETHODIMPnsresult |
2095 | nsDocShell::GetBusyFlags(BusyFlags* aBusyFlags) { |
2096 | 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" , 2096); return NS_ERROR_INVALID_POINTER; } } while (false); |
2097 | |
2098 | *aBusyFlags = mBusyFlags; |
2099 | return NS_OK; |
2100 | } |
2101 | |
2102 | NS_IMETHODIMPnsresult |
2103 | nsDocShell::GetLoadURIDelegate(nsILoadURIDelegate** aLoadURIDelegate) { |
2104 | nsCOMPtr<nsILoadURIDelegate> delegate = GetLoadURIDelegate(); |
2105 | delegate.forget(aLoadURIDelegate); |
2106 | return NS_OK; |
2107 | } |
2108 | |
2109 | already_AddRefed<nsILoadURIDelegate> nsDocShell::GetLoadURIDelegate() { |
2110 | if (nsCOMPtr<nsILoadURIDelegate> result = |
2111 | do_QueryActor("LoadURIDelegate", GetDocument())) { |
2112 | return result.forget(); |
2113 | } |
2114 | |
2115 | return nullptr; |
2116 | } |
2117 | |
2118 | NS_IMETHODIMPnsresult |
2119 | nsDocShell::GetUseErrorPages(bool* aUseErrorPages) { |
2120 | *aUseErrorPages = mBrowsingContext->GetUseErrorPages(); |
2121 | return NS_OK; |
2122 | } |
2123 | |
2124 | NS_IMETHODIMPnsresult |
2125 | nsDocShell::SetUseErrorPages(bool aUseErrorPages) { |
2126 | return mBrowsingContext->SetUseErrorPages(aUseErrorPages); |
2127 | } |
2128 | |
2129 | NS_IMETHODIMPnsresult |
2130 | nsDocShell::GetPreviousEntryIndex(int32_t* aPreviousEntryIndex) { |
2131 | *aPreviousEntryIndex = mPreviousEntryIndex; |
2132 | return NS_OK; |
2133 | } |
2134 | |
2135 | NS_IMETHODIMPnsresult |
2136 | nsDocShell::GetLoadedEntryIndex(int32_t* aLoadedEntryIndex) { |
2137 | *aLoadedEntryIndex = mLoadedEntryIndex; |
2138 | return NS_OK; |
2139 | } |
2140 | |
2141 | NS_IMETHODIMPnsresult |
2142 | nsDocShell::HistoryPurged(int32_t aNumEntries) { |
2143 | // These indices are used for fastback cache eviction, to determine |
2144 | // which session history entries are candidates for content viewer |
2145 | // eviction. We need to adjust by the number of entries that we |
2146 | // just purged from history, so that we look at the right session history |
2147 | // entries during eviction. |
2148 | mPreviousEntryIndex = std::max(-1, mPreviousEntryIndex - aNumEntries); |
2149 | mLoadedEntryIndex = std::max(0, mLoadedEntryIndex - aNumEntries); |
2150 | |
2151 | for (auto* child : mChildList.ForwardRange()) { |
2152 | nsCOMPtr<nsIDocShell> shell = do_QueryObject(child); |
2153 | if (shell) { |
2154 | shell->HistoryPurged(aNumEntries); |
2155 | } |
2156 | } |
2157 | |
2158 | return NS_OK; |
2159 | } |
2160 | |
2161 | nsresult nsDocShell::HistoryEntryRemoved(int32_t aIndex) { |
2162 | // These indices are used for fastback cache eviction, to determine |
2163 | // which session history entries are candidates for content viewer |
2164 | // eviction. We need to adjust by the number of entries that we |
2165 | // just purged from history, so that we look at the right session history |
2166 | // entries during eviction. |
2167 | if (aIndex == mPreviousEntryIndex) { |
2168 | mPreviousEntryIndex = -1; |
2169 | } else if (aIndex < mPreviousEntryIndex) { |
2170 | --mPreviousEntryIndex; |
2171 | } |
2172 | if (mLoadedEntryIndex == aIndex) { |
2173 | mLoadedEntryIndex = 0; |
2174 | } else if (aIndex < mLoadedEntryIndex) { |
2175 | --mLoadedEntryIndex; |
2176 | } |
2177 | |
2178 | for (auto* child : mChildList.ForwardRange()) { |
2179 | nsCOMPtr<nsIDocShell> shell = do_QueryObject(child); |
2180 | if (shell) { |
2181 | static_cast<nsDocShell*>(shell.get())->HistoryEntryRemoved(aIndex); |
2182 | } |
2183 | } |
2184 | |
2185 | return NS_OK; |
2186 | } |
2187 | |
2188 | nsresult nsDocShell::Now(DOMHighResTimeStamp* aWhen) { |
2189 | *aWhen = (TimeStamp::Now() - TimeStamp::ProcessCreation()).ToMilliseconds(); |
2190 | return NS_OK; |
2191 | } |
2192 | |
2193 | NS_IMETHODIMPnsresult |
2194 | nsDocShell::SetWindowDraggingAllowed(bool aValue) { |
2195 | RefPtr<nsDocShell> parent = GetInProcessParentDocshell(); |
2196 | if (!aValue && mItemType == typeChrome && !parent) { |
2197 | // Window dragging is always allowed for top level |
2198 | // chrome docshells. |
2199 | return NS_ERROR_FAILURE; |
2200 | } |
2201 | mWindowDraggingAllowed = aValue; |
2202 | return NS_OK; |
2203 | } |
2204 | |
2205 | NS_IMETHODIMPnsresult |
2206 | nsDocShell::GetWindowDraggingAllowed(bool* aValue) { |
2207 | // window dragging regions in CSS (-moz-window-drag:drag) |
2208 | // can be slow. Default behavior is to only allow it for |
2209 | // chrome top level windows. |
2210 | RefPtr<nsDocShell> parent = GetInProcessParentDocshell(); |
2211 | if (mItemType == typeChrome && !parent) { |
2212 | // Top level chrome window |
2213 | *aValue = true; |
2214 | } else { |
2215 | *aValue = mWindowDraggingAllowed; |
2216 | } |
2217 | return NS_OK; |
2218 | } |
2219 | |
2220 | NS_IMETHODIMPnsresult |
2221 | nsDocShell::GetCurrentDocumentChannel(nsIChannel** aResult) { |
2222 | NS_IF_ADDREF(*aResult = GetCurrentDocChannel())ns_if_addref(*aResult = GetCurrentDocChannel()); |
2223 | return NS_OK; |
2224 | } |
2225 | |
2226 | nsIChannel* nsDocShell::GetCurrentDocChannel() { |
2227 | if (mDocumentViewer) { |
2228 | Document* doc = mDocumentViewer->GetDocument(); |
2229 | if (doc) { |
2230 | return doc->GetChannel(); |
2231 | } |
2232 | } |
2233 | return nullptr; |
2234 | } |
2235 | |
2236 | NS_IMETHODIMPnsresult |
2237 | nsDocShell::AddWeakScrollObserver(nsIScrollObserver* aObserver) { |
2238 | nsWeakPtr weakObs = do_GetWeakReference(aObserver); |
2239 | if (!weakObs) { |
2240 | return NS_ERROR_FAILURE; |
2241 | } |
2242 | mScrollObservers.AppendElement(weakObs); |
2243 | return NS_OK; |
2244 | } |
2245 | |
2246 | NS_IMETHODIMPnsresult |
2247 | nsDocShell::RemoveWeakScrollObserver(nsIScrollObserver* aObserver) { |
2248 | nsWeakPtr obs = do_GetWeakReference(aObserver); |
2249 | return mScrollObservers.RemoveElement(obs) ? NS_OK : NS_ERROR_FAILURE; |
2250 | } |
2251 | |
2252 | void nsDocShell::NotifyAsyncPanZoomStarted() { |
2253 | nsTObserverArray<nsWeakPtr>::ForwardIterator iter(mScrollObservers); |
2254 | while (iter.HasMore()) { |
2255 | nsWeakPtr ref = iter.GetNext(); |
2256 | nsCOMPtr<nsIScrollObserver> obs = do_QueryReferent(ref); |
2257 | if (obs) { |
2258 | obs->AsyncPanZoomStarted(); |
2259 | } else { |
2260 | iter.Remove(); |
2261 | } |
2262 | } |
2263 | } |
2264 | |
2265 | void nsDocShell::NotifyAsyncPanZoomStopped() { |
2266 | nsTObserverArray<nsWeakPtr>::ForwardIterator iter(mScrollObservers); |
2267 | while (iter.HasMore()) { |
2268 | nsWeakPtr ref = iter.GetNext(); |
2269 | nsCOMPtr<nsIScrollObserver> obs = do_QueryReferent(ref); |
2270 | if (obs) { |
2271 | obs->AsyncPanZoomStopped(); |
2272 | } else { |
2273 | iter.Remove(); |
2274 | } |
2275 | } |
2276 | } |
2277 | |
2278 | NS_IMETHODIMPnsresult |
2279 | nsDocShell::NotifyScrollObservers() { |
2280 | nsTObserverArray<nsWeakPtr>::ForwardIterator iter(mScrollObservers); |
2281 | while (iter.HasMore()) { |
2282 | nsWeakPtr ref = iter.GetNext(); |
2283 | nsCOMPtr<nsIScrollObserver> obs = do_QueryReferent(ref); |
2284 | if (obs) { |
2285 | obs->ScrollPositionChanged(); |
2286 | } else { |
2287 | iter.Remove(); |
2288 | } |
2289 | } |
2290 | return NS_OK; |
2291 | } |
2292 | |
2293 | //***************************************************************************** |
2294 | // nsDocShell::nsIDocShellTreeItem |
2295 | //***************************************************************************** |
2296 | |
2297 | NS_IMETHODIMPnsresult |
2298 | nsDocShell::GetName(nsAString& aName) { |
2299 | aName = mBrowsingContext->Name(); |
2300 | return NS_OK; |
2301 | } |
2302 | |
2303 | NS_IMETHODIMPnsresult |
2304 | nsDocShell::SetName(const nsAString& aName) { |
2305 | return mBrowsingContext->SetName(aName); |
2306 | } |
2307 | |
2308 | NS_IMETHODIMPnsresult |
2309 | nsDocShell::NameEquals(const nsAString& aName, bool* aResult) { |
2310 | 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" , 2310); return NS_ERROR_INVALID_POINTER; } } while (false); |
2311 | *aResult = mBrowsingContext->NameEquals(aName); |
2312 | return NS_OK; |
2313 | } |
2314 | |
2315 | NS_IMETHODIMPnsresult |
2316 | nsDocShell::GetCustomUserAgent(nsAString& aCustomUserAgent) { |
2317 | mBrowsingContext->GetCustomUserAgent(aCustomUserAgent); |
2318 | return NS_OK; |
2319 | } |
2320 | |
2321 | NS_IMETHODIMPnsresult |
2322 | nsDocShell::SetCustomUserAgent(const nsAString& aCustomUserAgent) { |
2323 | if (mWillChangeProcess) { |
2324 | 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" , 2324); |
2325 | return NS_ERROR_FAILURE; |
2326 | } |
2327 | |
2328 | return mBrowsingContext->SetCustomUserAgent(aCustomUserAgent); |
2329 | } |
2330 | |
2331 | NS_IMETHODIMPnsresult |
2332 | nsDocShell::ClearCachedPlatform() { |
2333 | nsCOMPtr<nsPIDOMWindowInner> win = |
2334 | mScriptGlobal ? mScriptGlobal->GetCurrentInnerWindow() : nullptr; |
2335 | if (win) { |
2336 | Navigator* navigator = win->Navigator(); |
2337 | if (navigator) { |
2338 | navigator->ClearPlatformCache(); |
2339 | } |
2340 | } |
2341 | |
2342 | return NS_OK; |
2343 | } |
2344 | |
2345 | NS_IMETHODIMPnsresult |
2346 | nsDocShell::ClearCachedUserAgent() { |
2347 | nsCOMPtr<nsPIDOMWindowInner> win = |
2348 | mScriptGlobal ? mScriptGlobal->GetCurrentInnerWindow() : nullptr; |
2349 | if (win) { |
2350 | Navigator* navigator = win->Navigator(); |
2351 | if (navigator) { |
2352 | navigator->ClearUserAgentCache(); |
2353 | } |
2354 | } |
2355 | |
2356 | return NS_OK; |
2357 | } |
2358 | |
2359 | /* virtual */ |
2360 | int32_t nsDocShell::ItemType() { return mItemType; } |
2361 | |
2362 | NS_IMETHODIMPnsresult |
2363 | nsDocShell::GetItemType(int32_t* aItemType) { |
2364 | 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" , 2364); return NS_ERROR_INVALID_POINTER; } } while (false); |
2365 | |
2366 | 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" , 2367); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "(mBrowsingContext->IsContent() ? typeContent : typeChrome) == mItemType" ")"); do { *((volatile int*)__null) = 2367; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
2367 | (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" , 2367); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "(mBrowsingContext->IsContent() ? typeContent : typeChrome) == mItemType" ")"); do { *((volatile int*)__null) = 2367; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2368 | *aItemType = mItemType; |
2369 | return NS_OK; |
2370 | } |
2371 | |
2372 | NS_IMETHODIMPnsresult |
2373 | nsDocShell::GetInProcessParent(nsIDocShellTreeItem** aParent) { |
2374 | if (!mParent) { |
2375 | *aParent = nullptr; |
2376 | } else { |
2377 | CallQueryInterface(mParent, aParent); |
2378 | } |
2379 | // Note that in the case when the parent is not an nsIDocShellTreeItem we |
2380 | // don't want to throw; we just want to return null. |
2381 | return NS_OK; |
2382 | } |
2383 | |
2384 | // With Fission, related nsDocShell objects may exist in a different process. In |
2385 | // that case, this method will return `nullptr`, despite a parent nsDocShell |
2386 | // object existing. |
2387 | // |
2388 | // Prefer using `BrowsingContext::Parent()`, which will succeed even if the |
2389 | // parent entry is not in the current process, and handle the case where the |
2390 | // parent nsDocShell is inaccessible. |
2391 | already_AddRefed<nsDocShell> nsDocShell::GetInProcessParentDocshell() { |
2392 | nsCOMPtr<nsIDocShell> docshell = do_QueryInterface(GetAsSupports(mParent)); |
2393 | return docshell.forget().downcast<nsDocShell>(); |
2394 | } |
2395 | |
2396 | void nsDocShell::MaybeCreateInitialClientSource(nsIPrincipal* aPrincipal) { |
2397 | 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" , 2397); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mIsBeingDestroyed" ")"); do { *((volatile int*)__null) = 2397; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2398 | |
2399 | // If there is an existing document then there is no need to create |
2400 | // a client for a future initial about:blank document. |
2401 | if (mScriptGlobal && mScriptGlobal->GetCurrentInnerWindow() && |
2402 | mScriptGlobal->GetCurrentInnerWindow()->GetExtantDoc()) { |
2403 | 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" , 2404); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "mScriptGlobal->GetCurrentInnerWindow()->GetClientInfo().isSome()" ")"); do { *((volatile int*)__null) = 2404; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
2404 | 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" , 2404); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "mScriptGlobal->GetCurrentInnerWindow()->GetClientInfo().isSome()" ")"); do { *((volatile int*)__null) = 2404; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2405 | 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" , 2405); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "!mInitialClientSource" ")"); do { *((volatile int*)__null) = 2405; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2406 | return; |
2407 | } |
2408 | |
2409 | // Don't recreate the initial client source. We call this multiple times |
2410 | // when DoChannelLoad() is called before CreateAboutBlankDocumentViewer. |
2411 | if (mInitialClientSource) { |
2412 | return; |
2413 | } |
2414 | |
2415 | // Don't pre-allocate the client when we are sandboxed. The inherited |
2416 | // principal does not take sandboxing into account. |
2417 | // TODO: Refactor sandboxing principal code out so we can use it here. |
2418 | if (!aPrincipal && mBrowsingContext->GetSandboxFlags()) { |
2419 | return; |
2420 | } |
2421 | |
2422 | // We cannot get inherited foreign partitioned principal here. Instead, we |
2423 | // directly check which principal we want to inherit for the service worker. |
2424 | nsIPrincipal* principal = |
2425 | aPrincipal |
2426 | ? aPrincipal |
2427 | : GetInheritedPrincipal( |
2428 | false, StoragePrincipalHelper:: |
2429 | ShouldUsePartitionPrincipalForServiceWorker(this)); |
2430 | |
2431 | // Sometimes there is no principal available when we are called from |
2432 | // CreateAboutBlankDocumentViewer. For example, sometimes the principal |
2433 | // is only extracted from the load context after the document is created |
2434 | // in Document::ResetToURI(). Ideally we would do something similar |
2435 | // here, but for now lets just avoid the issue by not preallocating the |
2436 | // client. |
2437 | if (!principal) { |
2438 | return; |
2439 | } |
2440 | |
2441 | nsCOMPtr<nsPIDOMWindowOuter> win = GetWindow(); |
2442 | if (!win) { |
2443 | return; |
2444 | } |
2445 | |
2446 | mInitialClientSource = ClientManager::CreateSource( |
2447 | ClientType::Window, GetMainThreadSerialEventTarget(), principal); |
2448 | 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" , 2448); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "mInitialClientSource" ")"); do { *((volatile int*)__null) = 2448; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2449 | |
2450 | // Mark the initial client as execution ready, but owned by the docshell. |
2451 | // If the client is actually used this will cause ClientSource to force |
2452 | // the creation of the initial about:blank by calling |
2453 | // nsDocShell::GetDocument(). |
2454 | mInitialClientSource->DocShellExecutionReady(this); |
2455 | |
2456 | // Next, check to see if the parent is controlled. |
2457 | nsCOMPtr<nsIDocShell> parent = GetInProcessParentDocshell(); |
2458 | nsPIDOMWindowOuter* parentOuter = parent ? parent->GetWindow() : nullptr; |
2459 | nsPIDOMWindowInner* parentInner = |
2460 | parentOuter ? parentOuter->GetCurrentInnerWindow() : nullptr; |
2461 | if (!parentInner) { |
2462 | return; |
2463 | } |
2464 | |
2465 | nsCOMPtr<nsIURI> uri; |
2466 | 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" , 2466); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false" ") (" "NS_SUCCEEDED(NS_NewURI(getter_AddRefs(uri), \"about:blank\"_ns))" ")"); do { *((volatile int*)__null) = 2466; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); |
2467 | |
2468 | // We're done if there is no parent controller or if this docshell |
2469 | // is not permitted to control for some reason. |
2470 | Maybe<ServiceWorkerDescriptor> controller(parentInner->GetController()); |
2471 | if (controller.isNothing() || |
2472 | !ServiceWorkerAllowedToControlWindow(principal, uri)) { |
2473 | return; |
2474 | } |
2475 | |
2476 | mInitialClientSource->InheritController(controller.ref()); |
2477 | } |
2478 | |
2479 | Maybe<ClientInfo> nsDocShell::GetInitialClientInfo() const { |
2480 | if (mInitialClientSource) { |
2481 | Maybe<ClientInfo> result; |
2482 | result.emplace(mInitialClientSource->Info()); |
2483 | return result; |
2484 | } |
2485 | |
2486 | nsPIDOMWindowInner* innerWindow = |
2487 | mScriptGlobal ? mScriptGlobal->GetCurrentInnerWindow() : nullptr; |
2488 | Document* doc = innerWindow ? innerWindow->GetExtantDoc() : nullptr; |
2489 | |
2490 | if (!doc || !doc->IsInitialDocument()) { |
2491 | return Maybe<ClientInfo>(); |
2492 | } |
2493 | |
2494 | return innerWindow->GetClientInfo(); |
2495 | } |
2496 | |
2497 | nsresult nsDocShell::SetDocLoaderParent(nsDocLoader* aParent) { |
2498 | bool wasFrame = IsSubframe(); |
2499 | |
2500 | nsresult rv = nsDocLoader::SetDocLoaderParent(aParent); |
2501 | 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" , 2501); return rv; } } while (false); |
2502 | |
2503 | nsCOMPtr<nsISupportsPriority> priorityGroup = do_QueryInterface(mLoadGroup); |
2504 | if (wasFrame != IsSubframe() && priorityGroup) { |
2505 | priorityGroup->AdjustPriority(wasFrame ? -1 : 1); |
2506 | } |
2507 | |
2508 | // Curse ambiguous nsISupports inheritance! |
2509 | nsISupports* parent = GetAsSupports(aParent); |
2510 | |
2511 | // If parent is another docshell, we inherit all their flags for |
2512 | // allowing plugins, scripting etc. |
2513 | bool value; |
2514 | nsCOMPtr<nsIDocShell> parentAsDocShell(do_QueryInterface(parent)); |
2515 | |
2516 | if (parentAsDocShell) { |
2517 | if (mAllowMetaRedirects && |
2518 | NS_SUCCEEDED(parentAsDocShell->GetAllowMetaRedirects(&value))((bool)(__builtin_expect(!!(!NS_FAILED_impl(parentAsDocShell-> GetAllowMetaRedirects(&value))), 1)))) { |
2519 | SetAllowMetaRedirects(value); |
2520 | } |
2521 | if (mAllowSubframes && |
2522 | NS_SUCCEEDED(parentAsDocShell->GetAllowSubframes(&value))((bool)(__builtin_expect(!!(!NS_FAILED_impl(parentAsDocShell-> GetAllowSubframes(&value))), 1)))) { |
2523 | SetAllowSubframes(value); |
2524 | } |
2525 | if (mAllowImages && |
2526 | NS_SUCCEEDED(parentAsDocShell->GetAllowImages(&value))((bool)(__builtin_expect(!!(!NS_FAILED_impl(parentAsDocShell-> GetAllowImages(&value))), 1)))) { |
2527 | SetAllowImages(value); |
2528 | } |
2529 | SetAllowMedia(parentAsDocShell->GetAllowMedia() && mAllowMedia); |
2530 | if (mAllowWindowControl && |
2531 | NS_SUCCEEDED(parentAsDocShell->GetAllowWindowControl(&value))((bool)(__builtin_expect(!!(!NS_FAILED_impl(parentAsDocShell-> GetAllowWindowControl(&value))), 1)))) { |
2532 | SetAllowWindowControl(value); |
2533 | } |
2534 | if (NS_FAILED(parentAsDocShell->GetAllowDNSPrefetch(&value))((bool)(__builtin_expect(!!(NS_FAILED_impl(parentAsDocShell-> GetAllowDNSPrefetch(&value))), 0)))) { |
2535 | value = false; |
2536 | } |
2537 | SetAllowDNSPrefetch(mAllowDNSPrefetch && value); |
2538 | } |
2539 | |
2540 | nsCOMPtr<nsIURIContentListener> parentURIListener(do_GetInterface(parent)); |
2541 | if (parentURIListener) { |
2542 | mContentListener->SetParentContentListener(parentURIListener); |
2543 | } |
2544 | |
2545 | return NS_OK; |
2546 | } |
2547 | |
2548 | void nsDocShell::MaybeRestoreWindowName() { |
2549 | if (!StaticPrefs::privacy_window_name_update_enabled()) { |
2550 | return; |
2551 | } |
2552 | |
2553 | // We only restore window.name for the top-level content. |
2554 | if (!mBrowsingContext->IsTopContent()) { |
2555 | return; |
2556 | } |
2557 | |
2558 | nsAutoString name; |
2559 | |
2560 | // Following implements https://html.spec.whatwg.org/#history-traversal: |
2561 | // Step 4.4. Check if the loading entry has a name. |
2562 | |
2563 | if (mLSHE) { |
2564 | mLSHE->GetName(name); |
2565 | } |
2566 | |
2567 | if (mLoadingEntry) { |
2568 | name = mLoadingEntry->mInfo.GetName(); |
2569 | } |
2570 | |
2571 | if (name.IsEmpty()) { |
2572 | return; |
2573 | } |
2574 | |
2575 | // Step 4.4.1. Set the name to the browsing context. |
2576 | Unused << mBrowsingContext->SetName(name); |
2577 | |
2578 | // Step 4.4.2. Clear the name of all entries that are contiguous and |
2579 | // same-origin with the loading entry. |
2580 | if (mLSHE) { |
2581 | nsSHistory::WalkContiguousEntries( |
2582 | mLSHE, [](nsISHEntry* aEntry) { aEntry->SetName(EmptyString()); }); |
2583 | } |
2584 | |
2585 | if (mLoadingEntry) { |
2586 | // Clear the name of the session entry in the child side. For parent side, |
2587 | // the clearing will be done when we commit the history to the parent. |
2588 | mLoadingEntry->mInfo.SetName(EmptyString()); |
2589 | } |
2590 | } |
2591 | |
2592 | void nsDocShell::StoreWindowNameToSHEntries() { |
2593 | 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" , 2593); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mBrowsingContext->IsTopContent()" ")"); do { *((volatile int*)__null) = 2593; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2594 | |
2595 | nsAutoString name; |
2596 | mBrowsingContext->GetName(name); |
2597 | |
2598 | if (mOSHE) { |
2599 | nsSHistory::WalkContiguousEntries( |
2600 | mOSHE, [&](nsISHEntry* aEntry) { aEntry->SetName(name); }); |
2601 | } |
2602 | |
2603 | if (mozilla::SessionHistoryInParent()) { |
2604 | if (XRE_IsParentProcess()) { |
2605 | SessionHistoryEntry* entry = |
2606 | mBrowsingContext->Canonical()->GetActiveSessionHistoryEntry(); |
2607 | if (entry) { |
2608 | nsSHistory::WalkContiguousEntries( |
2609 | entry, [&](nsISHEntry* aEntry) { aEntry->SetName(name); }); |
2610 | } |
2611 | } else { |
2612 | // Ask parent process to store the name in entries. |
2613 | mozilla::Unused |
2614 | << ContentChild::GetSingleton() |
2615 | ->SendSessionHistoryEntryStoreWindowNameInContiguousEntries( |
2616 | mBrowsingContext, name); |
2617 | } |
2618 | } |
2619 | } |
2620 | |
2621 | NS_IMETHODIMPnsresult |
2622 | nsDocShell::GetInProcessSameTypeParent(nsIDocShellTreeItem** aParent) { |
2623 | if (BrowsingContext* parentBC = mBrowsingContext->GetParent()) { |
2624 | *aParent = do_AddRef(parentBC->GetDocShell()).take(); |
2625 | } |
2626 | return NS_OK; |
2627 | } |
2628 | |
2629 | NS_IMETHODIMPnsresult |
2630 | nsDocShell::GetInProcessRootTreeItem(nsIDocShellTreeItem** aRootTreeItem) { |
2631 | 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" , 2631); return NS_ERROR_INVALID_POINTER; } } while (false); |
2632 | |
2633 | RefPtr<nsDocShell> root = this; |
2634 | RefPtr<nsDocShell> parent = root->GetInProcessParentDocshell(); |
2635 | while (parent) { |
2636 | root = parent; |
2637 | parent = root->GetInProcessParentDocshell(); |
2638 | } |
2639 | |
2640 | root.forget(aRootTreeItem); |
2641 | return NS_OK; |
2642 | } |
2643 | |
2644 | NS_IMETHODIMPnsresult |
2645 | nsDocShell::GetInProcessSameTypeRootTreeItem( |
2646 | nsIDocShellTreeItem** aRootTreeItem) { |
2647 | 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" , 2647); return NS_ERROR_INVALID_POINTER; } } while (false); |
2648 | *aRootTreeItem = static_cast<nsIDocShellTreeItem*>(this); |
2649 | |
2650 | nsCOMPtr<nsIDocShellTreeItem> parent; |
2651 | 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" , 2652); return NS_ERROR_FAILURE; } } while (false) |
2652 | 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" , 2652); return NS_ERROR_FAILURE; } } while (false); |
2653 | while (parent) { |
2654 | *aRootTreeItem = parent; |
2655 | 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" , 2657); return NS_ERROR_FAILURE; } } while (false) |
2656 | (*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" , 2657); return NS_ERROR_FAILURE; } } while (false) |
2657 | 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" , 2657); return NS_ERROR_FAILURE; } } while (false); |
2658 | } |
2659 | NS_ADDREF(*aRootTreeItem)(*aRootTreeItem)->AddRef(); |
2660 | return NS_OK; |
2661 | } |
2662 | |
2663 | NS_IMETHODIMPnsresult |
2664 | nsDocShell::GetTreeOwner(nsIDocShellTreeOwner** aTreeOwner) { |
2665 | 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" , 2665); return NS_ERROR_INVALID_POINTER; } } while (false); |
2666 | |
2667 | *aTreeOwner = mTreeOwner; |
2668 | NS_IF_ADDREF(*aTreeOwner)ns_if_addref(*aTreeOwner); |
2669 | return NS_OK; |
2670 | } |
2671 | |
2672 | NS_IMETHODIMPnsresult |
2673 | nsDocShell::SetTreeOwner(nsIDocShellTreeOwner* aTreeOwner) { |
2674 | if (mIsBeingDestroyed && aTreeOwner) { |
2675 | return NS_ERROR_FAILURE; |
2676 | } |
2677 | |
2678 | // Don't automatically set the progress based on the tree owner for frames |
2679 | if (!IsSubframe()) { |
2680 | nsCOMPtr<nsIWebProgress> webProgress = |
2681 | do_QueryInterface(GetAsSupports(this)); |
2682 | |
2683 | if (webProgress) { |
2684 | nsCOMPtr<nsIWebProgressListener> oldListener = |
2685 | do_QueryInterface(mTreeOwner); |
2686 | nsCOMPtr<nsIWebProgressListener> newListener = |
2687 | do_QueryInterface(aTreeOwner); |
2688 | |
2689 | if (oldListener) { |
2690 | webProgress->RemoveProgressListener(oldListener); |
2691 | } |
2692 | |
2693 | if (newListener) { |
2694 | webProgress->AddProgressListener(newListener, |
2695 | nsIWebProgress::NOTIFY_ALL); |
2696 | } |
2697 | } |
2698 | } |
2699 | |
2700 | mTreeOwner = aTreeOwner; // Weak reference per API |
2701 | |
2702 | for (auto* childDocLoader : mChildList.ForwardRange()) { |
2703 | nsCOMPtr<nsIDocShellTreeItem> child = do_QueryObject(childDocLoader); |
2704 | 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" , 2704); return NS_ERROR_FAILURE; } } while (false); |
2705 | |
2706 | if (child->ItemType() == mItemType) { |
2707 | child->SetTreeOwner(aTreeOwner); |
2708 | } |
2709 | } |
2710 | |
2711 | // If we're in the content process and have had a TreeOwner set on us, extract |
2712 | // our BrowserChild actor. If we've already had our BrowserChild set, assert |
2713 | // that it hasn't changed. |
2714 | if (mTreeOwner && XRE_IsContentProcess()) { |
2715 | nsCOMPtr<nsIBrowserChild> newBrowserChild = do_GetInterface(mTreeOwner); |
2716 | 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" , 2717); AnnotateMozCrashReason("MOZ_ASSERT" "(" "newBrowserChild" ") (" "No BrowserChild actor for tree owner in Content!" ")" ); do { *((volatile int*)__null) = 2717; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
2717 | "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" , 2717); AnnotateMozCrashReason("MOZ_ASSERT" "(" "newBrowserChild" ") (" "No BrowserChild actor for tree owner in Content!" ")" ); do { *((volatile int*)__null) = 2717; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2718 | |
2719 | if (mBrowserChild) { |
2720 | nsCOMPtr<nsIBrowserChild> oldBrowserChild = |
2721 | do_QueryReferent(mBrowserChild); |
2722 | 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" , 2724); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "oldBrowserChild == newBrowserChild" ") (" "Cannot change BrowserChild during nsDocShell lifetime!" ")"); do { *((volatile int*)__null) = 2724; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
2723 | 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" , 2724); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "oldBrowserChild == newBrowserChild" ") (" "Cannot change BrowserChild during nsDocShell lifetime!" ")"); do { *((volatile int*)__null) = 2724; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
2724 | "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" , 2724); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "oldBrowserChild == newBrowserChild" ") (" "Cannot change BrowserChild during nsDocShell lifetime!" ")"); do { *((volatile int*)__null) = 2724; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2725 | } else { |
2726 | mBrowserChild = do_GetWeakReference(newBrowserChild); |
2727 | } |
2728 | } |
2729 | |
2730 | return NS_OK; |
2731 | } |
2732 | |
2733 | NS_IMETHODIMPnsresult |
2734 | nsDocShell::GetHistoryID(nsID& aID) { |
2735 | aID = mBrowsingContext->GetHistoryID(); |
2736 | return NS_OK; |
2737 | } |
2738 | |
2739 | const nsID& nsDocShell::HistoryID() { return mBrowsingContext->GetHistoryID(); } |
2740 | |
2741 | NS_IMETHODIMPnsresult |
2742 | nsDocShell::GetIsInUnload(bool* aIsInUnload) { |
2743 | *aIsInUnload = mFiredUnloadEvent; |
2744 | return NS_OK; |
2745 | } |
2746 | |
2747 | NS_IMETHODIMPnsresult |
2748 | nsDocShell::GetInProcessChildCount(int32_t* aChildCount) { |
2749 | 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" , 2749); return NS_ERROR_INVALID_POINTER; } } while (false); |
2750 | *aChildCount = mChildList.Length(); |
2751 | return NS_OK; |
2752 | } |
2753 | |
2754 | NS_IMETHODIMPnsresult |
2755 | nsDocShell::AddChild(nsIDocShellTreeItem* aChild) { |
2756 | 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" , 2756); return NS_ERROR_INVALID_POINTER; } } while (false); |
2757 | |
2758 | RefPtr<nsDocLoader> childAsDocLoader = GetAsDocLoader(aChild); |
2759 | 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" , 2759); return NS_ERROR_UNEXPECTED; } } while (false); |
2760 | |
2761 | // Make sure we're not creating a loop in the docshell tree |
2762 | nsDocLoader* ancestor = this; |
2763 | do { |
2764 | if (childAsDocLoader == ancestor) { |
2765 | return NS_ERROR_ILLEGAL_VALUE; |
2766 | } |
2767 | ancestor = ancestor->GetParent(); |
2768 | } while (ancestor); |
2769 | |
2770 | // Make sure to remove the child from its current parent. |
2771 | nsDocLoader* childsParent = childAsDocLoader->GetParent(); |
2772 | if (childsParent) { |
2773 | nsresult rv = childsParent->RemoveChildLoader(childAsDocLoader); |
2774 | 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" , 2774); return rv; } } while (false); |
2775 | } |
2776 | |
2777 | // Make sure to clear the treeowner in case this child is a different type |
2778 | // from us. |
2779 | aChild->SetTreeOwner(nullptr); |
2780 | |
2781 | nsresult res = AddChildLoader(childAsDocLoader); |
2782 | 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" , 2782); return res; } } while (false); |
2783 | 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" , 2784); MOZ_PretendNoReturn(); } } while (0) |
2784 | "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" , 2784); MOZ_PretendNoReturn(); } } while (0); |
2785 | |
2786 | /* Set the child's global history if the parent has one */ |
2787 | if (mBrowsingContext->GetUseGlobalHistory()) { |
2788 | // childDocShell->SetUseGlobalHistory(true); |
2789 | // this should be set through BC inherit |
2790 | 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" , 2790); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aChild->GetBrowsingContext()->GetUseGlobalHistory()" ")"); do { *((volatile int*)__null) = 2790; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2791 | } |
2792 | |
2793 | if (aChild->ItemType() != mItemType) { |
2794 | return NS_OK; |
2795 | } |
2796 | |
2797 | aChild->SetTreeOwner(mTreeOwner); |
2798 | |
2799 | nsCOMPtr<nsIDocShell> childAsDocShell(do_QueryInterface(aChild)); |
2800 | if (!childAsDocShell) { |
2801 | return NS_OK; |
2802 | } |
2803 | |
2804 | // charset, style-disabling, and zoom will be inherited in SetupNewViewer() |
2805 | |
2806 | // Now take this document's charset and set the child's parentCharset field |
2807 | // to it. We'll later use that field, in the loading process, for the |
2808 | // charset choosing algorithm. |
2809 | // If we fail, at any point, we just return NS_OK. |
2810 | // This code has some performance impact. But this will be reduced when |
2811 | // the current charset will finally be stored as an Atom, avoiding the |
2812 | // alias resolution extra look-up. |
2813 | |
2814 | // we are NOT going to propagate the charset is this Chrome's docshell |
2815 | if (mItemType == nsIDocShellTreeItem::typeChrome) { |
2816 | return NS_OK; |
2817 | } |
2818 | |
2819 | // get the parent's current charset |
2820 | if (!mDocumentViewer) { |
2821 | return NS_OK; |
2822 | } |
2823 | Document* doc = mDocumentViewer->GetDocument(); |
2824 | if (!doc) { |
2825 | return NS_OK; |
2826 | } |
2827 | |
2828 | const Encoding* parentCS = doc->GetDocumentCharacterSet(); |
2829 | int32_t charsetSource = doc->GetDocumentCharacterSetSource(); |
2830 | // set the child's parentCharset |
2831 | childAsDocShell->SetParentCharset(parentCS, charsetSource, |
2832 | doc->NodePrincipal()); |
2833 | |
2834 | // printf("### 1 >>> Adding child. Parent CS = %s. ItemType = %d.\n", |
2835 | // NS_LossyConvertUTF16toASCII(parentCS).get(), mItemType); |
2836 | |
2837 | return NS_OK; |
2838 | } |
2839 | |
2840 | NS_IMETHODIMPnsresult |
2841 | nsDocShell::RemoveChild(nsIDocShellTreeItem* aChild) { |
2842 | 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" , 2842); return NS_ERROR_INVALID_POINTER; } } while (false); |
2843 | |
2844 | RefPtr<nsDocLoader> childAsDocLoader = GetAsDocLoader(aChild); |
2845 | 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" , 2845); return NS_ERROR_UNEXPECTED; } } while (false); |
2846 | |
2847 | nsresult rv = RemoveChildLoader(childAsDocLoader); |
2848 | 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" , 2848); return rv; } } while (false); |
2849 | |
2850 | aChild->SetTreeOwner(nullptr); |
2851 | |
2852 | return nsDocLoader::AddDocLoaderAsChildOfRoot(childAsDocLoader); |
2853 | } |
2854 | |
2855 | NS_IMETHODIMPnsresult |
2856 | nsDocShell::GetInProcessChildAt(int32_t aIndex, nsIDocShellTreeItem** aChild) { |
2857 | 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" , 2857); return NS_ERROR_INVALID_POINTER; } } while (false); |
2858 | |
2859 | RefPtr<nsDocShell> child = GetInProcessChildAt(aIndex); |
2860 | 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" , 2860); return NS_ERROR_UNEXPECTED; } } while (false); |
2861 | |
2862 | child.forget(aChild); |
2863 | |
2864 | return NS_OK; |
2865 | } |
2866 | |
2867 | nsDocShell* nsDocShell::GetInProcessChildAt(int32_t aIndex) { |
2868 | #ifdef DEBUG1 |
2869 | if (aIndex < 0) { |
2870 | 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" , 2870); |
2871 | } else if (static_cast<uint32_t>(aIndex) >= mChildList.Length()) { |
2872 | 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" , 2872); |
2873 | } |
2874 | #endif |
2875 | |
2876 | nsIDocumentLoader* child = ChildAt(aIndex); |
2877 | |
2878 | // child may be nullptr here. |
2879 | return static_cast<nsDocShell*>(child); |
2880 | } |
2881 | |
2882 | nsresult nsDocShell::AddChildSHEntry(nsISHEntry* aCloneRef, |
2883 | nsISHEntry* aNewEntry, |
2884 | int32_t aChildOffset, uint32_t aLoadType, |
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 | nsresult rv = NS_OK; |
2888 | |
2889 | if (mLSHE && aLoadType != LOAD_PUSHSTATE) { |
2890 | /* You get here if you are currently building a |
2891 | * hierarchy ie.,you just visited a frameset page |
2892 | */ |
2893 | if (NS_FAILED(mLSHE->ReplaceChild(aNewEntry))((bool)(__builtin_expect(!!(NS_FAILED_impl(mLSHE->ReplaceChild (aNewEntry))), 0)))) { |
2894 | rv = mLSHE->AddChild(aNewEntry, aChildOffset); |
2895 | } |
2896 | } else if (!aCloneRef) { |
2897 | /* This is an initial load in some subframe. Just append it if we can */ |
2898 | if (mOSHE) { |
2899 | rv = mOSHE->AddChild(aNewEntry, aChildOffset, UseRemoteSubframes()); |
2900 | } |
2901 | } else { |
2902 | RefPtr<ChildSHistory> shistory = GetRootSessionHistory(); |
2903 | if (shistory) { |
2904 | rv = shistory->LegacySHistory()->AddChildSHEntryHelper( |
2905 | aCloneRef, aNewEntry, mBrowsingContext->Top(), aCloneChildren); |
2906 | } |
2907 | } |
2908 | return rv; |
2909 | } |
2910 | |
2911 | nsresult nsDocShell::AddChildSHEntryToParent(nsISHEntry* aNewEntry, |
2912 | int32_t aChildOffset, |
2913 | bool aCloneChildren) { |
2914 | 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" , 2914); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()" ")"); do { *((volatile int*)__null) = 2914; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2915 | /* You will get here when you are in a subframe and |
2916 | * a new url has been loaded on you. |
2917 | * The mOSHE in this subframe will be the previous url's |
2918 | * mOSHE. This mOSHE will be used as the identification |
2919 | * for this subframe in the CloneAndReplace function. |
2920 | */ |
2921 | |
2922 | // In this case, we will end up calling AddEntry, which increases the |
2923 | // current index by 1 |
2924 | RefPtr<ChildSHistory> rootSH = GetRootSessionHistory(); |
2925 | if (rootSH) { |
2926 | mPreviousEntryIndex = rootSH->Index(); |
2927 | } |
2928 | |
2929 | nsresult rv; |
2930 | // XXX(farre): this is not Fission safe, expect errors. This never |
2931 | // get's executed once session history in the parent is enabled. |
2932 | nsCOMPtr<nsIDocShell> parent = do_QueryInterface(GetAsSupports(mParent), &rv); |
2933 | 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" , 2936); } } while (false) |
2934 | 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" , 2936); } } while (false) |
2935 | "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" , 2936); } } while (false) |
2936 | "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" , 2936); } } while (false); |
2937 | if (parent) { |
2938 | rv = nsDocShell::Cast(parent)->AddChildSHEntry( |
2939 | mOSHE, aNewEntry, aChildOffset, mLoadType, aCloneChildren); |
2940 | } |
2941 | |
2942 | if (rootSH) { |
2943 | mLoadedEntryIndex = rootSH->Index(); |
2944 | |
2945 | if (MOZ_UNLIKELY(MOZ_LOG_TEST(gPageCacheLog, LogLevel::Verbose))(__builtin_expect(!!((__builtin_expect(!!(mozilla::detail::log_test (gPageCacheLog, LogLevel::Verbose)), 0))), 0))) { |
2946 | 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) |
2947 | ("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) |
2948 | 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); |
2949 | } |
2950 | } |
2951 | |
2952 | return rv; |
2953 | } |
2954 | |
2955 | NS_IMETHODIMPnsresult |
2956 | nsDocShell::GetCurrentSHEntry(nsISHEntry** aEntry, bool* aOSHE) { |
2957 | *aOSHE = false; |
2958 | *aEntry = nullptr; |
2959 | if (mLSHE) { |
2960 | NS_ADDREF(*aEntry = mLSHE)(*aEntry = mLSHE)->AddRef(); |
2961 | } else if (mOSHE) { |
2962 | NS_ADDREF(*aEntry = mOSHE)(*aEntry = mOSHE)->AddRef(); |
2963 | *aOSHE = true; |
2964 | } |
2965 | return NS_OK; |
2966 | } |
2967 | |
2968 | NS_IMETHODIMPnsresult nsDocShell::SynchronizeLayoutHistoryState() { |
2969 | if (mActiveEntry && mActiveEntry->GetLayoutHistoryState() && |
2970 | mBrowsingContext) { |
2971 | if (XRE_IsContentProcess()) { |
2972 | dom::ContentChild* contentChild = dom::ContentChild::GetSingleton(); |
2973 | if (contentChild) { |
2974 | contentChild->SendSynchronizeLayoutHistoryState( |
2975 | mBrowsingContext, mActiveEntry->GetLayoutHistoryState()); |
2976 | } |
2977 | } else { |
2978 | SessionHistoryEntry* entry = |
2979 | mBrowsingContext->Canonical()->GetActiveSessionHistoryEntry(); |
2980 | if (entry) { |
2981 | entry->SetLayoutHistoryState(mActiveEntry->GetLayoutHistoryState()); |
2982 | } |
2983 | } |
2984 | if (mLoadingEntry && |
2985 | mLoadingEntry->mInfo.SharedId() == mActiveEntry->SharedId()) { |
2986 | mLoadingEntry->mInfo.SetLayoutHistoryState( |
2987 | mActiveEntry->GetLayoutHistoryState()); |
2988 | } |
2989 | } |
2990 | |
2991 | return NS_OK; |
2992 | } |
2993 | |
2994 | void nsDocShell::SetLoadGroupDefaultLoadFlags(nsLoadFlags aLoadFlags) { |
2995 | if (mLoadGroup) { |
2996 | mLoadGroup->SetDefaultLoadFlags(aLoadFlags); |
2997 | } else { |
2998 | 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" , 3000) |
2999 | "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" , 3000) |
3000 | "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" , 3000); |
3001 | } |
3002 | } |
3003 | |
3004 | nsIScriptGlobalObject* nsDocShell::GetScriptGlobalObject() { |
3005 | 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" , 3005); return nullptr; } } while (false); |
3006 | return mScriptGlobal; |
3007 | } |
3008 | |
3009 | Document* nsDocShell::GetDocument() { |
3010 | 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" , 3010); return nullptr; } } while (false); |
3011 | return mDocumentViewer->GetDocument(); |
3012 | } |
3013 | |
3014 | Document* nsDocShell::GetExtantDocument() { |
3015 | return mDocumentViewer ? mDocumentViewer->GetDocument() : nullptr; |
3016 | } |
3017 | |
3018 | nsPIDOMWindowOuter* nsDocShell::GetWindow() { |
3019 | if (NS_FAILED(EnsureScriptEnvironment())((bool)(__builtin_expect(!!(NS_FAILED_impl(EnsureScriptEnvironment ())), 0)))) { |
3020 | return nullptr; |
3021 | } |
3022 | return mScriptGlobal; |
3023 | } |
3024 | |
3025 | NS_IMETHODIMPnsresult |
3026 | nsDocShell::GetDomWindow(mozIDOMWindowProxy** aWindow) { |
3027 | 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" , 3027); return NS_ERROR_INVALID_POINTER; } } while (false); |
3028 | |
3029 | nsresult rv = EnsureScriptEnvironment(); |
3030 | 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" , 3030); return rv; } } while (false); |
3031 | |
3032 | RefPtr<nsGlobalWindowOuter> window = mScriptGlobal; |
3033 | window.forget(aWindow); |
3034 | return NS_OK; |
3035 | } |
3036 | |
3037 | NS_IMETHODIMPnsresult |
3038 | nsDocShell::GetMessageManager(ContentFrameMessageManager** aMessageManager) { |
3039 | RefPtr<ContentFrameMessageManager> mm; |
3040 | if (RefPtr<BrowserChild> browserChild = BrowserChild::GetFrom(this)) { |
3041 | mm = browserChild->GetMessageManager(); |
3042 | } else if (nsPIDOMWindowOuter* win = GetWindow()) { |
3043 | mm = win->GetMessageManager(); |
3044 | } |
3045 | mm.forget(aMessageManager); |
3046 | return NS_OK; |
3047 | } |
3048 | |
3049 | NS_IMETHODIMPnsresult |
3050 | nsDocShell::GetIsNavigating(bool* aOut) { |
3051 | *aOut = mIsNavigating; |
3052 | return NS_OK; |
3053 | } |
3054 | |
3055 | void nsDocShell::ClearFrameHistory(nsISHEntry* aEntry) { |
3056 | 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" , 3056); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()" ")"); do { *((volatile int*)__null) = 3056; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3057 | RefPtr<ChildSHistory> rootSH = GetRootSessionHistory(); |
3058 | if (!rootSH || !aEntry) { |
3059 | return; |
3060 | } |
3061 | |
3062 | rootSH->LegacySHistory()->RemoveFrameEntries(aEntry); |
3063 | } |
3064 | |
3065 | //------------------------------------- |
3066 | //-- Helper Method for Print discovery |
3067 | //------------------------------------- |
3068 | bool nsDocShell::NavigationBlockedByPrinting(bool aDisplayErrorDialog) { |
3069 | if (!mBrowsingContext->Top()->GetIsPrinting()) { |
3070 | return false; |
3071 | } |
3072 | if (aDisplayErrorDialog) { |
3073 | DisplayLoadError(NS_ERROR_DOCUMENT_IS_PRINTMODE, nullptr, nullptr, nullptr); |
3074 | } |
3075 | return true; |
3076 | } |
3077 | |
3078 | bool nsDocShell::IsNavigationAllowed(bool aDisplayPrintErrorDialog, |
3079 | bool aCheckIfUnloadFired) { |
3080 | bool isAllowed = !NavigationBlockedByPrinting(aDisplayPrintErrorDialog) && |
3081 | (!aCheckIfUnloadFired || !mFiredUnloadEvent); |
3082 | if (!isAllowed) { |
3083 | return false; |
3084 | } |
3085 | if (!mDocumentViewer) { |
3086 | return true; |
3087 | } |
3088 | bool firingBeforeUnload; |
3089 | mDocumentViewer->GetBeforeUnloadFiring(&firingBeforeUnload); |
3090 | return !firingBeforeUnload; |
3091 | } |
3092 | |
3093 | //***************************************************************************** |
3094 | // nsDocShell::nsIWebNavigation |
3095 | //***************************************************************************** |
3096 | |
3097 | NS_IMETHODIMPnsresult |
3098 | nsDocShell::GetCanGoBack(bool* aCanGoBack) { |
3099 | *aCanGoBack = false; |
3100 | if (!IsNavigationAllowed(false)) { |
3101 | return NS_OK; // JS may not handle returning of an error code |
3102 | } |
3103 | RefPtr<ChildSHistory> rootSH = GetRootSessionHistory(); |
3104 | if (rootSH) { |
3105 | *aCanGoBack = rootSH->CanGo(-1); |
3106 | 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) |
3107 | ("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); |
3108 | |
3109 | return NS_OK; |
3110 | } |
3111 | return NS_ERROR_FAILURE; |
3112 | } |
3113 | |
3114 | NS_IMETHODIMPnsresult |
3115 | nsDocShell::GetCanGoForward(bool* aCanGoForward) { |
3116 | *aCanGoForward = false; |
3117 | if (!IsNavigationAllowed(false)) { |
3118 | return NS_OK; // JS may not handle returning of an error code |
3119 | } |
3120 | RefPtr<ChildSHistory> rootSH = GetRootSessionHistory(); |
3121 | if (rootSH) { |
3122 | *aCanGoForward = rootSH->CanGo(1); |
3123 | 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) |
3124 | ("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); |
3125 | return NS_OK; |
3126 | } |
3127 | return NS_ERROR_FAILURE; |
3128 | } |
3129 | |
3130 | NS_IMETHODIMPnsresult |
3131 | nsDocShell::GoBack(bool aRequireUserInteraction, bool aUserActivation) { |
3132 | if (!IsNavigationAllowed()) { |
3133 | return NS_OK; // JS may not handle returning of an error code |
3134 | } |
3135 | |
3136 | auto cleanupIsNavigating = MakeScopeExit([&]() { mIsNavigating = false; }); |
3137 | mIsNavigating = true; |
3138 | |
3139 | RefPtr<ChildSHistory> rootSH = GetRootSessionHistory(); |
3140 | 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" , 3140); return NS_ERROR_FAILURE; } } while (false); |
3141 | ErrorResult rv; |
3142 | rootSH->Go(-1, aRequireUserInteraction, aUserActivation, rv); |
3143 | return rv.StealNSResult(); |
3144 | } |
3145 | |
3146 | NS_IMETHODIMPnsresult |
3147 | nsDocShell::GoForward(bool aRequireUserInteraction, bool aUserActivation) { |
3148 | if (!IsNavigationAllowed()) { |
3149 | return NS_OK; // JS may not handle returning of an error code |
3150 | } |
3151 | |
3152 | auto cleanupIsNavigating = MakeScopeExit([&]() { mIsNavigating = false; }); |
3153 | mIsNavigating = true; |
3154 | |
3155 | RefPtr<ChildSHistory> rootSH = GetRootSessionHistory(); |
3156 | 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" , 3156); return NS_ERROR_FAILURE; } } while (false); |
3157 | ErrorResult rv; |
3158 | rootSH->Go(1, aRequireUserInteraction, aUserActivation, rv); |
3159 | return rv.StealNSResult(); |
3160 | } |
3161 | |
3162 | // XXX(nika): We may want to stop exposing this API in the child process? Going |
3163 | // to a specific index from multiple different processes could definitely race. |
3164 | NS_IMETHODIMPnsresult |
3165 | nsDocShell::GotoIndex(int32_t aIndex, bool aUserActivation) { |
3166 | if (!IsNavigationAllowed()) { |
3167 | return NS_OK; // JS may not handle returning of an error code |
3168 | } |
3169 | |
3170 | auto cleanupIsNavigating = MakeScopeExit([&]() { mIsNavigating = false; }); |
3171 | mIsNavigating = true; |
3172 | |
3173 | RefPtr<ChildSHistory> rootSH = GetRootSessionHistory(); |
3174 | 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" , 3174); return NS_ERROR_FAILURE; } } while (false); |
3175 | |
3176 | ErrorResult rv; |
3177 | rootSH->GotoIndex(aIndex, aIndex - rootSH->Index(), false, aUserActivation, |
3178 | rv); |
3179 | return rv.StealNSResult(); |
3180 | } |
3181 | |
3182 | nsresult nsDocShell::LoadURI(nsIURI* aURI, |
3183 | const LoadURIOptions& aLoadURIOptions) { |
3184 | if (!IsNavigationAllowed()) { |
3185 | return NS_OK; // JS may not handle returning of an error code |
3186 | } |
3187 | RefPtr<nsDocShellLoadState> loadState; |
3188 | nsresult rv = nsDocShellLoadState::CreateFromLoadURIOptions( |
3189 | mBrowsingContext, aURI, aLoadURIOptions, getter_AddRefs(loadState)); |
3190 | 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" , 3190); AnnotateMozCrashReason("MOZ_ASSERT" "(" "rv != NS_ERROR_MALFORMED_URI" ")"); do { *((volatile int*)__null) = 3190; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3191 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || !loadState) { |
3192 | return NS_ERROR_FAILURE; |
3193 | } |
3194 | |
3195 | return LoadURI(loadState, true); |
3196 | } |
3197 | |
3198 | NS_IMETHODIMPnsresult |
3199 | nsDocShell::LoadURIFromScript(nsIURI* aURI, |
3200 | JS::Handle<JS::Value> aLoadURIOptions, |
3201 | JSContext* aCx) { |
3202 | // generate dictionary for aLoadURIOptions and forward call |
3203 | LoadURIOptions loadURIOptions; |
3204 | if (!loadURIOptions.Init(aCx, aLoadURIOptions)) { |
3205 | return NS_ERROR_INVALID_ARG; |
3206 | } |
3207 | return LoadURI(aURI, loadURIOptions); |
3208 | } |
3209 | |
3210 | nsresult nsDocShell::FixupAndLoadURIString( |
3211 | const nsAString& aURIString, const LoadURIOptions& aLoadURIOptions) { |
3212 | if (!IsNavigationAllowed()) { |
3213 | return NS_OK; // JS may not handle returning of an error code |
3214 | } |
3215 | |
3216 | RefPtr<nsDocShellLoadState> loadState; |
3217 | nsresult rv = nsDocShellLoadState::CreateFromLoadURIOptions( |
3218 | mBrowsingContext, aURIString, aLoadURIOptions, getter_AddRefs(loadState)); |
3219 | |
3220 | uint32_t loadFlags = aLoadURIOptions.mLoadFlags; |
3221 | if (NS_ERROR_MALFORMED_URI == rv) { |
3222 | 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) |
3223 | ("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) |
3224 | "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) |
3225 | 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); |
3226 | |
3227 | // We need to store a session history entry. We don't have a valid URI, so |
3228 | // we use about:blank instead. |
3229 | nsCOMPtr<nsIURI> uri; |
3230 | 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" , 3230); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false" ") (" "NS_SUCCEEDED(NS_NewURI(getter_AddRefs(uri), \"about:blank\"_ns))" ")"); do { *((volatile int*)__null) = 3230; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); |
3231 | nsCOMPtr<nsIPrincipal> triggeringPrincipal; |
3232 | if (aLoadURIOptions.mTriggeringPrincipal) { |
3233 | triggeringPrincipal = aLoadURIOptions.mTriggeringPrincipal; |
3234 | } else { |
3235 | triggeringPrincipal = nsContentUtils::GetSystemPrincipal(); |
3236 | } |
3237 | if (mozilla::SessionHistoryInParent()) { |
3238 | mActiveEntry = MakeUnique<SessionHistoryInfo>( |
3239 | uri, triggeringPrincipal, nullptr, nullptr, nullptr, |
3240 | nsLiteralCString("text/html")); |
3241 | mBrowsingContext->SetActiveSessionHistoryEntry( |
3242 | Nothing(), mActiveEntry.get(), MAKE_LOAD_TYPE(LOAD_NORMAL, loadFlags)((LOAD_NORMAL) | ((loadFlags) << 16)), |
3243 | /* aUpdatedCacheKey = */ 0); |
3244 | } |
3245 | if (DisplayLoadError(rv, nullptr, PromiseFlatStringTPromiseFlatString<char16_t>(aURIString).get(), |
3246 | nullptr) && |
3247 | (loadFlags & LOAD_FLAGS_ERROR_LOAD_CHANGES_RV) != 0) { |
3248 | return NS_ERROR_LOAD_SHOWED_ERRORPAGE; |
3249 | } |
3250 | } |
3251 | |
3252 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || !loadState) { |
3253 | return NS_ERROR_FAILURE; |
3254 | } |
3255 | |
3256 | return LoadURI(loadState, true); |
3257 | } |
3258 | |
3259 | NS_IMETHODIMPnsresult |
3260 | nsDocShell::FixupAndLoadURIStringFromScript( |
3261 | const nsAString& aURIString, JS::Handle<JS::Value> aLoadURIOptions, |
3262 | JSContext* aCx) { |
3263 | // generate dictionary for aLoadURIOptions and forward call |
3264 | LoadURIOptions loadURIOptions; |
3265 | if (!loadURIOptions.Init(aCx, aLoadURIOptions)) { |
3266 | return NS_ERROR_INVALID_ARG; |
3267 | } |
3268 | return FixupAndLoadURIString(aURIString, loadURIOptions); |
3269 | } |
3270 | |
3271 | void nsDocShell::UnblockEmbedderLoadEventForFailure(bool aFireFrameErrorEvent) { |
3272 | // If we're not in a content frame, or are at a BrowsingContext tree boundary, |
3273 | // such as the content-chrome boundary, don't fire the error event. |
3274 | if (mBrowsingContext->IsTopContent() || mBrowsingContext->IsChrome()) { |
3275 | return; |
3276 | } |
3277 | |
3278 | // If embedder is same-process, then unblocking the load event is already |
3279 | // handled by nsDocLoader. Fire the error event on our embedder element if |
3280 | // requested. |
3281 | // |
3282 | // XXX: Bug 1440212 is looking into potentially changing this behaviour to act |
3283 | // more like the remote case when in-process. |
3284 | RefPtr<Element> element = mBrowsingContext->GetEmbedderElement(); |
3285 | if (element) { |
3286 | if (aFireFrameErrorEvent) { |
3287 | if (RefPtr<nsFrameLoaderOwner> flo = do_QueryObject(element)) { |
3288 | if (RefPtr<nsFrameLoader> fl = flo->GetFrameLoader()) { |
3289 | fl->FireErrorEvent(); |
3290 | } |
3291 | } |
3292 | } |
3293 | return; |
3294 | } |
3295 | |
3296 | // If we have a cross-process parent document, we must notify it that we no |
3297 | // longer block its load event. This is necessary for OOP sub-documents |
3298 | // because error documents do not result in a call to |
3299 | // SendMaybeFireEmbedderLoadEvents via any of the normal call paths. |
3300 | // (Obviously, we must do this before any of the returns below.) |
3301 | RefPtr<BrowserChild> browserChild = BrowserChild::GetFrom(this); |
3302 | if (browserChild && |
3303 | !mBrowsingContext->GetParentWindowContext()->IsInProcess()) { |
3304 | mozilla::Unused << browserChild->SendMaybeFireEmbedderLoadEvents( |
3305 | aFireFrameErrorEvent ? EmbedderElementEventType::ErrorEvent |
3306 | : EmbedderElementEventType::NoEvent); |
3307 | } |
3308 | } |
3309 | |
3310 | NS_IMETHODIMPnsresult |
3311 | nsDocShell::DisplayLoadError(nsresult aError, nsIURI* aURI, |
3312 | const char16_t* aURL, nsIChannel* aFailedChannel, |
3313 | bool* aDisplayedErrorPage) { |
3314 | 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 ) |
3315 | ("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 ) |
3316 | 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 ); |
3317 | |
3318 | *aDisplayedErrorPage = false; |
3319 | // Get prompt and string bundle services |
3320 | nsCOMPtr<nsIPrompt> prompter; |
3321 | nsCOMPtr<nsIStringBundle> stringBundle; |
3322 | GetPromptAndStringBundle(getter_AddRefs(prompter), |
3323 | getter_AddRefs(stringBundle)); |
3324 | |
3325 | 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" , 3325); return NS_ERROR_FAILURE; } } while (false); |
3326 | 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" , 3326); return NS_ERROR_FAILURE; } } while (false); |
3327 | |
3328 | const char* error = nullptr; |
3329 | // The key used to select the appropriate error message from the properties |
3330 | // file. |
3331 | const char* errorDescriptionID = nullptr; |
3332 | AutoTArray<nsString, 3> formatStrs; |
3333 | bool addHostPort = false; |
3334 | bool isBadStsCertError = false; |
3335 | nsresult rv = NS_OK; |
3336 | nsAutoString messageStr; |
3337 | nsAutoCString cssClass; |
3338 | nsAutoCString errorPage; |
3339 | |
3340 | errorPage.AssignLiteral("neterror"); |
3341 | |
3342 | // Turn the error code into a human readable error message. |
3343 | if (NS_ERROR_UNKNOWN_PROTOCOL == aError) { |
3344 | 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" , 3344); return NS_ERROR_INVALID_POINTER; } } while (false); |
3345 | |
3346 | // Extract the schemes into a comma delimited list. |
3347 | nsAutoCString scheme; |
3348 | aURI->GetScheme(scheme); |
3349 | CopyASCIItoUTF16(scheme, *formatStrs.AppendElement()); |
3350 | nsCOMPtr<nsINestedURI> nestedURI = do_QueryInterface(aURI); |
3351 | while (nestedURI) { |
3352 | nsCOMPtr<nsIURI> tempURI; |
3353 | nsresult rv2; |
3354 | rv2 = nestedURI->GetInnerURI(getter_AddRefs(tempURI)); |
3355 | if (NS_SUCCEEDED(rv2)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv2)), 1))) && tempURI) { |
3356 | tempURI->GetScheme(scheme); |
3357 | formatStrs[0].AppendLiteral(", "); |
3358 | AppendASCIItoUTF16(scheme, formatStrs[0]); |
3359 | } |
3360 | nestedURI = do_QueryInterface(tempURI); |
3361 | } |
3362 | error = "unknownProtocolFound"; |
3363 | } else if (NS_ERROR_FILE_NOT_FOUND == aError) { |
3364 | 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" , 3364); return NS_ERROR_INVALID_POINTER; } } while (false); |
3365 | error = "fileNotFound"; |
3366 | } else if (NS_ERROR_FILE_ACCESS_DENIED == aError) { |
3367 | 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" , 3367); return NS_ERROR_INVALID_POINTER; } } while (false); |
3368 | error = "fileAccessDenied"; |
3369 | } else if (NS_ERROR_UNKNOWN_HOST == aError) { |
3370 | 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" , 3370); return NS_ERROR_INVALID_POINTER; } } while (false); |
3371 | // Get the host |
3372 | nsAutoCString host; |
3373 | nsCOMPtr<nsIURI> innermostURI = NS_GetInnermostURI(aURI); |
3374 | innermostURI->GetHost(host); |
3375 | CopyUTF8toUTF16(host, *formatStrs.AppendElement()); |
3376 | errorDescriptionID = "dnsNotFound2"; |
3377 | error = "dnsNotFound"; |
3378 | } else if (NS_ERROR_CONNECTION_REFUSED == aError || |
3379 | NS_ERROR_PROXY_BAD_GATEWAY == aError) { |
3380 | 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" , 3380); return NS_ERROR_INVALID_POINTER; } } while (false); |
3381 | addHostPort = true; |
3382 | error = "connectionFailure"; |
3383 | } else if (NS_ERROR_NET_INTERRUPT == aError) { |
3384 | 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" , 3384); return NS_ERROR_INVALID_POINTER; } } while (false); |
3385 | addHostPort = true; |
3386 | error = "netInterrupt"; |
3387 | } else if (NS_ERROR_NET_TIMEOUT == aError || |
3388 | NS_ERROR_PROXY_GATEWAY_TIMEOUT == aError || |
3389 | NS_ERROR_NET_TIMEOUT_EXTERNAL == aError) { |
3390 | 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" , 3390); return NS_ERROR_INVALID_POINTER; } } while (false); |
3391 | // Get the host |
3392 | nsAutoCString host; |
3393 | aURI->GetHost(host); |
3394 | CopyUTF8toUTF16(host, *formatStrs.AppendElement()); |
3395 | error = "netTimeout"; |
3396 | } else if (NS_ERROR_CSP_FRAME_ANCESTOR_VIOLATION == aError || |
3397 | NS_ERROR_CSP_FORM_ACTION_VIOLATION == aError) { |
3398 | // CSP error |
3399 | cssClass.AssignLiteral("neterror"); |
3400 | error = "cspBlocked"; |
3401 | } else if (NS_ERROR_XFO_VIOLATION == aError) { |
3402 | // XFO error |
3403 | cssClass.AssignLiteral("neterror"); |
3404 | error = "xfoBlocked"; |
3405 | } else if (NS_ERROR_GET_MODULE(aError) == NS_ERROR_MODULE_SECURITY21) { |
3406 | nsCOMPtr<nsINSSErrorsService> nsserr = |
3407 | do_GetService(NS_NSS_ERRORS_SERVICE_CONTRACTID"@mozilla.org/nss_errors_service;1"); |
3408 | |
3409 | uint32_t errorClass; |
3410 | if (!nsserr || NS_FAILED(nsserr->GetErrorClass(aError, &errorClass))((bool)(__builtin_expect(!!(NS_FAILED_impl(nsserr->GetErrorClass (aError, &errorClass))), 0)))) { |
3411 | errorClass = nsINSSErrorsService::ERROR_CLASS_SSL_PROTOCOL; |
3412 | } |
3413 | |
3414 | nsCOMPtr<nsITransportSecurityInfo> tsi; |
3415 | if (aFailedChannel) { |
3416 | aFailedChannel->GetSecurityInfo(getter_AddRefs(tsi)); |
3417 | } |
3418 | if (tsi) { |
3419 | uint32_t securityState; |
3420 | tsi->GetSecurityState(&securityState); |
3421 | if (securityState & nsIWebProgressListener::STATE_USES_SSL_3) { |
3422 | error = "sslv3Used"; |
Value stored to 'error' is never read | |
3423 | addHostPort = true; |
3424 | } else if (securityState & |
3425 | nsIWebProgressListener::STATE_USES_WEAK_CRYPTO) { |
3426 | error = "weakCryptoUsed"; |
3427 | addHostPort = true; |
3428 | } |
3429 | } else { |
3430 | // No channel, let's obtain the generic error message |
3431 | if (nsserr) { |
3432 | nsserr->GetErrorMessage(aError, messageStr); |
3433 | } |
3434 | } |
3435 | // We don't have a message string here anymore but DisplayLoadError |
3436 | // requires a non-empty messageStr. |
3437 | messageStr.Truncate(); |
3438 | messageStr.AssignLiteral(u" "); |
3439 | if (errorClass == nsINSSErrorsService::ERROR_CLASS_BAD_CERT) { |
3440 | error = "nssBadCert"; |
3441 | |
3442 | // If this is an HTTP Strict Transport Security host or a pinned host |
3443 | // and the certificate is bad, don't allow overrides (RFC 6797 section |
3444 | // 12.1). |
3445 | bool isStsHost = false; |
3446 | bool isPinnedHost = false; |
3447 | OriginAttributes attrsForHSTS; |
3448 | if (aFailedChannel) { |
3449 | StoragePrincipalHelper::GetOriginAttributesForHSTS(aFailedChannel, |
3450 | attrsForHSTS); |
3451 | } else { |
3452 | attrsForHSTS = GetOriginAttributes(); |
3453 | } |
3454 | |
3455 | if (XRE_IsParentProcess()) { |
3456 | nsCOMPtr<nsISiteSecurityService> sss = |
3457 | do_GetService(NS_SSSERVICE_CONTRACTID"@mozilla.org/ssservice;1", &rv); |
3458 | 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" , 3458); return rv; } } while (false); |
3459 | rv = sss->IsSecureURI(aURI, attrsForHSTS, &isStsHost); |
3460 | 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" , 3460); return rv; } } while (false); |
3461 | } else { |
3462 | mozilla::dom::ContentChild* cc = |
3463 | mozilla::dom::ContentChild::GetSingleton(); |
3464 | cc->SendIsSecureURI(aURI, attrsForHSTS, &isStsHost); |
3465 | } |
3466 | nsCOMPtr<nsIPublicKeyPinningService> pkps = |
3467 | do_GetService(NS_PKPSERVICE_CONTRACTID"@mozilla.org/security/publickeypinningservice;1", &rv); |
3468 | 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" , 3468); return rv; } } while (false); |
3469 | rv = pkps->HostHasPins(aURI, &isPinnedHost); |
3470 | |
3471 | if (Preferences::GetBool("browser.xul.error_pages.expert_bad_cert", |
3472 | false)) { |
3473 | cssClass.AssignLiteral("expertBadCert"); |
3474 | } |
3475 | |
3476 | // HSTS/pinning takes precedence over the expert bad cert pref. We |
3477 | // never want to show the "Add Exception" button for these sites. |
3478 | // In the future we should differentiate between an HSTS host and a |
3479 | // pinned host and display a more informative message to the user. |
3480 | if (isStsHost || isPinnedHost) { |
3481 | isBadStsCertError = true; |
3482 | cssClass.AssignLiteral("badStsCert"); |
3483 | } |
3484 | |
3485 | errorPage.Assign("certerror"); |
3486 | } else { |
3487 | error = "nssFailure2"; |
3488 | } |
3489 | } else if (NS_ERROR_PHISHING_URI == aError || |
3490 | NS_ERROR_MALWARE_URI == aError || |
3491 | NS_ERROR_UNWANTED_URI == aError || |
3492 | NS_ERROR_HARMFUL_URI == aError) { |
3493 | nsAutoCString host; |
3494 | aURI->GetHost(host); |
3495 | CopyUTF8toUTF16(host, *formatStrs.AppendElement()); |
3496 | |
3497 | // Malware and phishing detectors may want to use an alternate error |
3498 | // page, but if the pref's not set, we'll fall back on the standard page |
3499 | nsAutoCString alternateErrorPage; |
3500 | nsresult rv = Preferences::GetCString("urlclassifier.alternate_error_page", |
3501 | alternateErrorPage); |
3502 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) { |
3503 | errorPage.Assign(alternateErrorPage); |
3504 | } |
3505 | |
3506 | if (NS_ERROR_PHISHING_URI == aError) { |
3507 | error = "deceptiveBlocked"; |
3508 | } else if (NS_ERROR_MALWARE_URI == aError) { |
3509 | error = "malwareBlocked"; |
3510 | } else if (NS_ERROR_UNWANTED_URI == aError) { |
3511 | error = "unwantedBlocked"; |
3512 | } else if (NS_ERROR_HARMFUL_URI == aError) { |
3513 | error = "harmfulBlocked"; |
3514 | } |
3515 | |
3516 | cssClass.AssignLiteral("blacklist"); |
3517 | } else if (NS_ERROR_CONTENT_CRASHED == aError) { |
3518 | errorPage.AssignLiteral("tabcrashed"); |
3519 | error = "tabcrashed"; |
3520 | |
3521 | RefPtr<EventTarget> handler = mChromeEventHandler; |
3522 | if (handler) { |
3523 | nsCOMPtr<Element> element = do_QueryInterface(handler); |
3524 | element->GetAttribute(u"crashedPageTitle"_ns, messageStr); |
3525 | } |
3526 | |
3527 | // DisplayLoadError requires a non-empty messageStr to proceed and call |
3528 | // LoadErrorPage. If the page doesn't have a title, we will use a blank |
3529 | // space which will be trimmed and thus treated as empty by the front-end. |
3530 | if (messageStr.IsEmpty()) { |
3531 | messageStr.AssignLiteral(u" "); |
3532 | } |
3533 | } else if (NS_ERROR_FRAME_CRASHED == aError) { |
3534 | errorPage.AssignLiteral("framecrashed"); |
3535 | error = "framecrashed"; |
3536 | messageStr.AssignLiteral(u" "); |
3537 | } else if (NS_ERROR_BUILDID_MISMATCH == aError) { |
3538 | errorPage.AssignLiteral("restartrequired"); |
3539 | error = "restartrequired"; |
3540 | |
3541 | // DisplayLoadError requires a non-empty messageStr to proceed and call |
3542 | // LoadErrorPage. If the page doesn't have a title, we will use a blank |
3543 | // space which will be trimmed and thus treated as empty by the front-end. |
3544 | if (messageStr.IsEmpty()) { |
3545 | messageStr.AssignLiteral(u" "); |
3546 | } |
3547 | } else { |
3548 | // Errors requiring simple formatting |
3549 | switch (aError) { |
3550 | case NS_ERROR_MALFORMED_URI: |
3551 | // URI is malformed |
3552 | error = "malformedURI"; |
3553 | errorDescriptionID = "malformedURI2"; |
3554 | break; |
3555 | case NS_ERROR_REDIRECT_LOOP: |
3556 | // Doc failed to load because the server generated too many redirects |
3557 | error = "redirectLoop"; |
3558 | break; |
3559 | case NS_ERROR_UNKNOWN_SOCKET_TYPE: |
3560 | // Doc failed to load because PSM is not installed |
3561 | error = "unknownSocketType"; |
3562 | break; |
3563 | case NS_ERROR_NET_RESET: |
3564 | // Doc failed to load because the server kept reseting the connection |
3565 | // before we could read any data from it |
3566 | error = "netReset"; |
3567 | break; |
3568 | case NS_ERROR_DOCUMENT_NOT_CACHED: |
3569 | // Doc failed to load because the cache does not contain a copy of |
3570 | // the document. |
3571 | error = "notCached"; |
3572 | break; |
3573 | case NS_ERROR_OFFLINE: |
3574 | // Doc failed to load because we are offline. |
3575 | error = "netOffline"; |
3576 | break; |
3577 | case NS_ERROR_DOCUMENT_IS_PRINTMODE: |
3578 | // Doc navigation attempted while Printing or Print Preview |
3579 | error = "isprinting"; |
3580 | break; |
3581 | case NS_ERROR_PORT_ACCESS_NOT_ALLOWED: |
3582 | // Port blocked for security reasons |
3583 | addHostPort = true; |
3584 | error = "deniedPortAccess"; |
3585 | break; |
3586 | case NS_ERROR_UNKNOWN_PROXY_HOST: |
3587 | // Proxy hostname could not be resolved. |
3588 | error = "proxyResolveFailure"; |
3589 | break; |
3590 | case NS_ERROR_PROXY_CONNECTION_REFUSED: |
3591 | case NS_ERROR_PROXY_FORBIDDEN: |
3592 | case NS_ERROR_PROXY_NOT_IMPLEMENTED: |
3593 | case NS_ERROR_PROXY_AUTHENTICATION_FAILED: |
3594 | case NS_ERROR_PROXY_TOO_MANY_REQUESTS: |
3595 | // Proxy connection was refused. |
3596 | error = "proxyConnectFailure"; |
3597 | break; |
3598 | case NS_ERROR_INVALID_CONTENT_ENCODING: |
3599 | // Bad Content Encoding. |
3600 | error = "contentEncodingError"; |
3601 | break; |
3602 | case NS_ERROR_UNSAFE_CONTENT_TYPE: |
3603 | // Channel refused to load from an unrecognized content type. |
3604 | error = "unsafeContentType"; |
3605 | break; |
3606 | case NS_ERROR_CORRUPTED_CONTENT: |
3607 | // Broken Content Detected. e.g. Content-MD5 check failure. |
3608 | error = "corruptedContentErrorv2"; |
3609 | break; |
3610 | case NS_ERROR_INTERCEPTION_FAILED: |
3611 | // ServiceWorker intercepted request, but something went wrong. |
3612 | error = "corruptedContentErrorv2"; |
3613 | break; |
3614 | case NS_ERROR_NET_INADEQUATE_SECURITY: |
3615 | // Server negotiated bad TLS for HTTP/2. |
3616 | error = "inadequateSecurityError"; |
3617 | addHostPort = true; |
3618 | break; |
3619 | case NS_ERROR_BLOCKED_BY_POLICY: |
3620 | case NS_ERROR_DOM_COOP_FAILED: |
3621 | case NS_ERROR_DOM_COEP_FAILED: |
3622 | // Page blocked by policy |
3623 | error = "blockedByPolicy"; |
3624 | break; |
3625 | case NS_ERROR_NET_HTTP2_SENT_GOAWAY: |
3626 | case NS_ERROR_NET_HTTP3_PROTOCOL_ERROR: |
3627 | // HTTP/2 or HTTP/3 stack detected a protocol error |
3628 | error = "networkProtocolError"; |
3629 | break; |
3630 | |
3631 | default: |
3632 | break; |
3633 | } |
3634 | } |
3635 | |
3636 | nsresult delegateErrorCode = aError; |
3637 | // If the HTTPS-Only Mode upgraded this request and the upgrade might have |
3638 | // caused this error, we replace the error-page with about:httpsonlyerror |
3639 | if (nsHTTPSOnlyUtils::CouldBeHttpsOnlyError(aFailedChannel, aError)) { |
3640 | errorPage.AssignLiteral("httpsonlyerror"); |
3641 | delegateErrorCode = NS_ERROR_HTTPS_ONLY; |
3642 | } else if (isBadStsCertError) { |
3643 | delegateErrorCode = NS_ERROR_BAD_HSTS_CERT; |
3644 | } |
3645 | |
3646 | if (nsCOMPtr<nsILoadURIDelegate> loadURIDelegate = GetLoadURIDelegate()) { |
3647 | nsCOMPtr<nsIURI> errorPageURI; |
3648 | rv = loadURIDelegate->HandleLoadError( |
3649 | aURI, delegateErrorCode, NS_ERROR_GET_MODULE(delegateErrorCode), |
3650 | getter_AddRefs(errorPageURI)); |
3651 | // If the docshell is going away there's no point in showing an error page. |
3652 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || mIsBeingDestroyed) { |
3653 | *aDisplayedErrorPage = false; |
3654 | return NS_OK; |
3655 | } |
3656 | |
3657 | if (errorPageURI) { |
3658 | *aDisplayedErrorPage = |
3659 | NS_SUCCEEDED(LoadErrorPage(errorPageURI, aURI, aFailedChannel))((bool)(__builtin_expect(!!(!NS_FAILED_impl(LoadErrorPage(errorPageURI , aURI, aFailedChannel))), 1))); |
3660 | return NS_OK; |
3661 | } |
3662 | } |
3663 | |
3664 | // Test if the error should be displayed |
3665 | if (!error) { |
3666 | return NS_OK; |
3667 | } |
3668 | |
3669 | if (!errorDescriptionID) { |
3670 | errorDescriptionID = error; |
3671 | } |
3672 | |
3673 | Telemetry::AccumulateCategoricalKeyed( |
3674 | IsSubframe() ? "frame"_ns : "top"_ns, |
3675 | mozilla::dom::LoadErrorToTelemetryLabel(aError)); |
3676 | |
3677 | // Test if the error needs to be formatted |
3678 | if (!messageStr.IsEmpty()) { |
3679 | // already obtained message |
3680 | } else { |
3681 | if (addHostPort) { |
3682 | // Build up the host:port string. |
3683 | nsAutoCString hostport; |
3684 | if (aURI) { |
3685 | aURI->GetHostPort(hostport); |
3686 | } else { |
3687 | hostport.Assign('?'); |
3688 | } |
3689 | CopyUTF8toUTF16(hostport, *formatStrs.AppendElement()); |
3690 | } |
3691 | |
3692 | nsAutoCString spec; |
3693 | rv = NS_ERROR_NOT_AVAILABLE; |
3694 | auto& nextFormatStr = *formatStrs.AppendElement(); |
3695 | if (aURI) { |
3696 | // displaying "file://" is aesthetically unpleasing and could even be |
3697 | // confusing to the user |
3698 | if (SchemeIsFile(aURI)) { |
3699 | aURI->GetPathQueryRef(spec); |
3700 | } else { |
3701 | aURI->GetSpec(spec); |
3702 | } |
3703 | |
3704 | nsCOMPtr<nsITextToSubURI> textToSubURI( |
3705 | do_GetService(NS_ITEXTTOSUBURI_CONTRACTID"@mozilla.org/intl/texttosuburi;1", &rv)); |
3706 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) { |
3707 | rv = textToSubURI->UnEscapeURIForUI(spec, nextFormatStr); |
3708 | } |
3709 | } else { |
3710 | spec.Assign('?'); |
3711 | } |
3712 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
3713 | CopyUTF8toUTF16(spec, nextFormatStr); |
3714 | } |
3715 | rv = NS_OK; |
3716 | |
3717 | nsAutoString str; |
3718 | rv = |
3719 | stringBundle->FormatStringFromName(errorDescriptionID, formatStrs, str); |
3720 | 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" , 3720); return rv; } } while (false); |
3721 | messageStr.Assign(str); |
3722 | } |
3723 | |
3724 | // Display the error as a page or an alert prompt |
3725 | 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" , 3725); return NS_ERROR_FAILURE; } } while (false); |
3726 | |
3727 | if ((NS_ERROR_NET_INTERRUPT == aError || NS_ERROR_NET_RESET == aError) && |
3728 | SchemeIsHTTPS(aURI)) { |
3729 | // Maybe TLS intolerant. Treat this as an SSL error. |
3730 | error = "nssFailure2"; |
3731 | } |
3732 | |
3733 | if (mBrowsingContext->GetUseErrorPages()) { |
3734 | // Display an error page |
3735 | nsresult loadedPage = |
3736 | LoadErrorPage(aURI, aURL, errorPage.get(), error, messageStr.get(), |
3737 | cssClass.get(), aFailedChannel); |
3738 | *aDisplayedErrorPage = NS_SUCCEEDED(loadedPage)((bool)(__builtin_expect(!!(!NS_FAILED_impl(loadedPage)), 1)) ); |
3739 | } else { |
3740 | // The prompter reqires that our private window has a document (or it |
3741 | // asserts). Satisfy that assertion now since GetDoc will force |
3742 | // creation of one if it hasn't already been created. |
3743 | if (mScriptGlobal) { |
3744 | Unused << mScriptGlobal->GetDoc(); |
3745 | } |
3746 | |
3747 | // Display a message box |
3748 | prompter->Alert(nullptr, messageStr.get()); |
3749 | } |
3750 | |
3751 | return NS_OK; |
3752 | } |
3753 | |
3754 | #define PREF_SAFEBROWSING_ALLOWOVERRIDE"browser.safebrowsing.allowOverride" "browser.safebrowsing.allowOverride" |
3755 | |
3756 | nsresult nsDocShell::LoadErrorPage(nsIURI* aURI, const char16_t* aURL, |
3757 | const char* aErrorPage, |
3758 | const char* aErrorType, |
3759 | const char16_t* aDescription, |
3760 | const char* aCSSClass, |
3761 | nsIChannel* aFailedChannel) { |
3762 | if (mIsBeingDestroyed) { |
3763 | return NS_ERROR_NOT_AVAILABLE; |
3764 | } |
3765 | |
3766 | #if defined(DEBUG1) |
3767 | if (MOZ_LOG_TEST(gDocShellLog, LogLevel::Debug)(__builtin_expect(!!(mozilla::detail::log_test(gDocShellLog, LogLevel ::Debug)), 0))) { |
3768 | nsAutoCString chanName; |
3769 | if (aFailedChannel) { |
3770 | aFailedChannel->GetName(chanName); |
3771 | } else { |
3772 | chanName.AssignLiteral("<no channel>"); |
3773 | } |
3774 | |
3775 | 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) |
3776 | ("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) |
3777 | 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) |
3778 | 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); |
3779 | } |
3780 | #endif |
3781 | |
3782 | nsAutoCString url; |
3783 | if (aURI) { |
3784 | nsresult rv = aURI->GetSpec(url); |
3785 | 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" , 3785); return rv; } } while (false); |
3786 | } else if (aURL) { |
3787 | CopyUTF16toUTF8(MakeStringSpan(aURL), url); |
3788 | } else { |
3789 | return NS_ERROR_INVALID_POINTER; |
3790 | } |
3791 | |
3792 | // Create a URL to pass all the error information through to the page. |
3793 | |
3794 | #undef SAFE_ESCAPE |
3795 | #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" , 3795)) { return NS_ERROR_OUT_OF_MEMORY; } \ |
3796 | 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" , 3796)) { \ |
3797 | return NS_ERROR_OUT_OF_MEMORY; \ |
3798 | } |
3799 | |
3800 | nsCString escapedUrl, escapedError, escapedDescription, escapedCSSClass; |
3801 | 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" , 3801)) { return NS_ERROR_OUT_OF_MEMORY; }; |
3802 | 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" , 3802)) { return NS_ERROR_OUT_OF_MEMORY; }; |
3803 | 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" , 3804)) { return NS_ERROR_OUT_OF_MEMORY; } |
3804 | 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" , 3804)) { return NS_ERROR_OUT_OF_MEMORY; }; |
3805 | if (aCSSClass) { |
3806 | nsCString cssClass(aCSSClass); |
3807 | 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" , 3807)) { return NS_ERROR_OUT_OF_MEMORY; }; |
3808 | } |
3809 | nsCString errorPageUrl("about:"); |
3810 | errorPageUrl.AppendASCII(aErrorPage); |
3811 | errorPageUrl.AppendLiteral("?e="); |
3812 | |
3813 | errorPageUrl.AppendASCII(escapedError.get()); |
3814 | errorPageUrl.AppendLiteral("&u="); |
3815 | errorPageUrl.AppendASCII(escapedUrl.get()); |
3816 | if ((strcmp(aErrorPage, "blocked") == 0) && |
3817 | Preferences::GetBool(PREF_SAFEBROWSING_ALLOWOVERRIDE"browser.safebrowsing.allowOverride", true)) { |
3818 | errorPageUrl.AppendLiteral("&o=1"); |
3819 | } |
3820 | if (!escapedCSSClass.IsEmpty()) { |
3821 | errorPageUrl.AppendLiteral("&s="); |
3822 | errorPageUrl.AppendASCII(escapedCSSClass.get()); |
3823 | } |
3824 | errorPageUrl.AppendLiteral("&c=UTF-8"); |
3825 | |
3826 | nsCOMPtr<nsICaptivePortalService> cps = do_GetService(NS_CAPTIVEPORTAL_CID{ 0xbdbe0555, 0xfc3d, 0x4f7b, { 0x92, 0x05, 0xc3, 0x09, 0xce, 0xb2, 0xd6, 0x41 } }); |
3827 | int32_t cpsState; |
3828 | if (cps && NS_SUCCEEDED(cps->GetState(&cpsState))((bool)(__builtin_expect(!!(!NS_FAILED_impl(cps->GetState( &cpsState))), 1))) && |
3829 | cpsState == nsICaptivePortalService::LOCKED_PORTAL) { |
3830 | errorPageUrl.AppendLiteral("&captive=true"); |
3831 | } |
3832 | |
3833 | errorPageUrl.AppendLiteral("&d="); |
3834 | errorPageUrl.AppendASCII(escapedDescription.get()); |
3835 | |
3836 | nsCOMPtr<nsIURI> errorPageURI; |
3837 | nsresult rv = NS_NewURI(getter_AddRefs(errorPageURI), errorPageUrl); |
3838 | 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" , 3838); return rv; } } while (false); |
3839 | |
3840 | return LoadErrorPage(errorPageURI, aURI, aFailedChannel); |
3841 | } |
3842 | |
3843 | nsresult nsDocShell::LoadErrorPage(nsIURI* aErrorURI, nsIURI* aFailedURI, |
3844 | nsIChannel* aFailedChannel) { |
3845 | mFailedChannel = aFailedChannel; |
3846 | mFailedURI = aFailedURI; |
3847 | mFailedLoadType = mLoadType; |
3848 | |
3849 | if (mLSHE) { |
3850 | // Abandon mLSHE's BFCache entry and create a new one. This way, if |
3851 | // we go back or forward to another SHEntry with the same doc |
3852 | // identifier, the error page won't persist. |
3853 | mLSHE->AbandonBFCacheEntry(); |
3854 | } |
3855 | |
3856 | RefPtr<nsDocShellLoadState> loadState = new nsDocShellLoadState(aErrorURI); |
3857 | loadState->SetTriggeringPrincipal(nsContentUtils::GetSystemPrincipal()); |
3858 | if (mBrowsingContext) { |
3859 | loadState->SetTriggeringSandboxFlags(mBrowsingContext->GetSandboxFlags()); |
3860 | loadState->SetTriggeringWindowId( |
3861 | mBrowsingContext->GetCurrentInnerWindowId()); |
3862 | nsPIDOMWindowInner* innerWin = mScriptGlobal->GetCurrentInnerWindow(); |
3863 | if (innerWin) { |
3864 | loadState->SetTriggeringStorageAccess(innerWin->UsingStorageAccess()); |
3865 | } |
3866 | } |
3867 | loadState->SetLoadType(LOAD_ERROR_PAGE); |
3868 | loadState->SetFirstParty(true); |
3869 | loadState->SetSourceBrowsingContext(mBrowsingContext); |
3870 | if (mozilla::SessionHistoryInParent() && mLoadingEntry) { |
3871 | // We keep the loading entry for the load that failed here. If the user |
3872 | // reloads we want to try to reload the original load, not the error page. |
3873 | loadState->SetLoadingSessionHistoryInfo( |
3874 | MakeUnique<LoadingSessionHistoryInfo>(*mLoadingEntry)); |
3875 | } |
3876 | return InternalLoad(loadState); |
3877 | } |
3878 | |
3879 | NS_IMETHODIMPnsresult |
3880 | nsDocShell::Reload(uint32_t aReloadFlags) { |
3881 | if (!IsNavigationAllowed()) { |
3882 | return NS_OK; // JS may not handle returning of an error code |
3883 | } |
3884 | |
3885 | 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" , 3886); MOZ_PretendNoReturn(); } } while (0) |
3886 | "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" , 3886); MOZ_PretendNoReturn(); } } while (0); |
3887 | 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" , 3888); MOZ_PretendNoReturn(); } } while (0) |
3888 | "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" , 3888); MOZ_PretendNoReturn(); } } while (0); |
3889 | |
3890 | uint32_t loadType = MAKE_LOAD_TYPE(LOAD_RELOAD_NORMAL, aReloadFlags)((LOAD_RELOAD_NORMAL) | ((aReloadFlags) << 16)); |
3891 | 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" , 3891); return NS_ERROR_INVALID_ARG; } } while (false); |
3892 | |
3893 | // Send notifications to the HistoryListener if any, about the impending |
3894 | // reload |
3895 | RefPtr<ChildSHistory> rootSH = GetRootSessionHistory(); |
3896 | if (mozilla::SessionHistoryInParent()) { |
3897 | 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); |
3898 | bool forceReload = IsForceReloadType(loadType); |
3899 | if (!XRE_IsParentProcess()) { |
3900 | ++mPendingReloadCount; |
3901 | RefPtr<nsDocShell> docShell(this); |
3902 | nsCOMPtr<nsIDocumentViewer> viewer(mDocumentViewer); |
3903 | 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" , 3903); return NS_ERROR_UNEXPECTED; } } while (false); |
3904 | |
3905 | bool okToUnload = true; |
3906 | MOZ_TRY(viewer->PermitUnload(&okToUnload))do { auto mozTryTempResult_ = ::mozilla::ToResult(viewer-> PermitUnload(&okToUnload)); if ((__builtin_expect(!!(mozTryTempResult_ .isErr()), 0))) { return mozTryTempResult_.propagateErr(); } } while (0); |
3907 | if (!okToUnload) { |
3908 | return NS_OK; |
3909 | } |
3910 | |
3911 | RefPtr<Document> doc(GetDocument()); |
3912 | RefPtr<BrowsingContext> browsingContext(mBrowsingContext); |
3913 | nsCOMPtr<nsIURI> currentURI(mCurrentURI); |
3914 | nsCOMPtr<nsIReferrerInfo> referrerInfo(mReferrerInfo); |
3915 | RefPtr<StopDetector> stopDetector = new StopDetector(); |
3916 | nsCOMPtr<nsILoadGroup> loadGroup; |
3917 | GetLoadGroup(getter_AddRefs(loadGroup)); |
3918 | if (loadGroup) { |
3919 | // loadGroup may be null in theory. In that case stopDetector just |
3920 | // doesn't do anything. |
3921 | loadGroup->AddRequest(stopDetector, nullptr); |
3922 | } |
3923 | |
3924 | ContentChild::GetSingleton()->SendNotifyOnHistoryReload( |
3925 | mBrowsingContext, forceReload, |
3926 | [docShell, doc, loadType, browsingContext, currentURI, referrerInfo, |
3927 | loadGroup, stopDetector]( |
3928 | std::tuple<bool, Maybe<NotNull<RefPtr<nsDocShellLoadState>>>, |
3929 | Maybe<bool>>&& aResult) { |
3930 | auto scopeExit = MakeScopeExit([loadGroup, stopDetector]() { |
3931 | if (loadGroup) { |
3932 | loadGroup->RemoveRequest(stopDetector, nullptr, NS_OK); |
3933 | } |
3934 | }); |
3935 | |
3936 | // Decrease mPendingReloadCount before any other early returns! |
3937 | if (--(docShell->mPendingReloadCount) > 0) { |
3938 | return; |
3939 | } |
3940 | |
3941 | if (stopDetector->Canceled()) { |
3942 | return; |
3943 | } |
3944 | bool canReload; |
3945 | Maybe<NotNull<RefPtr<nsDocShellLoadState>>> loadState; |
3946 | Maybe<bool> reloadingActiveEntry; |
3947 | |
3948 | std::tie(canReload, loadState, reloadingActiveEntry) = aResult; |
3949 | |
3950 | if (!canReload) { |
3951 | return; |
3952 | } |
3953 | |
3954 | if (loadState.isSome()) { |
3955 | 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) |
3956 | 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) |
3957 | ("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); |
3958 | loadState.ref()->SetNotifiedBeforeUnloadListeners(true); |
3959 | docShell->LoadHistoryEntry(loadState.ref(), loadType, |
3960 | reloadingActiveEntry.ref()); |
3961 | } else { |
3962 | 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) |
3963 | ("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); |
3964 | ReloadDocument(docShell, doc, loadType, browsingContext, |
3965 | currentURI, referrerInfo, |
3966 | /* aNotifiedBeforeUnloadListeners */ true); |
3967 | } |
3968 | }, |
3969 | [](mozilla::ipc::ResponseRejectReason) {}); |
3970 | } else { |
3971 | // Parent process |
3972 | bool canReload = false; |
3973 | Maybe<NotNull<RefPtr<nsDocShellLoadState>>> loadState; |
3974 | Maybe<bool> reloadingActiveEntry; |
3975 | if (!mBrowsingContext->IsDiscarded()) { |
3976 | mBrowsingContext->Canonical()->NotifyOnHistoryReload( |
3977 | forceReload, canReload, loadState, reloadingActiveEntry); |
3978 | } |
3979 | if (canReload) { |
3980 | if (loadState.isSome()) { |
3981 | 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) |
3982 | ("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); |
3983 | LoadHistoryEntry(loadState.ref(), loadType, |
3984 | reloadingActiveEntry.ref()); |
3985 | } else { |
3986 | 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) |
3987 | ("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); |
3988 | RefPtr<Document> doc = GetDocument(); |
3989 | RefPtr<BrowsingContext> bc = mBrowsingContext; |
3990 | nsCOMPtr<nsIURI> currentURI = mCurrentURI; |
3991 | nsCOMPtr<nsIReferrerInfo> referrerInfo = mReferrerInfo; |
3992 | ReloadDocument(this, doc, loadType, bc, currentURI, referrerInfo); |
3993 | } |
3994 | } |
3995 | } |
3996 | return NS_OK; |
3997 | } |
3998 | |
3999 | bool canReload = true; |
4000 | if (rootSH) { |
4001 | rootSH->LegacySHistory()->NotifyOnHistoryReload(&canReload); |
4002 | } |
4003 | |
4004 | if (!canReload) { |
4005 | return NS_OK; |
4006 | } |
4007 | |
4008 | /* If you change this part of code, make sure bug 45297 does not re-occur */ |
4009 | if (mOSHE) { |
4010 | nsCOMPtr<nsISHEntry> oshe = mOSHE; |
4011 | return LoadHistoryEntry( |
4012 | oshe, loadType, |
4013 | aReloadFlags & nsIWebNavigation::LOAD_FLAGS_USER_ACTIVATION); |
4014 | } |
4015 | |
4016 | if (mLSHE) { // In case a reload happened before the current load is done |
4017 | nsCOMPtr<nsISHEntry> lshe = mLSHE; |
4018 | return LoadHistoryEntry( |
4019 | lshe, loadType, |
4020 | aReloadFlags & nsIWebNavigation::LOAD_FLAGS_USER_ACTIVATION); |
4021 | } |
4022 | |
4023 | RefPtr<Document> doc = GetDocument(); |
4024 | RefPtr<BrowsingContext> bc = mBrowsingContext; |
4025 | nsCOMPtr<nsIURI> currentURI = mCurrentURI; |
4026 | nsCOMPtr<nsIReferrerInfo> referrerInfo = mReferrerInfo; |
4027 | return ReloadDocument(this, doc, loadType, bc, currentURI, referrerInfo); |
4028 | } |
4029 | |
4030 | /* static */ |
4031 | nsresult nsDocShell::ReloadDocument(nsDocShell* aDocShell, Document* aDocument, |
4032 | uint32_t aLoadType, |
4033 | BrowsingContext* aBrowsingContext, |
4034 | nsIURI* aCurrentURI, |
4035 | nsIReferrerInfo* aReferrerInfo, |
4036 | bool aNotifiedBeforeUnloadListeners) { |
4037 | if (!aDocument) { |
4038 | return NS_OK; |
4039 | } |
4040 | |
4041 | // Do not inherit owner from document |
4042 | uint32_t flags = INTERNAL_LOAD_FLAGS_NONE; |
4043 | nsAutoString srcdoc; |
4044 | nsIURI* baseURI = nullptr; |
4045 | nsCOMPtr<nsIURI> originalURI; |
4046 | nsCOMPtr<nsIURI> resultPrincipalURI; |
4047 | bool loadReplace = false; |
4048 | |
4049 | nsIPrincipal* triggeringPrincipal = aDocument->NodePrincipal(); |
4050 | nsCOMPtr<nsIContentSecurityPolicy> csp = aDocument->GetCsp(); |
4051 | uint32_t triggeringSandboxFlags = aDocument->GetSandboxFlags(); |
4052 | uint64_t triggeringWindowId = aDocument->InnerWindowID(); |
4053 | bool triggeringStorageAccess = aDocument->UsingStorageAccess(); |
4054 | |
4055 | nsAutoString contentTypeHint; |
4056 | aDocument->GetContentType(contentTypeHint); |
4057 | |
4058 | if (aDocument->IsSrcdocDocument()) { |
4059 | aDocument->GetSrcdocData(srcdoc); |
4060 | flags |= INTERNAL_LOAD_FLAGS_IS_SRCDOC; |
4061 | baseURI = aDocument->GetBaseURI(); |
4062 | } else { |
4063 | srcdoc = VoidString(); |
4064 | } |
4065 | nsCOMPtr<nsIChannel> chan = aDocument->GetChannel(); |
4066 | if (chan) { |
4067 | uint32_t loadFlags; |
4068 | chan->GetLoadFlags(&loadFlags); |
4069 | loadReplace = loadFlags & nsIChannel::LOAD_REPLACE; |
4070 | nsCOMPtr<nsIHttpChannel> httpChan(do_QueryInterface(chan)); |
4071 | if (httpChan) { |
4072 | httpChan->GetOriginalURI(getter_AddRefs(originalURI)); |
4073 | } |
4074 | |
4075 | nsCOMPtr<nsILoadInfo> loadInfo = chan->LoadInfo(); |
4076 | loadInfo->GetResultPrincipalURI(getter_AddRefs(resultPrincipalURI)); |
4077 | } |
4078 | |
4079 | if (!triggeringPrincipal) { |
4080 | 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" , 4080); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "Reload needs a valid triggeringPrincipal" ")"); do { *((volatile int*)__null) = 4080; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
4081 | return NS_ERROR_FAILURE; |
4082 | } |
4083 | |
4084 | // Stack variables to ensure changes to the member variables don't affect to |
4085 | // the call. |
4086 | nsCOMPtr<nsIURI> currentURI = aCurrentURI; |
4087 | |
4088 | // Reload always rewrites result principal URI. |
4089 | Maybe<nsCOMPtr<nsIURI>> emplacedResultPrincipalURI; |
4090 | emplacedResultPrincipalURI.emplace(std::move(resultPrincipalURI)); |
4091 | |
4092 | RefPtr<WindowContext> context = aBrowsingContext->GetCurrentWindowContext(); |
4093 | RefPtr<nsDocShellLoadState> loadState = new nsDocShellLoadState(currentURI); |
4094 | loadState->SetReferrerInfo(aReferrerInfo); |
4095 | loadState->SetOriginalURI(originalURI); |
4096 | loadState->SetMaybeResultPrincipalURI(emplacedResultPrincipalURI); |
4097 | loadState->SetLoadReplace(loadReplace); |
4098 | loadState->SetTriggeringPrincipal(triggeringPrincipal); |
4099 | loadState->SetTriggeringSandboxFlags(triggeringSandboxFlags); |
4100 | loadState->SetTriggeringWindowId(triggeringWindowId); |
4101 | loadState->SetTriggeringStorageAccess(triggeringStorageAccess); |
4102 | loadState->SetPrincipalToInherit(triggeringPrincipal); |
4103 | loadState->SetCsp(csp); |
4104 | loadState->SetInternalLoadFlags(flags); |
4105 | loadState->SetTypeHint(NS_ConvertUTF16toUTF8(contentTypeHint)); |
4106 | loadState->SetLoadType(aLoadType); |
4107 | loadState->SetFirstParty(true); |
4108 | loadState->SetSrcdocData(srcdoc); |
4109 | loadState->SetSourceBrowsingContext(aBrowsingContext); |
4110 | loadState->SetBaseURI(baseURI); |
4111 | loadState->SetHasValidUserGestureActivation( |
4112 | context && context->HasValidTransientUserGestureActivation()); |
4113 | |
4114 | loadState->SetTextDirectiveUserActivation( |
4115 | aDocument->ConsumeTextDirectiveUserActivation() || |
4116 | loadState->HasValidUserGestureActivation()); |
4117 | |
4118 | loadState->SetNotifiedBeforeUnloadListeners(aNotifiedBeforeUnloadListeners); |
4119 | return aDocShell->InternalLoad(loadState); |
4120 | } |
4121 | |
4122 | NS_IMETHODIMPnsresult |
4123 | nsDocShell::Stop(uint32_t aStopFlags) { |
4124 | // Revoke any pending event related to content viewer restoration |
4125 | mRestorePresentationEvent.Revoke(); |
4126 | |
4127 | if (mLoadType == LOAD_ERROR_PAGE) { |
4128 | if (mLSHE) { |
4129 | // Since error page loads never unset mLSHE, do so now |
4130 | SetHistoryEntryAndUpdateBC(Some(nullptr), Some<nsISHEntry*>(mLSHE)); |
4131 | } |
4132 | mActiveEntryIsLoadingFromSessionHistory = false; |
4133 | |
4134 | mFailedChannel = nullptr; |
4135 | mFailedURI = nullptr; |
4136 | } |
4137 | |
4138 | if (nsIWebNavigation::STOP_CONTENT & aStopFlags) { |
4139 | // Stop the document loading and animations |
4140 | if (mDocumentViewer) { |
4141 | nsCOMPtr<nsIDocumentViewer> viewer = mDocumentViewer; |
4142 | viewer->Stop(); |
4143 | } |
4144 | } else if (nsIWebNavigation::STOP_NETWORK & aStopFlags) { |
4145 | // Stop the document loading only |
4146 | if (mDocumentViewer) { |
4147 | RefPtr<Document> doc = mDocumentViewer->GetDocument(); |
4148 | if (doc) { |
4149 | doc->StopDocumentLoad(); |
4150 | } |
4151 | } |
4152 | } |
4153 | |
4154 | if (nsIWebNavigation::STOP_NETWORK & aStopFlags) { |
4155 | // Suspend any timers that were set for this loader. We'll clear |
4156 | // them out for good in CreateDocumentViewer. |
4157 | if (mRefreshURIList) { |
4158 | SuspendRefreshURIs(); |
4159 | mSavedRefreshURIList.swap(mRefreshURIList); |
4160 | mRefreshURIList = nullptr; |
4161 | } |
4162 | |
4163 | // XXXbz We could also pass |this| to nsIURILoader::Stop. That will |
4164 | // just call Stop() on us as an nsIDocumentLoader... We need fewer |
4165 | // redundant apis! |
4166 | Stop(); |
4167 | |
4168 | // Clear out mChannelToDisconnectOnPageHide. This page won't go in the |
4169 | // BFCache now, and the Stop above will have removed the DocumentChannel |
4170 | // from the loadgroup. |
4171 | mChannelToDisconnectOnPageHide = 0; |
4172 | } |
4173 | |
4174 | for (auto* child : mChildList.ForwardRange()) { |
4175 | nsCOMPtr<nsIWebNavigation> shellAsNav(do_QueryObject(child)); |
4176 | if (shellAsNav) { |
4177 | shellAsNav->Stop(aStopFlags); |
4178 | } |
4179 | } |
4180 | |
4181 | return NS_OK; |
4182 | } |
4183 | |
4184 | NS_IMETHODIMPnsresult |
4185 | nsDocShell::GetDocument(Document** aDocument) { |
4186 | 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" , 4186); return NS_ERROR_INVALID_POINTER; } } while (false); |
4187 | 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" , 4187); return NS_ERROR_FAILURE; } } while (false); |
4188 | |
4189 | RefPtr<Document> doc = mDocumentViewer->GetDocument(); |
4190 | if (!doc) { |
4191 | return NS_ERROR_NOT_AVAILABLE; |
4192 | } |
4193 | |
4194 | doc.forget(aDocument); |
4195 | return NS_OK; |
4196 | } |
4197 | |
4198 | NS_IMETHODIMPnsresult |
4199 | nsDocShell::GetCurrentURI(nsIURI** aURI) { |
4200 | 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" , 4200); return NS_ERROR_INVALID_POINTER; } } while (false); |
4201 | |
4202 | nsCOMPtr<nsIURI> uri = mCurrentURI; |
4203 | uri.forget(aURI); |
4204 | return NS_OK; |
4205 | } |
4206 | |
4207 | NS_IMETHODIMPnsresult |
4208 | nsDocShell::GetSessionHistoryXPCOM(nsISupports** aSessionHistory) { |
4209 | 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" , 4209); return NS_ERROR_INVALID_POINTER; } } while (false); |
4210 | RefPtr<ChildSHistory> shistory = GetSessionHistory(); |
4211 | shistory.forget(aSessionHistory); |
4212 | return NS_OK; |
4213 | } |
4214 | |
4215 | //***************************************************************************** |
4216 | // nsDocShell::nsIWebPageDescriptor |
4217 | //***************************************************************************** |
4218 | |
4219 | NS_IMETHODIMPnsresult |
4220 | nsDocShell::LoadPageAsViewSource(nsIDocShell* aOtherDocShell, |
4221 | const nsAString& aURI) { |
4222 | if (!aOtherDocShell) { |
4223 | return NS_ERROR_INVALID_POINTER; |
4224 | } |
4225 | nsCOMPtr<nsIURI> newURI; |
4226 | nsresult rv = NS_NewURI(getter_AddRefs(newURI), aURI); |
4227 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
4228 | return rv; |
4229 | } |
4230 | |
4231 | RefPtr<nsDocShellLoadState> loadState; |
4232 | uint32_t cacheKey; |
4233 | auto* otherDocShell = nsDocShell::Cast(aOtherDocShell); |
4234 | if (mozilla::SessionHistoryInParent()) { |
4235 | loadState = new nsDocShellLoadState(newURI); |
4236 | if (!otherDocShell->FillLoadStateFromCurrentEntry(*loadState)) { |
4237 | return NS_ERROR_INVALID_POINTER; |
4238 | } |
4239 | cacheKey = otherDocShell->GetCacheKeyFromCurrentEntry().valueOr(0); |
4240 | } else { |
4241 | nsCOMPtr<nsISHEntry> entry; |
4242 | bool isOriginalSHE; |
4243 | otherDocShell->GetCurrentSHEntry(getter_AddRefs(entry), &isOriginalSHE); |
4244 | if (!entry) { |
4245 | return NS_ERROR_INVALID_POINTER; |
4246 | } |
4247 | rv = entry->CreateLoadInfo(getter_AddRefs(loadState)); |
4248 | 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" , 4248); return rv; } } while (false); |
4249 | entry->GetCacheKey(&cacheKey); |
4250 | loadState->SetURI(newURI); |
4251 | loadState->SetSHEntry(nullptr); |
4252 | } |
4253 | |
4254 | // We're doing a load of the page, via an API that |
4255 | // is only exposed to system code. The triggering principal for this load |
4256 | // should be the system principal. |
4257 | loadState->SetTriggeringPrincipal(nsContentUtils::GetSystemPrincipal()); |
4258 | loadState->SetOriginalURI(nullptr); |
4259 | loadState->SetResultPrincipalURI(nullptr); |
4260 | |
4261 | return InternalLoad(loadState, Some(cacheKey)); |
4262 | } |
4263 | |
4264 | NS_IMETHODIMPnsresult |
4265 | nsDocShell::GetCurrentDescriptor(nsISupports** aPageDescriptor) { |
4266 | 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" , 4266); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPageDescriptor" ") (" "Null out param?" ")"); do { *((volatile int*)__null) = 4266; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
4267 | |
4268 | *aPageDescriptor = nullptr; |
4269 | |
4270 | nsISHEntry* src = mOSHE ? mOSHE : mLSHE; |
4271 | if (src) { |
4272 | nsCOMPtr<nsISHEntry> dest; |
4273 | |
4274 | nsresult rv = src->Clone(getter_AddRefs(dest)); |
4275 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
4276 | return rv; |
4277 | } |
4278 | |
4279 | // null out inappropriate cloned attributes... |
4280 | dest->SetParent(nullptr); |
4281 | dest->SetIsSubFrame(false); |
4282 | |
4283 | return CallQueryInterface(dest, aPageDescriptor); |
4284 | } |
4285 | |
4286 | return NS_ERROR_NOT_AVAILABLE; |
4287 | } |
4288 | |
4289 | already_AddRefed<nsIInputStream> nsDocShell::GetPostDataFromCurrentEntry() |
4290 | const { |
4291 | nsCOMPtr<nsIInputStream> postData; |
4292 | if (mozilla::SessionHistoryInParent()) { |
4293 | if (mActiveEntry) { |
4294 | postData = mActiveEntry->GetPostData(); |
4295 | } else if (mLoadingEntry) { |
4296 | postData = mLoadingEntry->mInfo.GetPostData(); |
4297 | } |
4298 | } else { |
4299 | if (mOSHE) { |
4300 | postData = mOSHE->GetPostData(); |
4301 | } else if (mLSHE) { |
4302 | postData = mLSHE->GetPostData(); |
4303 | } |
4304 | } |
4305 | |
4306 | return postData.forget(); |
4307 | } |
4308 | |
4309 | Maybe<uint32_t> nsDocShell::GetCacheKeyFromCurrentEntry() const { |
4310 | if (mozilla::SessionHistoryInParent()) { |
4311 | if (mActiveEntry) { |
4312 | return Some(mActiveEntry->GetCacheKey()); |
4313 | } |
4314 | |
4315 | if (mLoadingEntry) { |
4316 | return Some(mLoadingEntry->mInfo.GetCacheKey()); |
4317 | } |
4318 | } else { |
4319 | if (mOSHE) { |
4320 | return Some(mOSHE->GetCacheKey()); |
4321 | } |
4322 | |
4323 | if (mLSHE) { |
4324 | return Some(mLSHE->GetCacheKey()); |
4325 | } |
4326 | } |
4327 | |
4328 | return Nothing(); |
4329 | } |
4330 | |
4331 | bool nsDocShell::FillLoadStateFromCurrentEntry( |
4332 | nsDocShellLoadState& aLoadState) { |
4333 | if (mLoadingEntry) { |
4334 | mLoadingEntry->mInfo.FillLoadInfo(aLoadState); |
4335 | return true; |
4336 | } |
4337 | if (mActiveEntry) { |
4338 | mActiveEntry->FillLoadInfo(aLoadState); |
4339 | return true; |
4340 | } |
4341 | return false; |
4342 | } |
4343 | |
4344 | //***************************************************************************** |
4345 | // nsDocShell::nsIBaseWindow |
4346 | //***************************************************************************** |
4347 | |
4348 | NS_IMETHODIMPnsresult |
4349 | nsDocShell::InitWindow(nativeWindow aParentNativeWindow, |
4350 | nsIWidget* aParentWidget, int32_t aX, int32_t aY, |
4351 | int32_t aWidth, int32_t aHeight) { |
4352 | SetParentWidget(aParentWidget); |
4353 | SetPositionAndSize(aX, aY, aWidth, aHeight, 0); |
4354 | 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" , 4354); return NS_ERROR_FAILURE; } } while (false); |
4355 | |
4356 | return NS_OK; |
4357 | } |
4358 | |
4359 | NS_IMETHODIMPnsresult |
4360 | nsDocShell::Destroy() { |
4361 | // XXX: We allow this function to be called just once. If you are going to |
4362 | // reset new variables in this function, please make sure the variables will |
4363 | // never be re-initialized. Adding assertions to check |mIsBeingDestroyed| |
4364 | // in the setter functions for the variables would be enough. |
4365 | if (mIsBeingDestroyed) { |
4366 | return NS_ERROR_DOCSHELL_DYING; |
4367 | } |
4368 | |
4369 | 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" , 4370); MOZ_PretendNoReturn(); } } while (0) |
4370 | "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" , 4370); MOZ_PretendNoReturn(); } } while (0); |
4371 | |
4372 | nsCOMPtr<nsIObserverService> serv = services::GetObserverService(); |
4373 | if (serv) { |
4374 | const char* msg = mItemType == typeContent |
4375 | ? NS_WEBNAVIGATION_DESTROY"webnavigation-destroy" |
4376 | : NS_CHROME_WEBNAVIGATION_DESTROY"chrome-webnavigation-destroy"; |
4377 | serv->NotifyObservers(GetAsSupports(this), msg, nullptr); |
4378 | } |
4379 | |
4380 | mIsBeingDestroyed = true; |
4381 | |
4382 | // Brak the cycle with the initial client, if present. |
4383 | mInitialClientSource.reset(); |
4384 | |
4385 | // Make sure to blow away our mLoadingURI just in case. No loads |
4386 | // from inside this pagehide. |
4387 | mLoadingURI = nullptr; |
4388 | |
4389 | // Fire unload event before we blow anything away. |
4390 | (void)FirePageHideNotification(true); |
4391 | |
4392 | // Clear pointers to any detached nsEditorData that's lying |
4393 | // around in shistory entries. Breaks cycle. See bug 430921. |
4394 | if (mOSHE) { |
4395 | mOSHE->SetEditorData(nullptr); |
4396 | } |
4397 | if (mLSHE) { |
4398 | mLSHE->SetEditorData(nullptr); |
4399 | } |
4400 | |
4401 | // Note: mContentListener can be null if Init() failed and we're being |
4402 | // called from the destructor. |
4403 | if (mContentListener) { |
4404 | mContentListener->DropDocShellReference(); |
4405 | mContentListener->SetParentContentListener(nullptr); |
4406 | // Note that we do NOT set mContentListener to null here; that |
4407 | // way if someone tries to do a load in us after this point |
4408 | // the nsDSURIContentListener will block it. All of which |
4409 | // means that we should do this before calling Stop(), of |
4410 | // course. |
4411 | } |
4412 | |
4413 | // Stop any URLs that are currently being loaded... |
4414 | Stop(nsIWebNavigation::STOP_ALL); |
4415 | |
4416 | mEditorData = nullptr; |
4417 | |
4418 | // Save the state of the current document, before destroying the window. |
4419 | // This is needed to capture the state of a frameset when the new document |
4420 | // causes the frameset to be destroyed... |
4421 | PersistLayoutHistoryState(); |
4422 | |
4423 | // Remove this docshell from its parent's child list |
4424 | nsCOMPtr<nsIDocShellTreeItem> docShellParentAsItem = |
4425 | do_QueryInterface(GetAsSupports(mParent)); |
4426 | if (docShellParentAsItem) { |
4427 | docShellParentAsItem->RemoveChild(this); |
4428 | } |
4429 | |
4430 | if (mDocumentViewer) { |
4431 | mDocumentViewer->Close(nullptr); |
4432 | mDocumentViewer->Destroy(); |
4433 | mDocumentViewer = nullptr; |
4434 | } |
4435 | |
4436 | nsDocLoader::Destroy(); |
4437 | |
4438 | mParentWidget = nullptr; |
4439 | SetCurrentURIInternal(nullptr); |
4440 | |
4441 | if (mScriptGlobal) { |
4442 | mScriptGlobal->DetachFromDocShell(!mWillChangeProcess); |
4443 | mScriptGlobal = nullptr; |
4444 | } |
4445 | |
4446 | if (GetSessionHistory()) { |
4447 | // We want to destroy these content viewers now rather than |
4448 | // letting their destruction wait for the session history |
4449 | // entries to get garbage collected. (Bug 488394) |
4450 | GetSessionHistory()->EvictLocalDocumentViewers(); |
4451 | } |
4452 | |
4453 | if (mWillChangeProcess && !mBrowsingContext->IsDiscarded()) { |
4454 | mBrowsingContext->PrepareForProcessChange(); |
4455 | } |
4456 | |
4457 | SetTreeOwner(nullptr); |
4458 | |
4459 | mBrowserChild = nullptr; |
4460 | |
4461 | mChromeEventHandler = nullptr; |
4462 | |
4463 | // Cancel any timers that were set for this docshell; this is needed |
4464 | // to break the cycle between us and the timers. |
4465 | CancelRefreshURITimers(); |
4466 | |
4467 | return NS_OK; |
4468 | } |
4469 | |
4470 | double nsDocShell::GetWidgetCSSToDeviceScale() { |
4471 | if (mParentWidget) { |
4472 | return mParentWidget->GetDefaultScale().scale; |
4473 | } |
4474 | if (nsCOMPtr<nsIBaseWindow> ownerWindow = do_QueryInterface(mTreeOwner)) { |
4475 | return ownerWindow->GetWidgetCSSToDeviceScale(); |
4476 | } |
4477 | return 1.0; |
4478 | } |
4479 | |
4480 | NS_IMETHODIMPnsresult |
4481 | nsDocShell::GetDevicePixelsPerDesktopPixel(double* aScale) { |
4482 | if (mParentWidget) { |
4483 | *aScale = mParentWidget->GetDesktopToDeviceScale().scale; |
4484 | return NS_OK; |
4485 | } |
4486 | |
4487 | nsCOMPtr<nsIBaseWindow> ownerWindow(do_QueryInterface(mTreeOwner)); |
4488 | if (ownerWindow) { |
4489 | return ownerWindow->GetDevicePixelsPerDesktopPixel(aScale); |
4490 | } |
4491 | |
4492 | *aScale = 1.0; |
4493 | return NS_OK; |
4494 | } |
4495 | |
4496 | NS_IMETHODIMPnsresult |
4497 | nsDocShell::SetPosition(int32_t aX, int32_t aY) { |
4498 | mBounds.MoveTo(aX, aY); |
4499 | |
4500 | if (mDocumentViewer) { |
4501 | 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" , 4501); return NS_ERROR_FAILURE; } } while (false); |
4502 | } |
4503 | |
4504 | return NS_OK; |
4505 | } |
4506 | |
4507 | NS_IMETHODIMPnsresult |
4508 | nsDocShell::SetPositionDesktopPix(int32_t aX, int32_t aY) { |
4509 | nsCOMPtr<nsIBaseWindow> ownerWindow(do_QueryInterface(mTreeOwner)); |
4510 | if (ownerWindow) { |
4511 | return ownerWindow->SetPositionDesktopPix(aX, aY); |
4512 | } |
4513 | |
4514 | double scale = 1.0; |
4515 | GetDevicePixelsPerDesktopPixel(&scale); |
4516 | return SetPosition(NSToIntRound(aX * scale), NSToIntRound(aY * scale)); |
4517 | } |
4518 | |
4519 | NS_IMETHODIMPnsresult |
4520 | nsDocShell::GetPosition(int32_t* aX, int32_t* aY) { |
4521 | return GetPositionAndSize(aX, aY, nullptr, nullptr); |
4522 | } |
4523 | |
4524 | NS_IMETHODIMPnsresult |
4525 | nsDocShell::SetSize(int32_t aWidth, int32_t aHeight, bool aRepaint) { |
4526 | int32_t x = 0, y = 0; |
4527 | GetPosition(&x, &y); |
4528 | return SetPositionAndSize(x, y, aWidth, aHeight, |
4529 | aRepaint ? nsIBaseWindow::eRepaint : 0); |
4530 | } |
4531 | |
4532 | NS_IMETHODIMPnsresult |
4533 | nsDocShell::GetSize(int32_t* aWidth, int32_t* aHeight) { |
4534 | return GetPositionAndSize(nullptr, nullptr, aWidth, aHeight); |
4535 | } |
4536 | |
4537 | NS_IMETHODIMPnsresult |
4538 | nsDocShell::SetPositionAndSize(int32_t aX, int32_t aY, int32_t aWidth, |
4539 | int32_t aHeight, uint32_t aFlags) { |
4540 | mBounds.SetRect(aX, aY, aWidth, aHeight); |
4541 | |
4542 | // Hold strong ref, since SetBounds can make us null out mDocumentViewer |
4543 | nsCOMPtr<nsIDocumentViewer> viewer = mDocumentViewer; |
4544 | if (viewer) { |
4545 | uint32_t cvflags = (aFlags & nsIBaseWindow::eDelayResize) |
4546 | ? nsIDocumentViewer::eDelayResize |
4547 | : 0; |
4548 | // XXX Border figured in here or is that handled elsewhere? |
4549 | nsresult rv = viewer->SetBoundsWithFlags(mBounds, cvflags); |
4550 | 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" , 4550); return NS_ERROR_FAILURE; } } while (false); |
4551 | } |
4552 | |
4553 | return NS_OK; |
4554 | } |
4555 | |
4556 | NS_IMETHODIMPnsresult |
4557 | nsDocShell::GetPositionAndSize(int32_t* aX, int32_t* aY, int32_t* aWidth, |
4558 | int32_t* aHeight) { |
4559 | if (mParentWidget) { |
4560 | // ensure size is up-to-date if window has changed resolution |
4561 | LayoutDeviceIntRect r = mParentWidget->GetClientBounds(); |
4562 | SetPositionAndSize(mBounds.X(), mBounds.Y(), r.Width(), r.Height(), 0); |
4563 | } |
4564 | |
4565 | // We should really consider just getting this information from |
4566 | // our window instead of duplicating the storage and code... |
4567 | if (aWidth || aHeight) { |
4568 | // Caller wants to know our size; make sure to give them up to |
4569 | // date information. |
4570 | RefPtr<Document> doc(do_GetInterface(GetAsSupports(mParent))); |
4571 | if (doc) { |
4572 | doc->FlushPendingNotifications(FlushType::Layout); |
4573 | } |
4574 | } |
4575 | |
4576 | DoGetPositionAndSize(aX, aY, aWidth, aHeight); |
4577 | return NS_OK; |
4578 | } |
4579 | |
4580 | void nsDocShell::DoGetPositionAndSize(int32_t* aX, int32_t* aY, int32_t* aWidth, |
4581 | int32_t* aHeight) { |
4582 | if (aX) { |
4583 | *aX = mBounds.X(); |
4584 | } |
4585 | if (aY) { |
4586 | *aY = mBounds.Y(); |
4587 | } |
4588 | if (aWidth) { |
4589 | *aWidth = mBounds.Width(); |
4590 | } |
4591 | if (aHeight) { |
4592 | *aHeight = mBounds.Height(); |
4593 | } |
4594 | } |
4595 | |
4596 | NS_IMETHODIMPnsresult |
4597 | nsDocShell::SetDimensions(DimensionRequest&& aRequest) { |
4598 | return NS_ERROR_NOT_IMPLEMENTED; |
4599 | } |
4600 | |
4601 | NS_IMETHODIMPnsresult |
4602 | nsDocShell::GetDimensions(DimensionKind aDimensionKind, int32_t* aX, |
4603 | int32_t* aY, int32_t* aCX, int32_t* aCY) { |
4604 | return NS_ERROR_NOT_IMPLEMENTED; |
4605 | } |
4606 | |
4607 | NS_IMETHODIMPnsresult |
4608 | nsDocShell::Repaint(bool aForce) { |
4609 | PresShell* presShell = GetPresShell(); |
4610 | 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" , 4610); return NS_ERROR_FAILURE; } } while (false); |
4611 | |
4612 | RefPtr<nsViewManager> viewManager = presShell->GetViewManager(); |
4613 | 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" , 4613); return NS_ERROR_FAILURE; } } while (false); |
4614 | |
4615 | viewManager->InvalidateAllViews(); |
4616 | return NS_OK; |
4617 | } |
4618 | |
4619 | NS_IMETHODIMPnsresult |
4620 | nsDocShell::GetParentWidget(nsIWidget** aParentWidget) { |
4621 | 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" , 4621); return NS_ERROR_INVALID_POINTER; } } while (false); |
4622 | |
4623 | *aParentWidget = mParentWidget; |
4624 | NS_IF_ADDREF(*aParentWidget)ns_if_addref(*aParentWidget); |
4625 | |
4626 | return NS_OK; |
4627 | } |
4628 | |
4629 | NS_IMETHODIMPnsresult |
4630 | nsDocShell::SetParentWidget(nsIWidget* aParentWidget) { |
4631 | 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" , 4631); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mIsBeingDestroyed" ")"); do { *((volatile int*)__null) = 4631; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
4632 | mParentWidget = aParentWidget; |
4633 | |
4634 | return NS_OK; |
4635 | } |
4636 | |
4637 | NS_IMETHODIMPnsresult |
4638 | nsDocShell::GetParentNativeWindow(nativeWindow* aParentNativeWindow) { |
4639 | 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" , 4639); return NS_ERROR_INVALID_POINTER; } } while (false); |
4640 | |
4641 | if (mParentWidget) { |
4642 | *aParentNativeWindow = mParentWidget->GetNativeData(NS_NATIVE_WIDGET3); |
4643 | } else { |
4644 | *aParentNativeWindow = nullptr; |
4645 | } |
4646 | |
4647 | return NS_OK; |
4648 | } |
4649 | |
4650 | NS_IMETHODIMPnsresult |
4651 | nsDocShell::SetParentNativeWindow(nativeWindow aParentNativeWindow) { |
4652 | return NS_ERROR_NOT_IMPLEMENTED; |
4653 | } |
4654 | |
4655 | NS_IMETHODIMPnsresult |
4656 | nsDocShell::GetNativeHandle(nsAString& aNativeHandle) { |
4657 | // the nativeHandle should be accessed from nsIAppWindow |
4658 | return NS_ERROR_NOT_IMPLEMENTED; |
4659 | } |
4660 | |
4661 | NS_IMETHODIMPnsresult |
4662 | nsDocShell::GetVisibility(bool* aVisibility) { |
4663 | 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" , 4663); return NS_ERROR_INVALID_POINTER; } } while (false); |
4664 | |
4665 | *aVisibility = false; |
4666 | |
4667 | if (!mDocumentViewer) { |
4668 | return NS_OK; |
4669 | } |
4670 | |
4671 | PresShell* presShell = GetPresShell(); |
4672 | if (!presShell) { |
4673 | return NS_OK; |
4674 | } |
4675 | |
4676 | // get the view manager |
4677 | nsViewManager* vm = presShell->GetViewManager(); |
4678 | 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" , 4678); return NS_ERROR_FAILURE; } } while (false); |
4679 | |
4680 | // get the root view |
4681 | nsView* view = vm->GetRootView(); // views are not ref counted |
4682 | 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" , 4682); return NS_ERROR_FAILURE; } } while (false); |
4683 | |
4684 | // if our root view is hidden, we are not visible |
4685 | if (view->GetVisibility() == ViewVisibility::Hide) { |
4686 | return NS_OK; |
4687 | } |
4688 | |
4689 | // otherwise, we must walk up the document and view trees checking |
4690 | // for a hidden view, unless we're an off screen browser, which |
4691 | // would make this test meaningless. |
4692 | |
4693 | RefPtr<nsDocShell> docShell = this; |
4694 | RefPtr<nsDocShell> parentItem = docShell->GetInProcessParentDocshell(); |
4695 | while (parentItem) { |
4696 | // Null-check for crash in bug 267804 |
4697 | if (!parentItem->GetPresShell()) { |
4698 | 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" , 4698); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: " "parent docshell has null pres shell" ")"); do { *((volatile int*)__null) = 4698; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
4699 | return NS_OK; |
4700 | } |
4701 | |
4702 | vm = docShell->GetPresShell()->GetViewManager(); |
4703 | if (vm) { |
4704 | view = vm->GetRootView(); |
4705 | } |
4706 | |
4707 | if (view) { |
4708 | view = view->GetParent(); // anonymous inner view |
4709 | if (view) { |
4710 | view = view->GetParent(); // subdocumentframe's view |
4711 | } |
4712 | } |
4713 | |
4714 | nsIFrame* frame = view ? view->GetFrame() : nullptr; |
4715 | if (frame && !frame->IsVisibleConsideringAncestors( |
4716 | nsIFrame::VISIBILITY_CROSS_CHROME_CONTENT_BOUNDARY)) { |
4717 | return NS_OK; |
4718 | } |
4719 | |
4720 | docShell = parentItem; |
4721 | parentItem = docShell->GetInProcessParentDocshell(); |
4722 | } |
4723 | |
4724 | nsCOMPtr<nsIBaseWindow> treeOwnerAsWin(do_QueryInterface(mTreeOwner)); |
4725 | if (!treeOwnerAsWin) { |
4726 | *aVisibility = true; |
4727 | return NS_OK; |
4728 | } |
4729 | |
4730 | // Check with the tree owner as well to give embedders a chance to |
4731 | // expose visibility as well. |
4732 | nsresult rv = treeOwnerAsWin->GetVisibility(aVisibility); |
4733 | if (rv == NS_ERROR_NOT_IMPLEMENTED) { |
4734 | // The tree owner had no opinion on our visibility. |
4735 | *aVisibility = true; |
4736 | return NS_OK; |
4737 | } |
4738 | return rv; |
4739 | } |
4740 | |
4741 | void nsDocShell::ActivenessMaybeChanged() { |
4742 | const bool isActive = mBrowsingContext->IsActive(); |
4743 | if (RefPtr<PresShell> presShell = GetPresShell()) { |
4744 | presShell->ActivenessMaybeChanged(); |
4745 | } |
4746 | |
4747 | // Tell the window about it |
4748 | if (mScriptGlobal) { |
4749 | mScriptGlobal->SetIsBackground(!isActive); |
4750 | if (RefPtr<Document> doc = mScriptGlobal->GetExtantDoc()) { |
4751 | // Update orientation when the top-level browsing context becomes active. |
4752 | if (isActive && mBrowsingContext->IsTop()) { |
4753 | // We only care about the top-level browsing context. |
4754 | auto orientation = mBrowsingContext->GetOrientationLock(); |
4755 | ScreenOrientation::UpdateActiveOrientationLock(orientation); |
4756 | } |
4757 | |
4758 | doc->PostVisibilityUpdateEvent(); |
4759 | } |
4760 | } |
4761 | |
4762 | // Tell the nsDOMNavigationTiming about it |
4763 | RefPtr<nsDOMNavigationTiming> timing = mTiming; |
4764 | if (!timing && mDocumentViewer) { |
4765 | if (Document* doc = mDocumentViewer->GetDocument()) { |
4766 | timing = doc->GetNavigationTiming(); |
4767 | } |
4768 | } |
4769 | if (timing) { |
4770 | timing->NotifyDocShellStateChanged( |
4771 | isActive ? nsDOMNavigationTiming::DocShellState::eActive |
4772 | : nsDOMNavigationTiming::DocShellState::eInactive); |
4773 | } |
4774 | |
4775 | // Restart or stop meta refresh timers if necessary |
4776 | if (mDisableMetaRefreshWhenInactive) { |
4777 | if (isActive) { |
4778 | ResumeRefreshURIs(); |
4779 | } else { |
4780 | SuspendRefreshURIs(); |
4781 | } |
4782 | } |
4783 | |
4784 | if (InputTaskManager::CanSuspendInputEvent()) { |
4785 | mBrowsingContext->Group()->UpdateInputTaskManagerIfNeeded(isActive); |
4786 | } |
4787 | } |
4788 | |
4789 | NS_IMETHODIMPnsresult |
4790 | nsDocShell::SetDefaultLoadFlags(uint32_t aDefaultLoadFlags) { |
4791 | if (!mWillChangeProcess) { |
4792 | // Intentionally ignoring handling discarded browsing contexts. |
4793 | Unused << mBrowsingContext->SetDefaultLoadFlags(aDefaultLoadFlags); |
4794 | } else { |
4795 | // Bug 1623565: DevTools tries to clean up defaultLoadFlags on |
4796 | // shutdown. Sorry DevTools, your DocShell is in another process. |
4797 | 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" , 4797); |
4798 | } |
4799 | return NS_OK; |
4800 | } |
4801 | |
4802 | NS_IMETHODIMPnsresult |
4803 | nsDocShell::GetDefaultLoadFlags(uint32_t* aDefaultLoadFlags) { |
4804 | *aDefaultLoadFlags = mBrowsingContext->GetDefaultLoadFlags(); |
4805 | return NS_OK; |
4806 | } |
4807 | |
4808 | NS_IMETHODIMPnsresult |
4809 | nsDocShell::GetFailedChannel(nsIChannel** aFailedChannel) { |
4810 | 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" , 4810); return NS_ERROR_INVALID_POINTER; } } while (false); |
4811 | Document* doc = GetDocument(); |
4812 | if (!doc) { |
4813 | *aFailedChannel = nullptr; |
4814 | return NS_OK; |
4815 | } |
4816 | NS_IF_ADDREF(*aFailedChannel = doc->GetFailedChannel())ns_if_addref(*aFailedChannel = doc->GetFailedChannel()); |
4817 | return NS_OK; |
4818 | } |
4819 | |
4820 | NS_IMETHODIMPnsresult |
4821 | nsDocShell::SetVisibility(bool aVisibility) { |
4822 | // Show()/Hide() may change mDocumentViewer. |
4823 | nsCOMPtr<nsIDocumentViewer> viewer = mDocumentViewer; |
4824 | if (!viewer) { |
4825 | return NS_OK; |
4826 | } |
4827 | if (aVisibility) { |
4828 | viewer->Show(); |
4829 | } else { |
4830 | viewer->Hide(); |
4831 | } |
4832 | |
4833 | return NS_OK; |
4834 | } |
4835 | |
4836 | NS_IMETHODIMPnsresult |
4837 | nsDocShell::GetEnabled(bool* aEnabled) { |
4838 | 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" , 4838); return NS_ERROR_INVALID_POINTER; } } while (false); |
4839 | *aEnabled = true; |
4840 | return NS_ERROR_NOT_IMPLEMENTED; |
4841 | } |
4842 | |
4843 | NS_IMETHODIMPnsresult |
4844 | nsDocShell::SetEnabled(bool aEnabled) { return NS_ERROR_NOT_IMPLEMENTED; } |
4845 | |
4846 | NS_IMETHODIMPnsresult |
4847 | nsDocShell::GetMainWidget(nsIWidget** aMainWidget) { |
4848 | // We don't create our own widget, so simply return the parent one. |
4849 | return GetParentWidget(aMainWidget); |
4850 | } |
4851 | |
4852 | NS_IMETHODIMPnsresult |
4853 | nsDocShell::GetTitle(nsAString& aTitle) { |
4854 | aTitle = mTitle; |
4855 | return NS_OK; |
4856 | } |
4857 | |
4858 | NS_IMETHODIMPnsresult |
4859 | nsDocShell::SetTitle(const nsAString& aTitle) { |
4860 | // Avoid unnecessary updates of the title if the URI and the title haven't |
4861 | // changed. |
4862 | if (mTitleValidForCurrentURI && mTitle == aTitle) { |
4863 | return NS_OK; |
4864 | } |
4865 | |
4866 | // Store local title |
4867 | mTitle = aTitle; |
4868 | mTitleValidForCurrentURI = true; |
4869 | |
4870 | // When title is set on the top object it should then be passed to the |
4871 | // tree owner. |
4872 | if (mBrowsingContext->IsTop()) { |
4873 | nsCOMPtr<nsIBaseWindow> treeOwnerAsWin(do_QueryInterface(mTreeOwner)); |
4874 | if (treeOwnerAsWin) { |
4875 | treeOwnerAsWin->SetTitle(aTitle); |
4876 | } |
4877 | } |
4878 | |
4879 | if (mCurrentURI && mLoadType != LOAD_ERROR_PAGE) { |
4880 | UpdateGlobalHistoryTitle(mCurrentURI); |
4881 | } |
4882 | |
4883 | // Update SessionHistory with the document's title. |
4884 | if (mLoadType != LOAD_BYPASS_HISTORY && mLoadType != LOAD_ERROR_PAGE) { |
4885 | SetTitleOnHistoryEntry(true); |
4886 | } |
4887 | |
4888 | return NS_OK; |
4889 | } |
4890 | |
4891 | void nsDocShell::SetTitleOnHistoryEntry(bool aUpdateEntryInSessionHistory) { |
4892 | if (mOSHE) { |
4893 | mOSHE->SetTitle(mTitle); |
4894 | } |
4895 | |
4896 | if (mActiveEntry && mBrowsingContext) { |
4897 | mActiveEntry->SetTitle(mTitle); |
4898 | if (aUpdateEntryInSessionHistory) { |
4899 | if (XRE_IsParentProcess()) { |
4900 | SessionHistoryEntry* entry = |
4901 | mBrowsingContext->Canonical()->GetActiveSessionHistoryEntry(); |
4902 | if (entry) { |
4903 | entry->SetTitle(mTitle); |
4904 | } |
4905 | } else { |
4906 | mozilla::Unused |
4907 | << ContentChild::GetSingleton()->SendSessionHistoryEntryTitle( |
4908 | mBrowsingContext, mTitle); |
4909 | } |
4910 | } |
4911 | } |
4912 | } |
4913 | |
4914 | nsPoint nsDocShell::GetCurScrollPos() { |
4915 | nsPoint scrollPos; |
4916 | if (ScrollContainerFrame* sf = GetRootScrollContainerFrame()) { |
4917 | scrollPos = sf->GetVisualViewportOffset(); |
4918 | } |
4919 | return scrollPos; |
4920 | } |
4921 | |
4922 | nsresult nsDocShell::SetCurScrollPosEx(int32_t aCurHorizontalPos, |
4923 | int32_t aCurVerticalPos) { |
4924 | ScrollContainerFrame* sf = GetRootScrollContainerFrame(); |
4925 | 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" , 4925); return NS_ERROR_FAILURE; } } while (false); |
4926 | |
4927 | ScrollMode scrollMode = |
4928 | sf->IsSmoothScroll() ? ScrollMode::SmoothMsd : ScrollMode::Instant; |
4929 | |
4930 | nsPoint targetPos(aCurHorizontalPos, aCurVerticalPos); |
4931 | sf->ScrollTo(targetPos, scrollMode); |
4932 | |
4933 | // Set the visual viewport offset as well. |
4934 | |
4935 | RefPtr<PresShell> presShell = GetPresShell(); |
4936 | 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" , 4936); return NS_ERROR_FAILURE; } } while (false); |
4937 | |
4938 | nsPresContext* presContext = presShell->GetPresContext(); |
4939 | 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" , 4939); return NS_ERROR_FAILURE; } } while (false); |
4940 | |
4941 | // Only the root content document can have a distinct visual viewport offset. |
4942 | if (!presContext->IsRootContentDocumentCrossProcess()) { |
4943 | return NS_OK; |
4944 | } |
4945 | |
4946 | // Not on a platform with a distinct visual viewport - don't bother setting |
4947 | // the visual viewport offset. |
4948 | if (!presShell->IsVisualViewportSizeSet()) { |
4949 | return NS_OK; |
4950 | } |
4951 | |
4952 | presShell->ScrollToVisual(targetPos, layers::FrameMetrics::eMainThread, |
4953 | scrollMode); |
4954 | |
4955 | return NS_OK; |
4956 | } |
4957 | |
4958 | void nsDocShell::SetScrollbarPreference(mozilla::ScrollbarPreference aPref) { |
4959 | if (mScrollbarPref == aPref) { |
4960 | return; |
4961 | } |
4962 | mScrollbarPref = aPref; |
4963 | auto* ps = GetPresShell(); |
4964 | if (!ps) { |
4965 | return; |
4966 | } |
4967 | nsIFrame* rootScrollContainerFrame = ps->GetRootScrollContainerFrame(); |
4968 | if (!rootScrollContainerFrame) { |
4969 | return; |
4970 | } |
4971 | ps->FrameNeedsReflow(rootScrollContainerFrame, |
4972 | IntrinsicDirty::FrameAncestorsAndDescendants, |
4973 | NS_FRAME_IS_DIRTY); |
4974 | } |
4975 | |
4976 | //***************************************************************************** |
4977 | // nsDocShell::nsIRefreshURI |
4978 | //***************************************************************************** |
4979 | |
4980 | NS_IMETHODIMPnsresult |
4981 | nsDocShell::RefreshURI(nsIURI* aURI, nsIPrincipal* aPrincipal, |
4982 | uint32_t aDelay) { |
4983 | 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" , 4983); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mIsBeingDestroyed" ")"); do { *((volatile int*)__null) = 4983; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
4984 | |
4985 | 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" , 4985); return NS_ERROR_INVALID_ARG; } } while (false); |
4986 | |
4987 | /* Check if Meta refresh/redirects are permitted. Some |
4988 | * embedded applications may not want to do this. |
4989 | * Must do this before sending out NOTIFY_REFRESH events |
4990 | * because listeners may have side effects (e.g. displaying a |
4991 | * button to manually trigger the refresh later). |
4992 | */ |
4993 | bool allowRedirects = true; |
4994 | GetAllowMetaRedirects(&allowRedirects); |
4995 | if (!allowRedirects) { |
4996 | return NS_OK; |
4997 | } |
4998 | |
4999 | // If any web progress listeners are listening for NOTIFY_REFRESH events, |
5000 | // give them a chance to block this refresh. |
5001 | bool sameURI; |
5002 | nsresult rv = aURI->Equals(mCurrentURI, &sameURI); |
5003 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
5004 | sameURI = false; |
5005 | } |
5006 | if (!RefreshAttempted(this, aURI, aDelay, sameURI)) { |
5007 | return NS_OK; |
5008 | } |
5009 | |
5010 | nsCOMPtr<nsITimerCallback> refreshTimer = |
5011 | new nsRefreshTimer(this, aURI, aPrincipal, aDelay); |
5012 | |
5013 | BusyFlags busyFlags = GetBusyFlags(); |
5014 | |
5015 | if (!mRefreshURIList) { |
5016 | mRefreshURIList = nsArray::Create(); |
5017 | } |
5018 | |
5019 | if (busyFlags & BUSY_FLAGS_BUSY || |
5020 | (!mBrowsingContext->IsActive() && mDisableMetaRefreshWhenInactive)) { |
5021 | // We don't want to create the timer right now. Instead queue up the |
5022 | // request and trigger the timer in EndPageLoad() or whenever we become |
5023 | // active. |
5024 | mRefreshURIList->AppendElement(refreshTimer); |
5025 | } else { |
5026 | // There is no page loading going on right now. Create the |
5027 | // timer and fire it right away. |
5028 | nsCOMPtr<nsPIDOMWindowOuter> win = GetWindow(); |
5029 | 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" , 5029); return NS_ERROR_FAILURE; } } while (false); |
5030 | |
5031 | nsCOMPtr<nsITimer> timer; |
5032 | 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) |
5033 | 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); |
5034 | |
5035 | mRefreshURIList->AppendElement(timer); // owning timer ref |
5036 | } |
5037 | return NS_OK; |
5038 | } |
5039 | |
5040 | nsresult nsDocShell::ForceRefreshURIFromTimer(nsIURI* aURI, |
5041 | nsIPrincipal* aPrincipal, |
5042 | uint32_t aDelay, |
5043 | nsITimer* aTimer) { |
5044 | 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" , 5044); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aTimer" ") (" "Must have a timer here" ")"); do { *((volatile int*)__null) = 5044; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
5045 | |
5046 | // Remove aTimer from mRefreshURIList if needed |
5047 | if (mRefreshURIList) { |
5048 | uint32_t n = 0; |
5049 | mRefreshURIList->GetLength(&n); |
5050 | |
5051 | for (uint32_t i = 0; i < n; ++i) { |
5052 | nsCOMPtr<nsITimer> timer = do_QueryElementAt(mRefreshURIList, i); |
5053 | if (timer == aTimer) { |
5054 | mRefreshURIList->RemoveElementAt(i); |
5055 | break; |
5056 | } |
5057 | } |
5058 | } |
5059 | |
5060 | return ForceRefreshURI(aURI, aPrincipal, aDelay); |
5061 | } |
5062 | |
5063 | NS_IMETHODIMPnsresult |
5064 | nsDocShell::ForceRefreshURI(nsIURI* aURI, nsIPrincipal* aPrincipal, |
5065 | uint32_t aDelay) { |
5066 | 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" , 5066); return NS_ERROR_INVALID_ARG; } } while (false); |
5067 | |
5068 | RefPtr<nsDocShellLoadState> loadState = new nsDocShellLoadState(aURI); |
5069 | loadState->SetOriginalURI(mCurrentURI); |
5070 | loadState->SetResultPrincipalURI(aURI); |
5071 | loadState->SetResultPrincipalURIIsSome(true); |
5072 | loadState->SetKeepResultPrincipalURIIfSet(true); |
5073 | loadState->SetIsMetaRefresh(true); |
5074 | |
5075 | // Set the triggering pricipal to aPrincipal if available, or current |
5076 | // document's principal otherwise. |
5077 | nsCOMPtr<nsIPrincipal> principal = aPrincipal; |
5078 | RefPtr<Document> doc = GetDocument(); |
5079 | if (!principal) { |
5080 | if (!doc) { |
5081 | return NS_ERROR_FAILURE; |
5082 | } |
5083 | principal = doc->NodePrincipal(); |
5084 | } |
5085 | loadState->SetTriggeringPrincipal(principal); |
5086 | if (doc) { |
5087 | loadState->SetCsp(doc->GetCsp()); |
5088 | loadState->SetHasValidUserGestureActivation( |
5089 | doc->HasValidTransientUserGestureActivation()); |
5090 | |
5091 | loadState->SetTextDirectiveUserActivation( |
5092 | doc->ConsumeTextDirectiveUserActivation() || |
5093 | loadState->HasValidUserGestureActivation()); |
5094 | loadState->SetTriggeringSandboxFlags(doc->GetSandboxFlags()); |
5095 | loadState->SetTriggeringWindowId(doc->InnerWindowID()); |
5096 | loadState->SetTriggeringStorageAccess(doc->UsingStorageAccess()); |
5097 | } |
5098 | |
5099 | loadState->SetPrincipalIsExplicit(true); |
5100 | |
5101 | /* Check if this META refresh causes a redirection |
5102 | * to another site. |
5103 | */ |
5104 | bool equalUri = false; |
5105 | nsresult rv = aURI->Equals(mCurrentURI, &equalUri); |
5106 | |
5107 | nsCOMPtr<nsIReferrerInfo> referrerInfo; |
5108 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && !equalUri && aDelay <= REFRESH_REDIRECT_TIMER15000) { |
5109 | /* It is a META refresh based redirection within the threshold time |
5110 | * we have in mind (15000 ms as defined by REFRESH_REDIRECT_TIMER). |
5111 | * Pass a REPLACE flag to LoadURI(). |
5112 | */ |
5113 | loadState->SetLoadType(LOAD_REFRESH_REPLACE); |
5114 | |
5115 | /* For redirects we mimic HTTP, which passes the |
5116 | * original referrer. |
5117 | * We will pass in referrer but will not send to server |
5118 | */ |
5119 | if (mReferrerInfo) { |
5120 | referrerInfo = static_cast<ReferrerInfo*>(mReferrerInfo.get()) |
5121 | ->CloneWithNewSendReferrer(false); |
5122 | } |
5123 | } else { |
5124 | loadState->SetLoadType(LOAD_REFRESH); |
5125 | /* We do need to pass in a referrer, but we don't want it to |
5126 | * be sent to the server. |
5127 | * For most refreshes the current URI is an appropriate |
5128 | * internal referrer. |
5129 | */ |
5130 | referrerInfo = new ReferrerInfo(mCurrentURI, ReferrerPolicy::_empty, false); |
5131 | } |
5132 | |
5133 | loadState->SetReferrerInfo(referrerInfo); |
5134 | loadState->SetLoadFlags( |
5135 | nsIWebNavigation::LOAD_FLAGS_DISALLOW_INHERIT_PRINCIPAL); |
5136 | loadState->SetFirstParty(true); |
5137 | |
5138 | /* |
5139 | * LoadURI(...) will cancel all refresh timers... This causes the |
5140 | * Timer and its refreshData instance to be released... |
5141 | */ |
5142 | LoadURI(loadState, false); |
5143 | |
5144 | return NS_OK; |
5145 | } |
5146 | |
5147 | static const char16_t* SkipASCIIWhitespace(const char16_t* aStart, |
5148 | const char16_t* aEnd) { |
5149 | const char16_t* iter = aStart; |
5150 | while (iter != aEnd && mozilla::IsAsciiWhitespace(*iter)) { |
5151 | ++iter; |
5152 | } |
5153 | return iter; |
5154 | } |
5155 | |
5156 | static std::tuple<const char16_t*, const char16_t*> ExtractURLString( |
5157 | const char16_t* aPosition, const char16_t* aEnd) { |
5158 | 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" , 5158); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPosition != aEnd" ")"); do { *((volatile int*)__null) = 5158; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
5159 | |
5160 | // 1. Let urlString be the substring of input from the code point at |
5161 | // position to the end of the string. |
5162 | const char16_t* urlStart = aPosition; |
5163 | const char16_t* urlEnd = aEnd; |
5164 | |
5165 | // 2. If the code point in input pointed to by position is U+0055 (U) or |
5166 | // U+0075 (u), then advance position to the next code point. |
5167 | // Otherwise, jump to the step labeled skip quotes. |
5168 | if (*aPosition == 'U' || *aPosition == 'u') { |
5169 | ++aPosition; |
5170 | |
5171 | // 3. If the code point in input pointed to by position is U+0052 (R) or |
5172 | // U+0072 (r), then advance position to the next code point. |
5173 | // Otherwise, jump to the step labeled parse. |
5174 | if (aPosition == aEnd || (*aPosition != 'R' && *aPosition != 'r')) { |
5175 | return std::make_tuple(urlStart, urlEnd); |
5176 | } |
5177 | |
5178 | ++aPosition; |
5179 | |
5180 | // 4. If the code point in input pointed to by position is U+004C (L) or |
5181 | // U+006C (l), then advance position to the next code point. |
5182 | // Otherwise, jump to the step labeled parse. |
5183 | if (aPosition == aEnd || (*aPosition != 'L' && *aPosition != 'l')) { |
5184 | return std::make_tuple(urlStart, urlEnd); |
5185 | } |
5186 | |
5187 | ++aPosition; |
5188 | |
5189 | // 5. Skip ASCII whitespace within input given position. |
5190 | aPosition = SkipASCIIWhitespace(aPosition, aEnd); |
5191 | |
5192 | // 6. If the code point in input pointed to by position is U+003D (=), |
5193 | // then advance position to the next code point. Otherwise, jump to |
5194 | // the step labeled parse. |
5195 | if (aPosition == aEnd || *aPosition != '=') { |
5196 | return std::make_tuple(urlStart, urlEnd); |
5197 | } |
5198 | |
5199 | ++aPosition; |
5200 | |
5201 | // 7. Skip ASCII whitespace within input given position. |
5202 | aPosition = SkipASCIIWhitespace(aPosition, aEnd); |
5203 | } |
5204 | |
5205 | // 8. Skip quotes: If the code point in input pointed to by position is |
5206 | // U+0027 (') or U+0022 ("), then let quote be that code point, and |
5207 | // advance position to the next code point. Otherwise, let quote be |
5208 | // the empty string. |
5209 | Maybe<char> quote; |
5210 | if (aPosition != aEnd && (*aPosition == '\'' || *aPosition == '"')) { |
5211 | quote.emplace(*aPosition); |
5212 | ++aPosition; |
5213 | } |
5214 | |
5215 | // 9. Set urlString to the substring of input from the code point at |
5216 | // position to the end of the string. |
5217 | urlStart = aPosition; |
5218 | urlEnd = aEnd; |
5219 | |
5220 | // 10. If quote is not the empty string, and there is a code point in |
5221 | // urlString equal to quote, then truncate urlString at that code |
5222 | // point, so that it and all subsequent code points are removed. |
5223 | const char16_t* quotePos; |
5224 | if (quote.isSome() && |
5225 | (quotePos = nsCharTraits<char16_t>::find( |
5226 | urlStart, std::distance(urlStart, aEnd), quote.value()))) { |
5227 | urlEnd = quotePos; |
5228 | } |
5229 | |
5230 | return std::make_tuple(urlStart, urlEnd); |
5231 | } |
5232 | |
5233 | void nsDocShell::SetupRefreshURIFromHeader(Document* aDocument, |
5234 | const nsAString& aHeader) { |
5235 | if (mIsBeingDestroyed) { |
5236 | return; |
5237 | } |
5238 | |
5239 | const char16_t* position = aHeader.BeginReading(); |
5240 | const char16_t* end = aHeader.EndReading(); |
5241 | |
5242 | // See |
5243 | // https://html.spec.whatwg.org/#pragma-directives:shared-declarative-refresh-steps. |
5244 | |
5245 | // 3. Skip ASCII whitespace |
5246 | position = SkipASCIIWhitespace(position, end); |
5247 | |
5248 | // 4. Let time be 0. |
5249 | CheckedInt<uint32_t> milliSeconds; |
5250 | |
5251 | // 5. Collect a sequence of code points that are ASCII digits |
5252 | const char16_t* digitsStart = position; |
5253 | while (position != end && mozilla::IsAsciiDigit(*position)) { |
5254 | ++position; |
5255 | } |
5256 | |
5257 | if (position == digitsStart) { |
5258 | // 6. If timeString is the empty string, then: |
5259 | // 1. If the code point in input pointed to by position is not U+002E |
5260 | // (.), then return. |
5261 | if (position == end || *position != '.') { |
5262 | return; |
5263 | } |
5264 | } else { |
5265 | // 7. Otherwise, set time to the result of parsing timeString using the |
5266 | // rules for parsing non-negative integers. |
5267 | nsContentUtils::ParseHTMLIntegerResultFlags result; |
5268 | uint32_t seconds = |
5269 | nsContentUtils::ParseHTMLInteger(digitsStart, position, &result); |
5270 | 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" , 5270); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!(result & nsContentUtils::eParseHTMLInteger_Negative)" ")"); do { *((volatile int*)__null) = 5270; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
5271 | if (result & nsContentUtils::eParseHTMLInteger_Error) { |
5272 | // The spec assumes no errors here (since we only pass ASCII digits in), |
5273 | // but we can still overflow, so this block should deal with that (and |
5274 | // only that). |
5275 | 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" , 5275); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!(result & nsContentUtils::eParseHTMLInteger_ErrorOverflow)" ")"); do { *((volatile int*)__null) = 5275; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
5276 | return; |
5277 | } |
5278 | 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" , 5279); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!(result & nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput)" ")"); do { *((volatile int*)__null) = 5279; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
5279 | !(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" , 5279); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!(result & nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput)" ")"); do { *((volatile int*)__null) = 5279; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
5280 | |
5281 | milliSeconds = seconds; |
5282 | milliSeconds *= 1000; |
5283 | if (!milliSeconds.isValid()) { |
5284 | return; |
5285 | } |
5286 | } |
5287 | |
5288 | // 8. Collect a sequence of code points that are ASCII digits and U+002E FULL |
5289 | // STOP characters (.) from input given position. Ignore any collected |
5290 | // characters. |
5291 | while (position != end && |
5292 | (mozilla::IsAsciiDigit(*position) || *position == '.')) { |
5293 | ++position; |
5294 | } |
5295 | |
5296 | // 9. Let urlRecord be document's URL. |
5297 | nsCOMPtr<nsIURI> urlRecord(aDocument->GetDocumentURI()); |
5298 | |
5299 | // 10. If position is not past the end of input |
5300 | if (position != end) { |
5301 | // 1. If the code point in input pointed to by position is not U+003B (;), |
5302 | // U+002C (,), or ASCII whitespace, then return. |
5303 | if (*position != ';' && *position != ',' && |
5304 | !mozilla::IsAsciiWhitespace(*position)) { |
5305 | return; |
5306 | } |
5307 | |
5308 | // 2. Skip ASCII whitespace within input given position. |
5309 | position = SkipASCIIWhitespace(position, end); |
5310 | |
5311 | // 3. If the code point in input pointed to by position is U+003B (;) or |
5312 | // U+002C (,), then advance position to the next code point. |
5313 | if (position != end && (*position == ';' || *position == ',')) { |
5314 | ++position; |
5315 | |
5316 | // 4. Skip ASCII whitespace within input given position. |
5317 | position = SkipASCIIWhitespace(position, end); |
5318 | } |
5319 | |
5320 | // 11. If position is not past the end of input, then: |
5321 | if (position != end) { |
5322 | const char16_t* urlStart; |
5323 | const char16_t* urlEnd; |
5324 | |
5325 | // 1-10. See ExtractURLString. |
5326 | std::tie(urlStart, urlEnd) = ExtractURLString(position, end); |
5327 | |
5328 | // 11. Parse: Parse urlString relative to document. If that fails, return. |
5329 | // Otherwise, set urlRecord to the resulting URL record. |
5330 | nsresult rv = |
5331 | NS_NewURI(getter_AddRefs(urlRecord), |
5332 | Substring(urlStart, std::distance(urlStart, urlEnd)), |
5333 | /* charset = */ nullptr, aDocument->GetDocBaseURI()); |
5334 | 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" , 5334); return; } } while (false); |
5335 | } |
5336 | } |
5337 | |
5338 | nsIPrincipal* principal = aDocument->NodePrincipal(); |
5339 | nsCOMPtr<nsIScriptSecurityManager> securityManager = |
5340 | nsContentUtils::GetSecurityManager(); |
5341 | nsresult rv = securityManager->CheckLoadURIWithPrincipal( |
5342 | principal, urlRecord, |
5343 | nsIScriptSecurityManager::LOAD_IS_AUTOMATIC_DOCUMENT_REPLACEMENT, |
5344 | aDocument->InnerWindowID()); |
5345 | 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" , 5345); return; } } while (false); |
5346 | |
5347 | bool isjs = true; |
5348 | rv = NS_URIChainHasFlags( |
5349 | urlRecord, nsIProtocolHandler::URI_OPENING_EXECUTES_SCRIPT, &isjs); |
5350 | 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" , 5350); return; } } while (false); |
5351 | |
5352 | if (isjs) { |
5353 | return; |
5354 | } |
5355 | |
5356 | RefreshURI(urlRecord, principal, milliSeconds.value()); |
5357 | } |
5358 | |
5359 | static void DoCancelRefreshURITimers(nsIMutableArray* aTimerList) { |
5360 | if (!aTimerList) { |
5361 | return; |
5362 | } |
5363 | |
5364 | uint32_t n = 0; |
5365 | aTimerList->GetLength(&n); |
5366 | |
5367 | while (n) { |
5368 | nsCOMPtr<nsITimer> timer(do_QueryElementAt(aTimerList, --n)); |
5369 | |
5370 | aTimerList->RemoveElementAt(n); // bye bye owning timer ref |
5371 | |
5372 | if (timer) { |
5373 | timer->Cancel(); |
5374 | } |
5375 | } |
5376 | } |
5377 | |
5378 | NS_IMETHODIMPnsresult |
5379 | nsDocShell::CancelRefreshURITimers() { |
5380 | DoCancelRefreshURITimers(mRefreshURIList); |
5381 | DoCancelRefreshURITimers(mSavedRefreshURIList); |
5382 | DoCancelRefreshURITimers(mBFCachedRefreshURIList); |
5383 | mRefreshURIList = nullptr; |
5384 | mSavedRefreshURIList = nullptr; |
5385 | mBFCachedRefreshURIList = nullptr; |
5386 | |
5387 | return NS_OK; |
5388 | } |
5389 | |
5390 | NS_IMETHODIMPnsresult |
5391 | nsDocShell::GetRefreshPending(bool* aResult) { |
5392 | if (!mRefreshURIList) { |
5393 | *aResult = false; |
5394 | return NS_OK; |
5395 | } |
5396 | |
5397 | uint32_t count; |
5398 | nsresult rv = mRefreshURIList->GetLength(&count); |
5399 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) { |
5400 | *aResult = (count != 0); |
5401 | } |
5402 | return rv; |
5403 | } |
5404 | |
5405 | void nsDocShell::RefreshURIToQueue() { |
5406 | if (mRefreshURIList) { |
5407 | uint32_t n = 0; |
5408 | mRefreshURIList->GetLength(&n); |
5409 | |
5410 | for (uint32_t i = 0; i < n; ++i) { |
5411 | nsCOMPtr<nsITimer> timer = do_QueryElementAt(mRefreshURIList, i); |
5412 | if (!timer) { |
5413 | continue; // this must be a nsRefreshURI already |
5414 | } |
5415 | |
5416 | // Replace this timer object with a nsRefreshTimer object. |
5417 | nsCOMPtr<nsITimerCallback> callback; |
5418 | timer->GetCallback(getter_AddRefs(callback)); |
5419 | |
5420 | timer->Cancel(); |
5421 | |
5422 | mRefreshURIList->ReplaceElementAt(callback, i); |
5423 | } |
5424 | } |
5425 | } |
5426 | |
5427 | NS_IMETHODIMPnsresult |
5428 | nsDocShell::SuspendRefreshURIs() { |
5429 | RefreshURIToQueue(); |
5430 | |
5431 | // Suspend refresh URIs for our child shells as well. |
5432 | for (auto* child : mChildList.ForwardRange()) { |
5433 | nsCOMPtr<nsIDocShell> shell = do_QueryObject(child); |
5434 | if (shell) { |
5435 | shell->SuspendRefreshURIs(); |
5436 | } |
5437 | } |
5438 | |
5439 | return NS_OK; |
5440 | } |
5441 | |
5442 | NS_IMETHODIMPnsresult |
5443 | nsDocShell::ResumeRefreshURIs() { |
5444 | RefreshURIFromQueue(); |
5445 | |
5446 | // Resume refresh URIs for our child shells as well. |
5447 | for (auto* child : mChildList.ForwardRange()) { |
5448 | nsCOMPtr<nsIDocShell> shell = do_QueryObject(child); |
5449 | if (shell) { |
5450 | shell->ResumeRefreshURIs(); |
5451 | } |
5452 | } |
5453 | |
5454 | return NS_OK; |
5455 | } |
5456 | |
5457 | nsresult nsDocShell::RefreshURIFromQueue() { |
5458 | if (!mRefreshURIList) { |
5459 | return NS_OK; |
5460 | } |
5461 | uint32_t n = 0; |
5462 | mRefreshURIList->GetLength(&n); |
5463 | |
5464 | while (n) { |
5465 | nsCOMPtr<nsITimerCallback> refreshInfo = |
5466 | do_QueryElementAt(mRefreshURIList, --n); |
5467 | |
5468 | if (refreshInfo) { |
5469 | // This is the nsRefreshTimer object, waiting to be |
5470 | // setup in a timer object and fired. |
5471 | // Create the timer and trigger it. |
5472 | uint32_t delay = static_cast<nsRefreshTimer*>( |
5473 | static_cast<nsITimerCallback*>(refreshInfo)) |
5474 | ->GetDelay(); |
5475 | nsCOMPtr<nsPIDOMWindowOuter> win = GetWindow(); |
5476 | if (win) { |
5477 | nsCOMPtr<nsITimer> timer; |
5478 | NS_NewTimerWithCallback(getter_AddRefs(timer), refreshInfo, delay, |
5479 | nsITimer::TYPE_ONE_SHOT); |
5480 | |
5481 | if (timer) { |
5482 | // Replace the nsRefreshTimer element in the queue with |
5483 | // its corresponding timer object, so that in case another |
5484 | // load comes through before the timer can go off, the timer will |
5485 | // get cancelled in CancelRefreshURITimer() |
5486 | mRefreshURIList->ReplaceElementAt(timer, n); |
5487 | } |
5488 | } |
5489 | } |
5490 | } |
5491 | |
5492 | return NS_OK; |
5493 | } |
5494 | |
5495 | static bool IsFollowupPartOfMultipart(nsIRequest* aRequest) { |
5496 | nsCOMPtr<nsIMultiPartChannel> multiPartChannel = do_QueryInterface(aRequest); |
5497 | bool firstPart = false; |
5498 | return multiPartChannel && |
5499 | NS_SUCCEEDED(multiPartChannel->GetIsFirstPart(&firstPart))((bool)(__builtin_expect(!!(!NS_FAILED_impl(multiPartChannel-> GetIsFirstPart(&firstPart))), 1))) && |
5500 | !firstPart; |
5501 | } |
5502 | |
5503 | nsresult nsDocShell::Embed(nsIDocumentViewer* aDocumentViewer, |
5504 | WindowGlobalChild* aWindowActor, |
5505 | bool aIsTransientAboutBlank, bool aPersist, |
5506 | nsIRequest* aRequest, nsIURI* aPreviousURI) { |
5507 | // Save the LayoutHistoryState of the previous document, before |
5508 | // setting up new document |
5509 | PersistLayoutHistoryState(); |
5510 | |
5511 | nsresult rv = SetupNewViewer(aDocumentViewer, aWindowActor); |
5512 | 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" , 5512); return rv; } } while (false); |
5513 | |
5514 | // XXX What if SetupNewViewer fails? |
5515 | if (mozilla::SessionHistoryInParent() ? !!mLoadingEntry : !!mLSHE) { |
5516 | // Set history.state |
5517 | SetDocCurrentStateObj(mLSHE, |
5518 | mLoadingEntry ? &mLoadingEntry->mInfo : nullptr); |
5519 | } |
5520 | |
5521 | if (mLSHE) { |
5522 | // Restore the editing state, if it's stored in session history. |
5523 | if (mLSHE->HasDetachedEditor()) { |
5524 | ReattachEditorToWindow(mLSHE); |
5525 | } |
5526 | |
5527 | SetHistoryEntryAndUpdateBC(Nothing(), Some<nsISHEntry*>(mLSHE)); |
5528 | } |
5529 | |
5530 | if (!aIsTransientAboutBlank && mozilla::SessionHistoryInParent() && |
5531 | !IsFollowupPartOfMultipart(aRequest)) { |
5532 | bool expired = false; |
5533 | uint32_t cacheKey = 0; |
5534 | nsCOMPtr<nsICacheInfoChannel> cacheChannel = do_QueryInterface(aRequest); |
5535 | if (cacheChannel) { |
5536 | // Check if the page has expired from cache |
5537 | uint32_t expTime = 0; |
5538 | cacheChannel->GetCacheTokenExpirationTime(&expTime); |
5539 | uint32_t now = PRTimeToSeconds(PR_Now()); |
5540 | if (expTime <= now) { |
5541 | expired = true; |
5542 | } |
5543 | |
5544 | // The checks for updating cache key are similar to the old session |
5545 | // history in OnNewURI. Try to update the cache key if |
5546 | // - we should update session history and aren't doing a session |
5547 | // history load. |
5548 | // - we're doing a forced reload. |
5549 | if (((!mLoadingEntry || !mLoadingEntry->mLoadIsFromSessionHistory) && |
5550 | mBrowsingContext->ShouldUpdateSessionHistory(mLoadType)) || |
5551 | IsForceReloadType(mLoadType)) { |
5552 | cacheChannel->GetCacheKey(&cacheKey); |
5553 | } |
5554 | } |
5555 | |
5556 | 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); |
5557 | MoveLoadingToActiveEntry(aPersist, expired, cacheKey, aPreviousURI); |
5558 | } |
5559 | |
5560 | bool updateHistory = true; |
5561 | |
5562 | // Determine if this type of load should update history |
5563 | switch (mLoadType) { |
5564 | case LOAD_NORMAL_REPLACE: |
5565 | case LOAD_REFRESH_REPLACE: |
5566 | case LOAD_STOP_CONTENT_AND_REPLACE: |
5567 | case LOAD_RELOAD_BYPASS_CACHE: |
5568 | case LOAD_RELOAD_BYPASS_PROXY: |
5569 | case LOAD_RELOAD_BYPASS_PROXY_AND_CACHE: |
5570 | case LOAD_REPLACE_BYPASS_CACHE: |
5571 | updateHistory = false; |
5572 | break; |
5573 | default: |
5574 | break; |
5575 | } |
5576 | |
5577 | if (!updateHistory) { |
5578 | SetLayoutHistoryState(nullptr); |
5579 | } |
5580 | |
5581 | return NS_OK; |
5582 | } |
5583 | |
5584 | //***************************************************************************** |
5585 | // nsDocShell::nsIWebProgressListener |
5586 | //***************************************************************************** |
5587 | |
5588 | NS_IMETHODIMPnsresult |
5589 | nsDocShell::OnProgressChange(nsIWebProgress* aProgress, nsIRequest* aRequest, |
5590 | int32_t aCurSelfProgress, int32_t aMaxSelfProgress, |
5591 | int32_t aCurTotalProgress, |
5592 | int32_t aMaxTotalProgress) { |
5593 | return NS_OK; |
5594 | } |
5595 | |
5596 | NS_IMETHODIMPnsresult |
5597 | nsDocShell::OnStateChange(nsIWebProgress* aProgress, nsIRequest* aRequest, |
5598 | uint32_t aStateFlags, nsresult aStatus) { |
5599 | if ((~aStateFlags & (STATE_START | STATE_IS_NETWORK)) == 0) { |
5600 | // Save timing statistics. |
5601 | nsCOMPtr<nsIChannel> channel(do_QueryInterface(aRequest)); |
5602 | nsCOMPtr<nsIURI> uri; |
5603 | channel->GetURI(getter_AddRefs(uri)); |
5604 | nsAutoCString aURI; |
5605 | uri->GetAsciiSpec(aURI); |
5606 | |
5607 | if (this == aProgress) { |
5608 | mozilla::Unused << MaybeInitTiming(); |
5609 | mTiming->NotifyFetchStart(uri, |
5610 | ConvertLoadTypeToNavigationType(mLoadType)); |
5611 | // If we are starting a DocumentChannel, we need to pass the timing |
5612 | // statistics so that should a process switch occur, the starting type can |
5613 | // be passed to the new DocShell running in the other content process. |
5614 | if (RefPtr<DocumentChannel> docChannel = do_QueryObject(aRequest)) { |
5615 | docChannel->SetNavigationTiming(mTiming); |
5616 | } |
5617 | } |
5618 | |
5619 | // Page has begun to load |
5620 | mBusyFlags = (BusyFlags)(BUSY_FLAGS_BUSY | BUSY_FLAGS_BEFORE_PAGE_LOAD); |
5621 | |
5622 | if ((aStateFlags & STATE_RESTORING) == 0) { |
5623 | if (SessionStorePlatformCollection()) { |
5624 | if (IsForceReloadType(mLoadType)) { |
5625 | if (WindowContext* windowContext = |
5626 | mBrowsingContext->GetCurrentWindowContext()) { |
5627 | SessionStoreChild::From(windowContext->GetWindowGlobalChild()) |
5628 | ->ResetSessionStore(mBrowsingContext, |
5629 | mBrowsingContext->GetSessionStoreEpoch()); |
5630 | } |
5631 | } |
5632 | } |
5633 | } |
5634 | } else if ((~aStateFlags & (STATE_TRANSFERRING | STATE_IS_DOCUMENT)) == 0) { |
5635 | // Page is loading |
5636 | mBusyFlags = (BusyFlags)(BUSY_FLAGS_BUSY | BUSY_FLAGS_PAGE_LOADING); |
5637 | } else if ((aStateFlags & STATE_STOP) && (aStateFlags & STATE_IS_NETWORK)) { |
5638 | // Page has finished loading |
5639 | mBusyFlags = BUSY_FLAGS_NONE; |
5640 | } |
5641 | |
5642 | if ((~aStateFlags & (STATE_IS_DOCUMENT | STATE_STOP)) == 0) { |
5643 | nsCOMPtr<nsIWebProgress> webProgress = |
5644 | do_QueryInterface(GetAsSupports(this)); |
5645 | // Is the document stop notification for this document? |
5646 | if (aProgress == webProgress.get()) { |
5647 | nsCOMPtr<nsIChannel> channel(do_QueryInterface(aRequest)); |
5648 | EndPageLoad(aProgress, channel, aStatus); |
5649 | } |
5650 | } |
5651 | // note that redirect state changes will go through here as well, but it |
5652 | // is better to handle those in OnRedirectStateChange where more |
5653 | // information is available. |
5654 | return NS_OK; |
5655 | } |
5656 | |
5657 | NS_IMETHODIMPnsresult |
5658 | nsDocShell::OnLocationChange(nsIWebProgress* aProgress, nsIRequest* aRequest, |
5659 | nsIURI* aURI, uint32_t aFlags) { |
5660 | // Since we've now changed Documents, notify the BrowsingContext that we've |
5661 | // changed. Ideally we'd just let the BrowsingContext do this when it |
5662 | // changes the current window global, but that happens before this and we |
5663 | // have a lot of tests that depend on the specific ordering of messages. |
5664 | bool isTopLevel = false; |
5665 | if (XRE_IsParentProcess() && |
5666 | !(aFlags & nsIWebProgressListener::LOCATION_CHANGE_SAME_DOCUMENT) && |
5667 | NS_SUCCEEDED(aProgress->GetIsTopLevel(&isTopLevel))((bool)(__builtin_expect(!!(!NS_FAILED_impl(aProgress->GetIsTopLevel (&isTopLevel))), 1))) && isTopLevel) { |
5668 | GetBrowsingContext()->Canonical()->UpdateSecurityState(); |
5669 | } |
5670 | return NS_OK; |
5671 | } |
5672 | |
5673 | void nsDocShell::OnRedirectStateChange(nsIChannel* aOldChannel, |
5674 | nsIChannel* aNewChannel, |
5675 | uint32_t aRedirectFlags, |
5676 | uint32_t aStateFlags) { |
5677 | 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" , 5678); MOZ_PretendNoReturn(); } } while (0) |
5678 | "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" , 5678); MOZ_PretendNoReturn(); } } while (0); |
5679 | |
5680 | if (!(aStateFlags & STATE_IS_DOCUMENT)) { |
5681 | return; // not a toplevel document |
5682 | } |
5683 | |
5684 | nsCOMPtr<nsIURI> oldURI, newURI; |
5685 | aOldChannel->GetURI(getter_AddRefs(oldURI)); |
5686 | aNewChannel->GetURI(getter_AddRefs(newURI)); |
5687 | if (!oldURI || !newURI) { |
5688 | return; |
5689 | } |
5690 | |
5691 | // DocumentChannel adds redirect chain to global history in the parent |
5692 | // process. The redirect chain can't be queried from the content process, so |
5693 | // there's no need to update global history here. |
5694 | RefPtr<DocumentChannel> docChannel = do_QueryObject(aOldChannel); |
5695 | if (!docChannel) { |
5696 | // Below a URI visit is saved (see AddURIVisit method doc). |
5697 | // The visit chain looks something like: |
5698 | // ... |
5699 | // Site N - 1 |
5700 | // => Site N |
5701 | // (redirect to =>) Site N + 1 (we are here!) |
5702 | |
5703 | // Get N - 1 and transition type |
5704 | nsCOMPtr<nsIURI> previousURI; |
5705 | uint32_t previousFlags = 0; |
5706 | ExtractLastVisit(aOldChannel, getter_AddRefs(previousURI), &previousFlags); |
5707 | |
5708 | if (aRedirectFlags & nsIChannelEventSink::REDIRECT_INTERNAL || |
5709 | net::ChannelIsPost(aOldChannel)) { |
5710 | // 1. Internal redirects are ignored because they are specific to the |
5711 | // channel implementation. |
5712 | // 2. POSTs are not saved by global history. |
5713 | // |
5714 | // Regardless, we need to propagate the previous visit to the new |
5715 | // channel. |
5716 | SaveLastVisit(aNewChannel, previousURI, previousFlags); |
5717 | } else { |
5718 | // Get the HTTP response code, if available. |
5719 | uint32_t responseStatus = 0; |
5720 | nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aOldChannel); |
5721 | if (httpChannel) { |
5722 | Unused << httpChannel->GetResponseStatus(&responseStatus); |
5723 | } |
5724 | |
5725 | // Add visit N -1 => N |
5726 | AddURIVisit(oldURI, previousURI, previousFlags, responseStatus); |
5727 | |
5728 | // Since N + 1 could be the final destination, we will not save N => N + 1 |
5729 | // here. OnNewURI will do that, so we will cache it. |
5730 | SaveLastVisit(aNewChannel, oldURI, aRedirectFlags); |
5731 | } |
5732 | } |
5733 | |
5734 | if (!(aRedirectFlags & nsIChannelEventSink::REDIRECT_INTERNAL) && |
5735 | mLoadType & (LOAD_CMD_RELOAD | LOAD_CMD_HISTORY)) { |
5736 | mLoadType = LOAD_NORMAL_REPLACE; |
5737 | SetHistoryEntryAndUpdateBC(Some(nullptr), Nothing()); |
5738 | } |
5739 | } |
5740 | |
5741 | NS_IMETHODIMPnsresult |
5742 | nsDocShell::OnStatusChange(nsIWebProgress* aWebProgress, nsIRequest* aRequest, |
5743 | nsresult aStatus, const char16_t* aMessage) { |
5744 | 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" , 5744); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: " "notification excluded in AddProgressListener(...)" ")"); do { *((volatile int*)__null) = 5744; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
5745 | return NS_OK; |
5746 | } |
5747 | |
5748 | NS_IMETHODIMPnsresult |
5749 | nsDocShell::OnSecurityChange(nsIWebProgress* aWebProgress, nsIRequest* aRequest, |
5750 | uint32_t aState) { |
5751 | MOZ_ASSERT_UNREACHABLE("notification excluded in AddProgressListener(...)")do { static_assert( mozilla::detail::AssertionConditionType< decltype(false)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: " "notification excluded in AddProgressListener(...)" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 5751); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: " "notification excluded in AddProgressListener(...)" ")"); do { *((volatile int*)__null) = 5751; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
5752 | return NS_OK; |
5753 | } |
5754 | |
5755 | NS_IMETHODIMPnsresult |
5756 | nsDocShell::OnContentBlockingEvent(nsIWebProgress* aWebProgress, |
5757 | nsIRequest* aRequest, uint32_t aEvent) { |
5758 | 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" , 5758); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: " "notification excluded in AddProgressListener(...)" ")"); do { *((volatile int*)__null) = 5758; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
5759 | return NS_OK; |
5760 | } |
5761 | |
5762 | already_AddRefed<nsIURIFixupInfo> nsDocShell::KeywordToURI( |
5763 | const nsACString& aKeyword, bool aIsPrivateContext) { |
5764 | nsCOMPtr<nsIURIFixupInfo> info; |
5765 | if (!XRE_IsContentProcess()) { |
5766 | nsCOMPtr<nsIURIFixup> uriFixup = components::URIFixup::Service(); |
5767 | if (uriFixup) { |
5768 | uriFixup->KeywordToURI(aKeyword, aIsPrivateContext, getter_AddRefs(info)); |
5769 | } |
5770 | } |
5771 | return info.forget(); |
5772 | } |
5773 | |
5774 | /* static */ |
5775 | already_AddRefed<nsIURI> nsDocShell::MaybeFixBadCertDomainErrorURI( |
5776 | nsIChannel* aChannel, nsIURI* aUrl) { |
5777 | if (!aChannel) { |
5778 | return nullptr; |
5779 | } |
5780 | |
5781 | nsresult rv = NS_OK; |
5782 | nsAutoCString host; |
5783 | rv = aUrl->GetAsciiHost(host); |
5784 | 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" , 5784)) { |
5785 | return nullptr; |
5786 | } |
5787 | |
5788 | // Return if fixup enable pref is turned off. |
5789 | if (!mozilla::StaticPrefs::security_bad_cert_domain_error_url_fix_enabled()) { |
5790 | return nullptr; |
5791 | } |
5792 | |
5793 | // Return if scheme is not HTTPS. |
5794 | if (!SchemeIsHTTPS(aUrl)) { |
5795 | return nullptr; |
5796 | } |
5797 | |
5798 | nsCOMPtr<nsILoadInfo> info = aChannel->LoadInfo(); |
5799 | if (!info) { |
5800 | return nullptr; |
5801 | } |
5802 | |
5803 | // Skip doing the fixup if our channel was redirected, because we |
5804 | // shouldn't be guessing things about the post-redirect URI. |
5805 | if (!info->RedirectChain().IsEmpty()) { |
5806 | return nullptr; |
5807 | } |
5808 | |
5809 | int32_t port = 0; |
5810 | rv = aUrl->GetPort(&port); |
5811 | 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" , 5811)) { |
5812 | return nullptr; |
5813 | } |
5814 | |
5815 | // Don't fix up hosts with ports. |
5816 | if (port != -1) { |
5817 | return nullptr; |
5818 | } |
5819 | |
5820 | // Don't fix up localhost url. |
5821 | if (host == "localhost") { |
5822 | return nullptr; |
5823 | } |
5824 | |
5825 | // Don't fix up hostnames with IP address. |
5826 | if (net_IsValidIPv4Addr(host) || net_IsValidIPv6Addr(host)) { |
5827 | return nullptr; |
5828 | } |
5829 | |
5830 | nsAutoCString userPass; |
5831 | rv = aUrl->GetUserPass(userPass); |
5832 | 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" , 5832)) { |
5833 | return nullptr; |
5834 | } |
5835 | |
5836 | // Security - URLs with user / password info should NOT be modified. |
5837 | if (!userPass.IsEmpty()) { |
5838 | return nullptr; |
5839 | } |
5840 | |
5841 | nsCOMPtr<nsITransportSecurityInfo> tsi; |
5842 | rv = aChannel->GetSecurityInfo(getter_AddRefs(tsi)); |
5843 | 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" , 5843)) { |
5844 | return nullptr; |
5845 | } |
5846 | |
5847 | if (NS_WARN_IF(!tsi)NS_warn_if_impl(!tsi, "!tsi", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 5847)) { |
5848 | return nullptr; |
5849 | } |
5850 | |
5851 | nsCOMPtr<nsIX509Cert> cert; |
5852 | rv = tsi->GetServerCert(getter_AddRefs(cert)); |
5853 | 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" , 5853)) { |
5854 | return nullptr; |
5855 | } |
5856 | |
5857 | nsTArray<uint8_t> certBytes; |
5858 | rv = cert->GetRawDER(certBytes); |
5859 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
5860 | return nullptr; |
5861 | } |
5862 | |
5863 | mozilla::pkix::Input serverCertInput; |
5864 | mozilla::pkix::Result result = |
5865 | serverCertInput.Init(certBytes.Elements(), certBytes.Length()); |
5866 | if (result != mozilla::pkix::Success) { |
5867 | return nullptr; |
5868 | } |
5869 | |
5870 | constexpr auto wwwPrefix = "www."_ns; |
5871 | nsAutoCString newHost; |
5872 | if (StringBeginsWith(host, wwwPrefix)) { |
5873 | // Try www.example.com -> example.com |
5874 | newHost.Assign(Substring(host, wwwPrefix.Length())); |
5875 | } else { |
5876 | // Try example.com -> www.example.com |
5877 | newHost.Assign(wwwPrefix); |
5878 | newHost.Append(host); |
5879 | } |
5880 | |
5881 | mozilla::pkix::Input newHostInput; |
5882 | result = newHostInput.Init( |
5883 | BitwiseCast<const uint8_t*, const char*>(newHost.BeginReading()), |
5884 | newHost.Length()); |
5885 | if (result != mozilla::pkix::Success) { |
5886 | return nullptr; |
5887 | } |
5888 | |
5889 | // Because certificate verification returned Result::ERROR_BAD_CERT_DOMAIN / |
5890 | // SSL_ERROR_BAD_CERT_DOMAIN, a chain was built and we know whether or not |
5891 | // the root was a built-in. |
5892 | bool rootIsBuiltIn; |
5893 | if (NS_FAILED(tsi->GetIsBuiltCertChainRootBuiltInRoot(&rootIsBuiltIn))((bool)(__builtin_expect(!!(NS_FAILED_impl(tsi->GetIsBuiltCertChainRootBuiltInRoot (&rootIsBuiltIn))), 0)))) { |
5894 | return nullptr; |
5895 | } |
5896 | mozilla::psm::SkipInvalidSANsForNonBuiltInRootsPolicy nameMatchingPolicy( |
5897 | rootIsBuiltIn); |
5898 | |
5899 | // Check if the certificate is valid for the new hostname. |
5900 | result = mozilla::pkix::CheckCertHostname(serverCertInput, newHostInput, |
5901 | nameMatchingPolicy); |
5902 | if (result != mozilla::pkix::Success) { |
5903 | return nullptr; |
5904 | } |
5905 | |
5906 | nsCOMPtr<nsIURI> newURI; |
5907 | Unused << NS_MutateURI(aUrl).SetHost(newHost).Finalize( |
5908 | getter_AddRefs(newURI)); |
5909 | |
5910 | return newURI.forget(); |
5911 | } |
5912 | |
5913 | /* static */ |
5914 | already_AddRefed<nsIURI> nsDocShell::AttemptURIFixup( |
5915 | nsIChannel* aChannel, nsresult aStatus, |
5916 | const mozilla::Maybe<nsCString>& aOriginalURIString, uint32_t aLoadType, |
5917 | bool aIsTopFrame, bool aAllowKeywordFixup, bool aUsePrivateBrowsing, |
5918 | bool aNotifyKeywordSearchLoading, nsIInputStream** aNewPostData, |
5919 | bool* outWasSchemelessInput) { |
5920 | if (aStatus != NS_ERROR_UNKNOWN_HOST && aStatus != NS_ERROR_NET_RESET && |
5921 | aStatus != NS_ERROR_CONNECTION_REFUSED && |
5922 | aStatus != |
5923 | mozilla::psm::GetXPCOMFromNSSError(SSL_ERROR_BAD_CERT_DOMAIN)) { |
5924 | return nullptr; |
5925 | } |
5926 | |
5927 | if (!(aLoadType == LOAD_NORMAL && aIsTopFrame) && !aAllowKeywordFixup) { |
5928 | return nullptr; |
5929 | } |
5930 | |
5931 | nsCOMPtr<nsIURI> url; |
5932 | nsresult rv = aChannel->GetURI(getter_AddRefs(url)); |
5933 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
5934 | return nullptr; |
5935 | } |
5936 | |
5937 | // |
5938 | // Try and make an alternative URI from the old one |
5939 | // |
5940 | nsCOMPtr<nsIURI> newURI; |
5941 | nsCOMPtr<nsIInputStream> newPostData; |
5942 | |
5943 | nsAutoCString oldSpec; |
5944 | url->GetSpec(oldSpec); |
5945 | |
5946 | // |
5947 | // First try keyword fixup |
5948 | // |
5949 | nsAutoString keywordProviderName, keywordAsSent; |
5950 | if (aStatus == NS_ERROR_UNKNOWN_HOST && aAllowKeywordFixup) { |
5951 | // we should only perform a keyword search under the following |
5952 | // conditions: |
5953 | // (0) Pref keyword.enabled is true |
5954 | // (1) the url scheme is http (or https) |
5955 | // (2) the url does not have a protocol scheme |
5956 | // If we don't enforce such a policy, then we end up doing |
5957 | // keyword searchs on urls we don't intend like imap, file, |
5958 | // mailbox, etc. This could lead to a security problem where we |
5959 | // send data to the keyword server that we shouldn't be. |
5960 | // Someone needs to clean up keywords in general so we can |
5961 | // determine on a per url basis if we want keywords |
5962 | // enabled...this is just a bandaid... |
5963 | nsAutoCString scheme; |
5964 | Unused << url->GetScheme(scheme); |
5965 | if (Preferences::GetBool("keyword.enabled", false) && |
5966 | StringBeginsWith(scheme, "http"_ns)) { |
5967 | bool attemptFixup = false; |
5968 | nsAutoCString host; |
5969 | Unused << url->GetHost(host); |
5970 | if (host.FindChar('.') == kNotFound) { |
5971 | attemptFixup = true; |
5972 | } else { |
5973 | // For domains with dots, we check the public suffix validity. |
5974 | nsCOMPtr<nsIEffectiveTLDService> tldService = |
5975 | do_GetService(NS_EFFECTIVETLDSERVICE_CONTRACTID"@mozilla.org/network/effective-tld-service;1"); |
5976 | if (tldService) { |
5977 | nsAutoCString suffix; |
5978 | attemptFixup = |
5979 | NS_SUCCEEDED(tldService->GetKnownPublicSuffix(url, suffix))((bool)(__builtin_expect(!!(!NS_FAILED_impl(tldService->GetKnownPublicSuffix (url, suffix))), 1))) && |
5980 | suffix.IsEmpty(); |
5981 | } |
5982 | } |
5983 | if (attemptFixup) { |
5984 | nsCOMPtr<nsIURIFixupInfo> info; |
5985 | // only send non-qualified hosts to the keyword server |
5986 | if (aOriginalURIString && !aOriginalURIString->IsEmpty()) { |
5987 | info = KeywordToURI(*aOriginalURIString, aUsePrivateBrowsing); |
5988 | } else { |
5989 | // |
5990 | // If this string was passed through nsStandardURL by |
5991 | // chance, then it may have been converted from UTF-8 to |
5992 | // ACE, which would result in a completely bogus keyword |
5993 | // query. Here we try to recover the original Unicode |
5994 | // value, but this is not 100% correct since the value may |
5995 | // have been normalized per the IDN normalization rules. |
5996 | // |
5997 | // Since we don't have access to the exact original string |
5998 | // that was entered by the user, this will just have to do. |
5999 | // |
6000 | // XXX: Since we are not trying to use the result as an |
6001 | // actual domain name, label-wise Punycode decode would |
6002 | // likely be more appropriate than the full ToUnicode |
6003 | // operation. |
6004 | bool isACE; |
6005 | nsAutoCString utf8Host; |
6006 | nsCOMPtr<nsIIDNService> idnSrv = |
6007 | do_GetService(NS_IDNSERVICE_CONTRACTID"@mozilla.org/network/idn-service;1"); |
6008 | if (idnSrv && NS_SUCCEEDED(idnSrv->IsACE(host, &isACE))((bool)(__builtin_expect(!!(!NS_FAILED_impl(idnSrv->IsACE( host, &isACE))), 1))) && isACE && |
6009 | NS_SUCCEEDED(idnSrv->ConvertACEtoUTF8(host, utf8Host))((bool)(__builtin_expect(!!(!NS_FAILED_impl(idnSrv->ConvertACEtoUTF8 (host, utf8Host))), 1)))) { |
6010 | info = KeywordToURI(utf8Host, aUsePrivateBrowsing); |
6011 | |
6012 | } else { |
6013 | info = KeywordToURI(host, aUsePrivateBrowsing); |
6014 | } |
6015 | } |
6016 | if (info) { |
6017 | info->GetPreferredURI(getter_AddRefs(newURI)); |
6018 | info->GetWasSchemelessInput(outWasSchemelessInput); |
6019 | if (newURI) { |
6020 | info->GetKeywordAsSent(keywordAsSent); |
6021 | info->GetKeywordProviderName(keywordProviderName); |
6022 | info->GetPostData(getter_AddRefs(newPostData)); |
6023 | } |
6024 | } |
6025 | } |
6026 | } |
6027 | } |
6028 | |
6029 | // |
6030 | // Now try change the address, e.g. turn http://foo into |
6031 | // http://www.foo.com, and if that doesn't work try https with |
6032 | // https://foo and https://www.foo.com. |
6033 | // |
6034 | if (aStatus == NS_ERROR_UNKNOWN_HOST || aStatus == NS_ERROR_NET_RESET) { |
6035 | // Skip fixup for anything except a normal document load |
6036 | // operation on the topframe. |
6037 | bool doCreateAlternate = aLoadType == LOAD_NORMAL && aIsTopFrame; |
6038 | |
6039 | if (doCreateAlternate) { |
6040 | nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo(); |
6041 | nsIPrincipal* principal = loadInfo->TriggeringPrincipal(); |
6042 | // Only do this if our channel was loaded directly by the user from the |
6043 | // URL bar or similar (system principal) and not redirected, because we |
6044 | // shouldn't be guessing things about links from other sites, or a |
6045 | // post-redirect URI. |
6046 | doCreateAlternate = principal && principal->IsSystemPrincipal() && |
6047 | loadInfo->RedirectChain().IsEmpty(); |
6048 | } |
6049 | // Test if keyword lookup produced a new URI or not |
6050 | if (doCreateAlternate && newURI) { |
6051 | bool sameURI = false; |
6052 | url->Equals(newURI, &sameURI); |
6053 | if (!sameURI) { |
6054 | // Keyword lookup made a new URI so no need to try |
6055 | // an alternate one. |
6056 | doCreateAlternate = false; |
6057 | } |
6058 | } |
6059 | if (doCreateAlternate) { |
6060 | newURI = nullptr; |
6061 | newPostData = nullptr; |
6062 | keywordProviderName.Truncate(); |
6063 | keywordAsSent.Truncate(); |
6064 | nsCOMPtr<nsIURIFixup> uriFixup = components::URIFixup::Service(); |
6065 | if (uriFixup) { |
6066 | nsCOMPtr<nsIURIFixupInfo> fixupInfo; |
6067 | uriFixup->GetFixupURIInfo(oldSpec, nsIURIFixup::FIXUP_FLAG_NONE, |
6068 | getter_AddRefs(fixupInfo)); |
6069 | if (fixupInfo) { |
6070 | fixupInfo->GetPreferredURI(getter_AddRefs(newURI)); |
6071 | } |
6072 | } |
6073 | } |
6074 | } else if (aStatus == NS_ERROR_CONNECTION_REFUSED && |
6075 | Preferences::GetBool("browser.fixup.fallback-to-https", false)) { |
6076 | // Try HTTPS, since http didn't work |
6077 | if (SchemeIsHTTP(url)) { |
6078 | int32_t port = 0; |
6079 | url->GetPort(&port); |
6080 | |
6081 | // Fall back to HTTPS only if port is default |
6082 | if (port == -1) { |
6083 | newURI = nullptr; |
6084 | newPostData = nullptr; |
6085 | Unused << NS_MutateURI(url) |
6086 | .SetScheme("https"_ns) |
6087 | .Finalize(getter_AddRefs(newURI)); |
6088 | } |
6089 | } |
6090 | } |
6091 | |
6092 | // If we have a SSL_ERROR_BAD_CERT_DOMAIN error, try adding or removing |
6093 | // "www." to/from the beginning of the domain name to see if we can avoid |
6094 | // showing the cert error page. For example, https://example.com -> |
6095 | // https://www.example.com or https://www.example.com -> https://example.com. |
6096 | if (aStatus == |
6097 | mozilla::psm::GetXPCOMFromNSSError(SSL_ERROR_BAD_CERT_DOMAIN)) { |
6098 | newPostData = nullptr; |
6099 | newURI = MaybeFixBadCertDomainErrorURI(aChannel, url); |
6100 | } |
6101 | |
6102 | // Did we make a new URI that is different to the old one? If so |
6103 | // load it. |
6104 | // |
6105 | if (newURI) { |
6106 | // Make sure the new URI is different from the old one, |
6107 | // otherwise there's little point trying to load it again. |
6108 | bool sameURI = false; |
6109 | url->Equals(newURI, &sameURI); |
6110 | if (!sameURI) { |
6111 | if (aNewPostData) { |
6112 | newPostData.forget(aNewPostData); |
6113 | } |
6114 | if (aNotifyKeywordSearchLoading) { |
6115 | // This notification is meant for Firefox Health Report so it |
6116 | // can increment counts from the search engine |
6117 | MaybeNotifyKeywordSearchLoading(keywordProviderName, keywordAsSent); |
6118 | } |
6119 | return newURI.forget(); |
6120 | } |
6121 | } |
6122 | |
6123 | return nullptr; |
6124 | } |
6125 | |
6126 | nsresult nsDocShell::FilterStatusForErrorPage( |
6127 | nsresult aStatus, nsIChannel* aChannel, uint32_t aLoadType, |
6128 | bool aIsTopFrame, bool aUseErrorPages, bool aIsInitialDocument, |
6129 | bool* aSkippedUnknownProtocolNavigation) { |
6130 | // Errors to be shown only on top-level frames |
6131 | if ((aStatus == NS_ERROR_UNKNOWN_HOST || |
6132 | aStatus == NS_ERROR_CONNECTION_REFUSED || |
6133 | aStatus == NS_ERROR_UNKNOWN_PROXY_HOST || |
6134 | aStatus == NS_ERROR_PROXY_CONNECTION_REFUSED || |
6135 | aStatus == NS_ERROR_PROXY_FORBIDDEN || |
6136 | aStatus == NS_ERROR_PROXY_NOT_IMPLEMENTED || |
6137 | aStatus == NS_ERROR_PROXY_AUTHENTICATION_FAILED || |
6138 | aStatus == NS_ERROR_PROXY_TOO_MANY_REQUESTS || |
6139 | aStatus == NS_ERROR_MALFORMED_URI || |
6140 | aStatus == NS_ERROR_BLOCKED_BY_POLICY || |
6141 | aStatus == NS_ERROR_DOM_COOP_FAILED || |
6142 | aStatus == NS_ERROR_DOM_COEP_FAILED) && |
6143 | (aIsTopFrame || aUseErrorPages)) { |
6144 | return aStatus; |
6145 | } |
6146 | |
6147 | if (aStatus == NS_ERROR_NET_TIMEOUT || |
6148 | aStatus == NS_ERROR_NET_TIMEOUT_EXTERNAL || |
6149 | aStatus == NS_ERROR_PROXY_GATEWAY_TIMEOUT || |
6150 | aStatus == NS_ERROR_REDIRECT_LOOP || |
6151 | aStatus == NS_ERROR_UNKNOWN_SOCKET_TYPE || |
6152 | aStatus == NS_ERROR_NET_INTERRUPT || aStatus == NS_ERROR_NET_RESET || |
6153 | aStatus == NS_ERROR_PROXY_BAD_GATEWAY || aStatus == NS_ERROR_OFFLINE || |
6154 | aStatus == NS_ERROR_MALWARE_URI || aStatus == NS_ERROR_PHISHING_URI || |
6155 | aStatus == NS_ERROR_UNWANTED_URI || aStatus == NS_ERROR_HARMFUL_URI || |
6156 | aStatus == NS_ERROR_UNSAFE_CONTENT_TYPE || |
6157 | aStatus == NS_ERROR_INTERCEPTION_FAILED || |
6158 | aStatus == NS_ERROR_NET_INADEQUATE_SECURITY || |
6159 | aStatus == NS_ERROR_NET_HTTP2_SENT_GOAWAY || |
6160 | aStatus == NS_ERROR_NET_HTTP3_PROTOCOL_ERROR || |
6161 | aStatus == NS_ERROR_DOM_BAD_URI || aStatus == NS_ERROR_FILE_NOT_FOUND || |
6162 | aStatus == NS_ERROR_FILE_ACCESS_DENIED || |
6163 | aStatus == NS_ERROR_CORRUPTED_CONTENT || |
6164 | aStatus == NS_ERROR_INVALID_CONTENT_ENCODING || |
6165 | NS_ERROR_GET_MODULE(aStatus) == NS_ERROR_MODULE_SECURITY21) { |
6166 | // Errors to be shown for any frame |
6167 | return aStatus; |
6168 | } |
6169 | |
6170 | if (aStatus == NS_ERROR_UNKNOWN_PROTOCOL) { |
6171 | // For unknown protocols we only display an error if the load is triggered |
6172 | // by the browser itself, or we're replacing the initial document (and |
6173 | // nothing else). Showing the error for page-triggered navigations causes |
6174 | // annoying behavior for users, see bug 1528305. |
6175 | // |
6176 | // We could, maybe, try to detect if this is in response to some user |
6177 | // interaction (like clicking a link, or something else) and maybe show |
6178 | // the error page in that case. But this allows for ctrl+clicking and such |
6179 | // to see the error page. |
6180 | nsCOMPtr<nsILoadInfo> info = aChannel->LoadInfo(); |
6181 | if (!info->TriggeringPrincipal()->IsSystemPrincipal() && |
6182 | !aIsInitialDocument) { |
6183 | if (aSkippedUnknownProtocolNavigation) { |
6184 | *aSkippedUnknownProtocolNavigation = true; |
6185 | } |
6186 | return NS_OK; |
6187 | } |
6188 | return aStatus; |
6189 | } |
6190 | |
6191 | if (aStatus == NS_ERROR_DOCUMENT_NOT_CACHED) { |
6192 | // Non-caching channels will simply return NS_ERROR_OFFLINE. |
6193 | // Caching channels would have to look at their flags to work |
6194 | // out which error to return. Or we can fix up the error here. |
6195 | if (!(aLoadType & LOAD_CMD_HISTORY)) { |
6196 | return NS_ERROR_OFFLINE; |
6197 | } |
6198 | return aStatus; |
6199 | } |
6200 | |
6201 | return NS_OK; |
6202 | } |
6203 | |
6204 | nsresult nsDocShell::EndPageLoad(nsIWebProgress* aProgress, |
6205 | nsIChannel* aChannel, nsresult aStatus) { |
6206 | 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) |
6207 | ("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) |
6208 | 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); |
6209 | if (!aChannel) { |
6210 | return NS_ERROR_NULL_POINTER; |
6211 | } |
6212 | |
6213 | // Make sure to discard the initial client if we never created the initial |
6214 | // about:blank document. Do this before possibly returning from the method |
6215 | // due to an error. |
6216 | mInitialClientSource.reset(); |
6217 | |
6218 | nsCOMPtr<nsIConsoleReportCollector> reporter = do_QueryInterface(aChannel); |
6219 | if (reporter) { |
6220 | nsCOMPtr<nsILoadGroup> loadGroup; |
6221 | aChannel->GetLoadGroup(getter_AddRefs(loadGroup)); |
6222 | if (loadGroup) { |
6223 | reporter->FlushConsoleReports(loadGroup); |
6224 | } else { |
6225 | reporter->FlushConsoleReports(GetDocument()); |
6226 | } |
6227 | } |
6228 | |
6229 | nsCOMPtr<nsIURI> url; |
6230 | nsresult rv = aChannel->GetURI(getter_AddRefs(url)); |
6231 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
6232 | return rv; |
6233 | } |
6234 | |
6235 | nsCOMPtr<nsITimedChannel> timingChannel = do_QueryInterface(aChannel); |
6236 | if (timingChannel) { |
6237 | TimeStamp channelCreationTime; |
6238 | rv = timingChannel->GetChannelCreation(&channelCreationTime); |
6239 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && !channelCreationTime.IsNull()) { |
6240 | glean::performance_page::total_content_page_load.AccumulateRawDuration( |
6241 | TimeStamp::Now() - channelCreationTime); |
6242 | } |
6243 | } |
6244 | |
6245 | // Timing is picked up by the window, we don't need it anymore |
6246 | mTiming = nullptr; |
6247 | |
6248 | // clean up reload state for meta charset |
6249 | if (eCharsetReloadRequested == mCharsetReloadState) { |
6250 | mCharsetReloadState = eCharsetReloadStopOrigional; |
6251 | } else { |
6252 | mCharsetReloadState = eCharsetReloadInit; |
6253 | } |
6254 | |
6255 | // Save a pointer to the currently-loading history entry. |
6256 | // nsDocShell::EndPageLoad will clear mLSHE, but we may need this history |
6257 | // entry further down in this method. |
6258 | nsCOMPtr<nsISHEntry> loadingSHE = mLSHE; |
6259 | mozilla::Unused << loadingSHE; // XXX: Not sure if we need this anymore |
6260 | |
6261 | // |
6262 | // one of many safeguards that prevent death and destruction if |
6263 | // someone is so very very rude as to bring this window down |
6264 | // during this load handler. |
6265 | // |
6266 | nsCOMPtr<nsIDocShell> kungFuDeathGrip(this); |
6267 | |
6268 | // Notify the DocumentViewer that the Document has finished loading. This |
6269 | // will cause any OnLoad(...) and PopState(...) handlers to fire. |
6270 | if (!mEODForCurrentDocument && mDocumentViewer) { |
6271 | mIsExecutingOnLoadHandler = true; |
6272 | nsCOMPtr<nsIDocumentViewer> viewer = mDocumentViewer; |
6273 | viewer->LoadComplete(aStatus); |
6274 | mIsExecutingOnLoadHandler = false; |
6275 | |
6276 | mEODForCurrentDocument = true; |
6277 | } |
6278 | /* Check if the httpChannel has any cache-control related response headers, |
6279 | * like no-store, no-cache. If so, update SHEntry so that |
6280 | * when a user goes back/forward to this page, we appropriately do |
6281 | * form value restoration or load from server. |
6282 | */ |
6283 | nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(aChannel)); |
6284 | if (!httpChannel) { |
6285 | // HttpChannel could be hiding underneath a Multipart channel. |
6286 | GetHttpChannel(aChannel, getter_AddRefs(httpChannel)); |
6287 | } |
6288 | |
6289 | if (httpChannel) { |
6290 | // figure out if SH should be saving layout state. |
6291 | bool discardLayoutState = ShouldDiscardLayoutState(httpChannel); |
6292 | if (mLSHE && discardLayoutState && (mLoadType & LOAD_CMD_NORMAL) && |
6293 | (mLoadType != LOAD_BYPASS_HISTORY) && (mLoadType != LOAD_ERROR_PAGE)) { |
6294 | mLSHE->SetSaveLayoutStateFlag(false); |
6295 | } |
6296 | } |
6297 | |
6298 | // Clear mLSHE after calling the onLoadHandlers. This way, if the |
6299 | // onLoadHandler tries to load something different in |
6300 | // itself or one of its children, we can deal with it appropriately. |
6301 | if (mLSHE) { |
6302 | mLSHE->SetLoadType(LOAD_HISTORY); |
6303 | |
6304 | // Clear the mLSHE reference to indicate document loading is done one |
6305 | // way or another. |
6306 | SetHistoryEntryAndUpdateBC(Some(nullptr), Nothing()); |
6307 | } |
6308 | mActiveEntryIsLoadingFromSessionHistory = false; |
6309 | |
6310 | // if there's a refresh header in the channel, this method |
6311 | // will set it up for us. |
6312 | if (mBrowsingContext->IsActive() || !mDisableMetaRefreshWhenInactive) |
6313 | RefreshURIFromQueue(); |
6314 | |
6315 | // Test whether this is the top frame or a subframe |
6316 | bool isTopFrame = mBrowsingContext->IsTop(); |
6317 | |
6318 | bool hadErrorStatus = false; |
6319 | // If status code indicates an error it means that DocumentChannel already |
6320 | // tried to fixup the uri and failed. Throw an error dialog box here. |
6321 | if (NS_FAILED(aStatus)((bool)(__builtin_expect(!!(NS_FAILED_impl(aStatus)), 0)))) { |
6322 | // If we got CONTENT_BLOCKED from EndPageLoad, then we need to fire |
6323 | // the error event to our embedder, since tests are relying on this. |
6324 | // The error event is usually fired by the caller of InternalLoad, but |
6325 | // this particular error can happen asynchronously. |
6326 | // Bug 1629201 is filed for having much clearer decision making around |
6327 | // which cases need error events. |
6328 | bool fireFrameErrorEvent = (aStatus == NS_ERROR_CONTENT_BLOCKED_SHOW_ALT || |
6329 | aStatus == NS_ERROR_CONTENT_BLOCKED); |
6330 | UnblockEmbedderLoadEventForFailure(fireFrameErrorEvent); |
6331 | |
6332 | bool isInitialDocument = |
6333 | !GetExtantDocument() || GetExtantDocument()->IsInitialDocument(); |
6334 | bool skippedUnknownProtocolNavigation = false; |
6335 | aStatus = FilterStatusForErrorPage(aStatus, aChannel, mLoadType, isTopFrame, |
6336 | mBrowsingContext->GetUseErrorPages(), |
6337 | isInitialDocument, |
6338 | &skippedUnknownProtocolNavigation); |
6339 | hadErrorStatus = true; |
6340 | if (NS_FAILED(aStatus)((bool)(__builtin_expect(!!(NS_FAILED_impl(aStatus)), 0)))) { |
6341 | if (!mIsBeingDestroyed) { |
6342 | DisplayLoadError(aStatus, url, nullptr, aChannel); |
6343 | } |
6344 | } else if (skippedUnknownProtocolNavigation) { |
6345 | nsTArray<nsString> params; |
6346 | if (NS_FAILED(((bool)(__builtin_expect(!!(NS_FAILED_impl(NS_GetSanitizedURIStringFromURI (url, *params.AppendElement()))), 0))) |
6347 | NS_GetSanitizedURIStringFromURI(url, *params.AppendElement()))((bool)(__builtin_expect(!!(NS_FAILED_impl(NS_GetSanitizedURIStringFromURI (url, *params.AppendElement()))), 0)))) { |
6348 | params.LastElement().AssignLiteral(u"(unknown uri)"); |
6349 | } |
6350 | nsContentUtils::ReportToConsole( |
6351 | nsIScriptError::warningFlag, "DOM"_ns, GetExtantDocument(), |
6352 | nsContentUtils::eDOM_PROPERTIES, "UnknownProtocolNavigationPrevented", |
6353 | params); |
6354 | } |
6355 | } else { |
6356 | // If we have a host |
6357 | nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo(); |
6358 | PredictorLearnRedirect(url, aChannel, loadInfo->GetOriginAttributes()); |
6359 | } |
6360 | |
6361 | if (hadErrorStatus) { |
6362 | // Don't send session store updates if the reason EndPageLoad was called is |
6363 | // because we are process switching. Sometimes the update takes too long and |
6364 | // incorrectly overrides session store data from the following load. |
6365 | return NS_OK; |
6366 | } |
6367 | if (SessionStorePlatformCollection()) { |
6368 | if (WindowContext* windowContext = |
6369 | mBrowsingContext->GetCurrentWindowContext()) { |
6370 | using Change = SessionStoreChangeListener::Change; |
6371 | |
6372 | // We've finished loading the page and now we want to collect all the |
6373 | // session store state that the page is initialized with. |
6374 | SessionStoreChangeListener::CollectSessionStoreData( |
6375 | windowContext, |
6376 | EnumSet<Change>(Change::Input, Change::Scroll, Change::SessionHistory, |
6377 | Change::WireFrame)); |
6378 | } |
6379 | } |
6380 | |
6381 | return NS_OK; |
6382 | } |
6383 | |
6384 | //***************************************************************************** |
6385 | // nsDocShell: Content Viewer Management |
6386 | //***************************************************************************** |
6387 | |
6388 | nsresult nsDocShell::EnsureDocumentViewer() { |
6389 | if (mDocumentViewer) { |
6390 | return NS_OK; |
6391 | } |
6392 | if (mIsBeingDestroyed) { |
6393 | return NS_ERROR_FAILURE; |
6394 | } |
6395 | |
6396 | nsCOMPtr<nsIContentSecurityPolicy> cspToInheritForAboutBlank; |
6397 | nsCOMPtr<nsIURI> baseURI; |
6398 | nsIPrincipal* principal = GetInheritedPrincipal(false); |
6399 | nsIPrincipal* partitionedPrincipal = GetInheritedPrincipal(false, true); |
6400 | |
6401 | nsCOMPtr<nsIDocShellTreeItem> parentItem; |
6402 | GetInProcessSameTypeParent(getter_AddRefs(parentItem)); |
6403 | if (parentItem) { |
6404 | if (nsCOMPtr<nsPIDOMWindowOuter> domWin = GetWindow()) { |
6405 | nsCOMPtr<Element> parentElement = domWin->GetFrameElementInternal(); |
6406 | if (parentElement) { |
6407 | baseURI = parentElement->GetBaseURI(); |
6408 | cspToInheritForAboutBlank = parentElement->GetCsp(); |
6409 | } |
6410 | } |
6411 | } |
6412 | |
6413 | nsresult rv = CreateAboutBlankDocumentViewer( |
6414 | principal, partitionedPrincipal, cspToInheritForAboutBlank, baseURI, |
6415 | /* aIsInitialDocument */ true); |
6416 | |
6417 | 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" , 6417); return NS_ERROR_UNEXPECTED; } } while (false); |
6418 | |
6419 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) { |
6420 | RefPtr<Document> doc(GetDocument()); |
6421 | 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" , 6423); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc" ") (" "Should have doc if CreateAboutBlankDocumentViewer " "succeeded!" ")"); do { *((volatile int*)__null) = 6423; __attribute__ ((nomerge)) ::abort(); } while (false); } } while (false) |
6422 | "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" , 6423); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc" ") (" "Should have doc if CreateAboutBlankDocumentViewer " "succeeded!" ")"); do { *((volatile int*)__null) = 6423; __attribute__ ((nomerge)) ::abort(); } while (false); } } while (false) |
6423 | "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" , 6423); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc" ") (" "Should have doc if CreateAboutBlankDocumentViewer " "succeeded!" ")"); do { *((volatile int*)__null) = 6423; __attribute__ ((nomerge)) ::abort(); } while (false); } } while (false); |
6424 | MOZ_ASSERT(doc->IsInitialDocument(), "Document should be initial document")do { static_assert( mozilla::detail::AssertionConditionType< decltype(doc->IsInitialDocument())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(doc->IsInitialDocument()) )), 0))) { do { } while (false); MOZ_ReportAssertionFailure("doc->IsInitialDocument()" " (" "Document should be initial document" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 6424); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc->IsInitialDocument()" ") (" "Document should be initial document" ")"); do { *((volatile int*)__null) = 6424; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
6425 | |
6426 | // Documents created using EnsureDocumentViewer may be transient |
6427 | // placeholders created by framescripts before content has a |
6428 | // chance to load. In some cases, window.open(..., "noopener") |
6429 | // will create such a document and then synchronously tear it |
6430 | // down, firing a "pagehide" event. Doing so violates our |
6431 | // assertions about DocGroups. It's easier to silence the |
6432 | // assertion here than to avoid creating the extra document. |
6433 | doc->IgnoreDocGroupMismatches(); |
6434 | } |
6435 | |
6436 | return rv; |
6437 | } |
6438 | |
6439 | nsresult nsDocShell::CreateAboutBlankDocumentViewer( |
6440 | nsIPrincipal* aPrincipal, nsIPrincipal* aPartitionedPrincipal, |
6441 | nsIContentSecurityPolicy* aCSP, nsIURI* aBaseURI, bool aIsInitialDocument, |
6442 | const Maybe<nsILoadInfo::CrossOriginEmbedderPolicy>& aCOEP, |
6443 | bool aTryToSaveOldPresentation, bool aCheckPermitUnload, |
6444 | WindowGlobalChild* aActor) { |
6445 | RefPtr<Document> blankDoc; |
6446 | nsCOMPtr<nsIDocumentViewer> viewer; |
6447 | nsresult rv = NS_ERROR_FAILURE; |
6448 | |
6449 | 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 ) |
6450 | MarkerStack::Capture())do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl ("CreateAboutBlankDocumentViewer", ::geckoprofiler::category:: DOM, MarkerStack::Capture()); } } while (false); } while (false ); |
6451 | |
6452 | 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" , 6452); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aActor->DocumentPrincipal() == aPrincipal" ")"); do { *((volatile int*)__null) = 6452; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); |
6453 | |
6454 | /* mCreatingDocument should never be true at this point. However, it's |
6455 | a theoretical possibility. We want to know about it and make it stop, |
6456 | and this sounds like a job for an assertion. */ |
6457 | 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" , 6458); MOZ_PretendNoReturn(); } } while (0) |
6458 | "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" , 6458); MOZ_PretendNoReturn(); } } while (0); |
6459 | if (mCreatingDocument) { |
6460 | return NS_ERROR_FAILURE; |
6461 | } |
6462 | |
6463 | if (!mBrowsingContext->AncestorsAreCurrent() || |
6464 | mBrowsingContext->IsInBFCache()) { |
6465 | mBrowsingContext->RemoveRootFromBFCacheSync(); |
6466 | return NS_ERROR_NOT_AVAILABLE; |
6467 | } |
6468 | |
6469 | // mDocumentViewer->PermitUnload may release |this| docshell. |
6470 | nsCOMPtr<nsIDocShell> kungFuDeathGrip(this); |
6471 | |
6472 | AutoRestore<bool> creatingDocument(mCreatingDocument); |
6473 | mCreatingDocument = true; |
6474 | |
6475 | if (aPrincipal && !aPrincipal->IsSystemPrincipal() && |
6476 | mItemType != typeChrome) { |
6477 | 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" , 6478); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPrincipal->OriginAttributesRef() == mBrowsingContext->OriginAttributesRef()" ")"); do { *((volatile int*)__null) = 6478; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
6478 | 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" , 6478); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPrincipal->OriginAttributesRef() == mBrowsingContext->OriginAttributesRef()" ")"); do { *((volatile int*)__null) = 6478; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
6479 | } |
6480 | |
6481 | // Make sure timing is created. But first record whether we had it |
6482 | // already, so we don't clobber the timing for an in-progress load. |
6483 | bool hadTiming = mTiming; |
6484 | bool toBeReset = MaybeInitTiming(); |
6485 | if (mDocumentViewer) { |
6486 | if (aCheckPermitUnload) { |
6487 | // We've got a content viewer already. Make sure the user |
6488 | // permits us to discard the current document and replace it |
6489 | // with about:blank. And also ensure we fire the unload events |
6490 | // in the current document. |
6491 | |
6492 | // Unload gets fired first for |
6493 | // document loaded from the session history. |
6494 | mTiming->NotifyBeforeUnload(); |
6495 | |
6496 | bool okToUnload; |
6497 | rv = mDocumentViewer->PermitUnload(&okToUnload); |
6498 | |
6499 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && !okToUnload) { |
6500 | // The user chose not to unload the page, interrupt the load. |
6501 | MaybeResetInitTiming(toBeReset); |
6502 | return NS_ERROR_FAILURE; |
6503 | } |
6504 | if (mTiming) { |
6505 | mTiming->NotifyUnloadAccepted(mCurrentURI); |
6506 | } |
6507 | } |
6508 | |
6509 | mSavingOldViewer = |
6510 | aTryToSaveOldPresentation && |
6511 | CanSavePresentation(LOAD_NORMAL, nullptr, nullptr, |
6512 | /* aReportBFCacheComboTelemetry */ true); |
6513 | |
6514 | // Make sure to blow away our mLoadingURI just in case. No loads |
6515 | // from inside this pagehide. |
6516 | mLoadingURI = nullptr; |
6517 | |
6518 | // Stop any in-progress loading, so that we don't accidentally trigger any |
6519 | // PageShow notifications from Embed() interrupting our loading below. |
6520 | Stop(); |
6521 | |
6522 | // Notify the current document that it is about to be unloaded!! |
6523 | // |
6524 | // It is important to fire the unload() notification *before* any state |
6525 | // is changed within the DocShell - otherwise, javascript will get the |
6526 | // wrong information :-( |
6527 | // |
6528 | (void)FirePageHideNotification(!mSavingOldViewer); |
6529 | // pagehide notification might destroy this docshell. |
6530 | if (mIsBeingDestroyed) { |
6531 | return NS_ERROR_DOCSHELL_DYING; |
6532 | } |
6533 | } |
6534 | |
6535 | // Now make sure we don't think we're in the middle of firing unload after |
6536 | // this point. This will make us fire unload when the about:blank document |
6537 | // unloads... but that's ok, more or less. Would be nice if it fired load |
6538 | // too, of course. |
6539 | mFiredUnloadEvent = false; |
6540 | |
6541 | nsCOMPtr<nsIDocumentLoaderFactory> docFactory = |
6542 | nsContentUtils::FindInternalDocumentViewer("text/html"_ns); |
6543 | |
6544 | if (docFactory) { |
6545 | nsCOMPtr<nsIPrincipal> principal, partitionedPrincipal; |
6546 | const uint32_t sandboxFlags = |
6547 | mBrowsingContext->GetHasLoadedNonInitialDocument() |
6548 | ? mBrowsingContext->GetSandboxFlags() |
6549 | : mBrowsingContext->GetInitialSandboxFlags(); |
6550 | // If we're sandboxed, then create a new null principal. We skip |
6551 | // this if we're being created from WindowGlobalChild, since in |
6552 | // that case we already have a null principal if required. |
6553 | // We can't compare againt the BrowsingContext sandbox flag, since |
6554 | // the value was taken when the load initiated and may have since |
6555 | // changed. |
6556 | if ((sandboxFlags & SANDBOXED_ORIGIN) && !aActor) { |
6557 | if (aPrincipal) { |
6558 | principal = NullPrincipal::CreateWithInheritedAttributes(aPrincipal); |
6559 | } else { |
6560 | principal = NullPrincipal::Create(GetOriginAttributes()); |
6561 | } |
6562 | partitionedPrincipal = principal; |
6563 | } else { |
6564 | principal = aPrincipal; |
6565 | partitionedPrincipal = aPartitionedPrincipal; |
6566 | } |
6567 | |
6568 | // We cannot get the foreign partitioned prinicpal for the initial |
6569 | // about:blank page. So, we change to check if we need to use the |
6570 | // partitioned principal for the service worker here. |
6571 | MaybeCreateInitialClientSource( |
6572 | StoragePrincipalHelper::ShouldUsePartitionPrincipalForServiceWorker( |
6573 | this) |
6574 | ? partitionedPrincipal |
6575 | : principal); |
6576 | |
6577 | // generate (about:blank) document to load |
6578 | blankDoc = nsContentDLF::CreateBlankDocument(mLoadGroup, principal, |
6579 | partitionedPrincipal, this); |
6580 | if (blankDoc) { |
6581 | // Hack: manually set the CSP for the new document |
6582 | // Please create an actual copy of the CSP (do not share the same |
6583 | // reference) otherwise appending a new policy within the new |
6584 | // document will be incorrectly propagated to the opening doc. |
6585 | if (aCSP) { |
6586 | RefPtr<nsCSPContext> cspToInherit = new nsCSPContext(); |
6587 | cspToInherit->InitFromOther(static_cast<nsCSPContext*>(aCSP)); |
6588 | blankDoc->SetCsp(cspToInherit); |
6589 | } |
6590 | |
6591 | blankDoc->SetIsInitialDocument(aIsInitialDocument); |
6592 | |
6593 | blankDoc->SetEmbedderPolicy(aCOEP); |
6594 | |
6595 | // Hack: set the base URI manually, since this document never |
6596 | // got Reset() with a channel. |
6597 | blankDoc->SetBaseURI(aBaseURI); |
6598 | |
6599 | // Copy our sandbox flags to the document. These are immutable |
6600 | // after being set here. |
6601 | blankDoc->SetSandboxFlags(sandboxFlags); |
6602 | |
6603 | // create a content viewer for us and the new document |
6604 | docFactory->CreateInstanceForDocument( |
6605 | NS_ISUPPORTS_CAST(nsIDocShell*, this)static_cast<nsISupports*>(static_cast<nsIDocShell*> (this)), blankDoc, "view", |
6606 | getter_AddRefs(viewer)); |
6607 | |
6608 | // hook 'em up |
6609 | if (viewer) { |
6610 | viewer->SetContainer(this); |
6611 | rv = Embed(viewer, aActor, true, false, nullptr, mCurrentURI); |
6612 | 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" , 6612); return rv; } } while (false); |
6613 | |
6614 | SetCurrentURI(blankDoc->GetDocumentURI(), nullptr, |
6615 | /* aFireLocationChange */ true, |
6616 | /* aIsInitialAboutBlank */ true, |
6617 | /* aLocationFlags */ 0); |
6618 | rv = mIsBeingDestroyed ? NS_ERROR_NOT_AVAILABLE : NS_OK; |
6619 | } |
6620 | |
6621 | if (Element* embedderElement = blankDoc->GetEmbedderElement()) { |
6622 | blankDoc->InitFeaturePolicy(AsVariant(embedderElement)); |
6623 | } else { |
6624 | blankDoc->InitFeaturePolicy(AsVariant(Nothing{})); |
6625 | } |
6626 | } |
6627 | } |
6628 | |
6629 | // The transient about:blank viewer doesn't have a session history entry. |
6630 | SetHistoryEntryAndUpdateBC(Nothing(), Some(nullptr)); |
6631 | |
6632 | // Clear out our mTiming like we would in EndPageLoad, if we didn't |
6633 | // have one before entering this function. |
6634 | if (!hadTiming) { |
6635 | mTiming = nullptr; |
6636 | mBlankTiming = true; |
6637 | } |
6638 | |
6639 | return rv; |
6640 | } |
6641 | |
6642 | NS_IMETHODIMPnsresult |
6643 | nsDocShell::CreateAboutBlankDocumentViewer(nsIPrincipal* aPrincipal, |
6644 | nsIPrincipal* aPartitionedPrincipal, |
6645 | nsIContentSecurityPolicy* aCSP) { |
6646 | return CreateAboutBlankDocumentViewer(aPrincipal, aPartitionedPrincipal, aCSP, |
6647 | nullptr, |
6648 | /* aIsInitialDocument */ false); |
6649 | } |
6650 | |
6651 | nsresult nsDocShell::CreateDocumentViewerForActor( |
6652 | WindowGlobalChild* aWindowActor) { |
6653 | 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" , 6653); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aWindowActor" ")"); do { *((volatile int*)__null) = 6653; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
6654 | |
6655 | // FIXME: WindowGlobalChild should provide the PartitionedPrincipal. |
6656 | // FIXME: We may want to support non-initial documents here. |
6657 | nsresult rv = CreateAboutBlankDocumentViewer( |
6658 | aWindowActor->DocumentPrincipal(), aWindowActor->DocumentPrincipal(), |
6659 | /* aCsp */ nullptr, |
6660 | /* aBaseURI */ nullptr, |
6661 | /* aIsInitialDocument */ true, |
6662 | /* aCOEP */ Nothing(), |
6663 | /* aTryToSaveOldPresentation */ true, |
6664 | /* aCheckPermitUnload */ true, aWindowActor); |
6665 | #ifdef DEBUG1 |
6666 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) { |
6667 | RefPtr<Document> doc(GetDocument()); |
6668 | 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" , 6670); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc" ") (" "Should have a document if CreateAboutBlankDocumentViewer succeeded" ")"); do { *((volatile int*)__null) = 6670; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
6669 | 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" , 6670); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc" ") (" "Should have a document if CreateAboutBlankDocumentViewer succeeded" ")"); do { *((volatile int*)__null) = 6670; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
6670 | "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" , 6670); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc" ") (" "Should have a document if CreateAboutBlankDocumentViewer succeeded" ")"); do { *((volatile int*)__null) = 6670; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
6671 | 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" , 6672); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc->GetOwnerGlobal() == aWindowActor->GetWindowGlobal()" ") (" "New document should be in the same global as our actor" ")"); do { *((volatile int*)__null) = 6672; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
6672 | "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" , 6672); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc->GetOwnerGlobal() == aWindowActor->GetWindowGlobal()" ") (" "New document should be in the same global as our actor" ")"); do { *((volatile int*)__null) = 6672; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
6673 | 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" , 6674); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc->IsInitialDocument()" ") (" "New document should be an initial document" ")"); do { *((volatile int*)__null) = 6674; __attribute__((nomerge)) :: abort(); } while (false); } } while (false) |
6674 | "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" , 6674); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc->IsInitialDocument()" ") (" "New document should be an initial document" ")"); do { *((volatile int*)__null) = 6674; __attribute__((nomerge)) :: abort(); } while (false); } } while (false); |
6675 | } |
6676 | #endif |
6677 | |
6678 | return rv; |
6679 | } |
6680 | |
6681 | bool nsDocShell::CanSavePresentation(uint32_t aLoadType, |
6682 | nsIRequest* aNewRequest, |
6683 | Document* aNewDocument, |
6684 | bool aReportBFCacheComboTelemetry) { |
6685 | if (!mOSHE) { |
6686 | return false; // no entry to save into |
6687 | } |
6688 | |
6689 | 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" , 6690); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()" ") (" "mOSHE cannot be non-null with SHIP" ")"); do { *((volatile int*)__null) = 6690; __attribute__((nomerge)) ::abort(); } while (false); } } while (false) |
6690 | "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" , 6690); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()" ") (" "mOSHE cannot be non-null with SHIP" ")"); do { *((volatile int*)__null) = 6690; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
6691 | nsCOMPtr<nsIDocumentViewer> viewer = mOSHE->GetDocumentViewer(); |
6692 | if (viewer) { |
6693 | 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" , 6693); |
6694 | return false; |
6695 | } |
6696 | |
6697 | // Only save presentation for "normal" loads and link loads. Anything else |
6698 | // probably wants to refetch the page, so caching the old presentation |
6699 | // would be incorrect. |
6700 | if (aLoadType != LOAD_NORMAL && aLoadType != LOAD_HISTORY && |
6701 | aLoadType != LOAD_LINK && aLoadType != LOAD_STOP_CONTENT && |
6702 | aLoadType != LOAD_STOP_CONTENT_AND_REPLACE && |
6703 | aLoadType != LOAD_ERROR_PAGE) { |
6704 | return false; |
6705 | } |
6706 | |
6707 | // If the session history entry has the saveLayoutState flag set to false, |
6708 | // then we should not cache the presentation. |
6709 | if (!mOSHE->GetSaveLayoutStateFlag()) { |
6710 | return false; |
6711 | } |
6712 | |
6713 | // If the document is not done loading, don't cache it. |
6714 | if (!mScriptGlobal || mScriptGlobal->IsLoading()) { |
6715 | 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) |
6716 | ("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); |
6717 | return false; |
6718 | } |
6719 | |
6720 | if (mScriptGlobal->WouldReuseInnerWindow(aNewDocument)) { |
6721 | return false; |
6722 | } |
6723 | |
6724 | // Avoid doing the work of saving the presentation state in the case where |
6725 | // the content viewer cache is disabled. |
6726 | if (nsSHistory::GetMaxTotalViewers() == 0) { |
6727 | return false; |
6728 | } |
6729 | |
6730 | // Don't cache the content viewer if we're in a subframe. |
6731 | if (mBrowsingContext->GetParent()) { |
6732 | return false; // this is a subframe load |
6733 | } |
6734 | |
6735 | // If the document does not want its presentation cached, then don't. |
6736 | RefPtr<Document> doc = mScriptGlobal->GetExtantDoc(); |
6737 | |
6738 | uint32_t bfCacheCombo = 0; |
6739 | bool canSavePresentation = |
6740 | doc->CanSavePresentation(aNewRequest, bfCacheCombo, true); |
6741 | 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" , 6741); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bfCacheCombo == 0" ")"); do { *((volatile int*)__null) = 6741; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); |
6742 | if (canSavePresentation && doc->IsTopLevelContentDocument()) { |
6743 | auto* browsingContextGroup = mBrowsingContext->Group(); |
6744 | nsTArray<RefPtr<BrowsingContext>>& topLevelContext = |
6745 | browsingContextGroup->Toplevels(); |
6746 | |
6747 | for (const auto& browsingContext : topLevelContext) { |
6748 | if (browsingContext != mBrowsingContext) { |
6749 | if (StaticPrefs::docshell_shistory_bfcache_require_no_opener()) { |
6750 | canSavePresentation = false; |
6751 | } |
6752 | bfCacheCombo |= BFCacheStatus::NOT_ONLY_TOPLEVEL_IN_BCG; |
6753 | break; |
6754 | } |
6755 | } |
6756 | } |
6757 | |
6758 | if (aReportBFCacheComboTelemetry) { |
6759 | ReportBFCacheComboTelemetry(bfCacheCombo); |
6760 | } |
6761 | return doc && canSavePresentation; |
6762 | } |
6763 | |
6764 | /* static */ |
6765 | void nsDocShell::ReportBFCacheComboTelemetry(uint32_t aCombo) { |
6766 | // There are 11 possible reasons to make a request fails to use BFCache |
6767 | // (see BFCacheStatus in dom/base/Document.h), and we'd like to record |
6768 | // the common combinations for reasons which make requests fail to use |
6769 | // BFCache. These combinations are generated based on some local browsings, |
6770 | // we need to adjust them when necessary. |
6771 | enum BFCacheStatusCombo : uint32_t { |
6772 | BFCACHE_SUCCESS, |
6773 | NOT_ONLY_TOPLEVEL = mozilla::dom::BFCacheStatus::NOT_ONLY_TOPLEVEL_IN_BCG, |
6774 | // If both unload and beforeunload listeners are presented, it'll be |
6775 | // recorded as unload |
6776 | UNLOAD = mozilla::dom::BFCacheStatus::UNLOAD_LISTENER, |
6777 | UNLOAD_REQUEST = mozilla::dom::BFCacheStatus::UNLOAD_LISTENER | |
6778 | mozilla::dom::BFCacheStatus::REQUEST, |
6779 | REQUEST = mozilla::dom::BFCacheStatus::REQUEST, |
6780 | UNLOAD_REQUEST_PEER = mozilla::dom::BFCacheStatus::UNLOAD_LISTENER | |
6781 | mozilla::dom::BFCacheStatus::REQUEST | |
6782 | mozilla::dom::BFCacheStatus::ACTIVE_PEER_CONNECTION, |
6783 | UNLOAD_REQUEST_PEER_MSE = |
6784 | mozilla::dom::BFCacheStatus::UNLOAD_LISTENER | |
6785 | mozilla::dom::BFCacheStatus::REQUEST | |
6786 | mozilla::dom::BFCacheStatus::ACTIVE_PEER_CONNECTION | |
6787 | mozilla::dom::BFCacheStatus::CONTAINS_MSE_CONTENT, |
6788 | UNLOAD_REQUEST_MSE = mozilla::dom::BFCacheStatus::UNLOAD_LISTENER | |
6789 | mozilla::dom::BFCacheStatus::REQUEST | |
6790 | mozilla::dom::BFCacheStatus::CONTAINS_MSE_CONTENT, |
6791 | SUSPENDED_UNLOAD_REQUEST_PEER = |
6792 | mozilla::dom::BFCacheStatus::SUSPENDED | |
6793 | mozilla::dom::BFCacheStatus::UNLOAD_LISTENER | |
6794 | mozilla::dom::BFCacheStatus::REQUEST | |
6795 | mozilla::dom::BFCacheStatus::ACTIVE_PEER_CONNECTION, |
6796 | REMOTE_SUBFRAMES = mozilla::dom::BFCacheStatus::CONTAINS_REMOTE_SUBFRAMES, |
6797 | BEFOREUNLOAD = mozilla::dom::BFCacheStatus::BEFOREUNLOAD_LISTENER, |
6798 | }; |
6799 | |
6800 | // Beforeunload is recorded as a blocker only if it is the only one to block |
6801 | // bfcache. |
6802 | if (aCombo != mozilla::dom::BFCacheStatus::BEFOREUNLOAD_LISTENER) { |
6803 | aCombo &= ~mozilla::dom::BFCacheStatus::BEFOREUNLOAD_LISTENER; |
6804 | } |
6805 | switch (aCombo) { |
6806 | case BFCACHE_SUCCESS: |
6807 | Telemetry::AccumulateCategorical( |
6808 | Telemetry::LABELS_BFCACHE_COMBO::BFCache_Success); |
6809 | break; |
6810 | case NOT_ONLY_TOPLEVEL: |
6811 | if (StaticPrefs::docshell_shistory_bfcache_require_no_opener()) { |
6812 | Telemetry::AccumulateCategorical( |
6813 | Telemetry::LABELS_BFCACHE_COMBO::Other); |
6814 | break; |
6815 | } |
6816 | Telemetry::AccumulateCategorical( |
6817 | Telemetry::LABELS_BFCACHE_COMBO::BFCache_Success); |
6818 | Telemetry::AccumulateCategorical( |
6819 | Telemetry::LABELS_BFCACHE_COMBO::Success_Not_Toplevel); |
6820 | break; |
6821 | case UNLOAD: |
6822 | Telemetry::AccumulateCategorical(Telemetry::LABELS_BFCACHE_COMBO::Unload); |
6823 | break; |
6824 | case BEFOREUNLOAD: |
6825 | Telemetry::AccumulateCategorical( |
6826 | Telemetry::LABELS_BFCACHE_COMBO::Beforeunload); |
6827 | break; |
6828 | case UNLOAD_REQUEST: |
6829 | Telemetry::AccumulateCategorical( |
6830 | Telemetry::LABELS_BFCACHE_COMBO::Unload_Req); |
6831 | break; |
6832 | case REQUEST: |
6833 | Telemetry::AccumulateCategorical(Telemetry::LABELS_BFCACHE_COMBO::Req); |
6834 | break; |
6835 | case UNLOAD_REQUEST_PEER: |
6836 | Telemetry::AccumulateCategorical( |
6837 | Telemetry::LABELS_BFCACHE_COMBO::Unload_Req_Peer); |
6838 | break; |
6839 | case UNLOAD_REQUEST_PEER_MSE: |
6840 | Telemetry::AccumulateCategorical( |
6841 | Telemetry::LABELS_BFCACHE_COMBO::Unload_Req_Peer_MSE); |
6842 | break; |
6843 | case UNLOAD_REQUEST_MSE: |
6844 | Telemetry::AccumulateCategorical( |
6845 | Telemetry::LABELS_BFCACHE_COMBO::Unload_Req_MSE); |
6846 | break; |
6847 | case SUSPENDED_UNLOAD_REQUEST_PEER: |
6848 | Telemetry::AccumulateCategorical( |
6849 | Telemetry::LABELS_BFCACHE_COMBO::SPD_Unload_Req_Peer); |
6850 | break; |
6851 | case REMOTE_SUBFRAMES: |
6852 | Telemetry::AccumulateCategorical( |
6853 | Telemetry::LABELS_BFCACHE_COMBO::Remote_Subframes); |
6854 | break; |
6855 | default: |
6856 | Telemetry::AccumulateCategorical(Telemetry::LABELS_BFCACHE_COMBO::Other); |
6857 | break; |
6858 | } |
6859 | }; |
6860 | |
6861 | void nsDocShell::ReattachEditorToWindow(nsISHEntry* aSHEntry) { |
6862 | 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" , 6862); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()" ")"); do { *((volatile int*)__null) = 6862; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
6863 | 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" , 6863); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mIsBeingDestroyed" ")"); do { *((volatile int*)__null) = 6863; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
6864 | |
6865 | 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" , 6866); MOZ_PretendNoReturn(); } } while (0) |
6866 | "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" , 6866); MOZ_PretendNoReturn(); } } while (0); |
6867 | 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" , 6868); MOZ_PretendNoReturn(); } } while (0) |
6868 | "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" , 6868); MOZ_PretendNoReturn(); } } while (0); |
6869 | |
6870 | if (mEditorData || !aSHEntry) { |
6871 | return; |
6872 | } |
6873 | |
6874 | mEditorData = WrapUnique(aSHEntry->ForgetEditorData()); |
6875 | if (mEditorData) { |
6876 | #ifdef DEBUG1 |
6877 | nsresult rv = |
6878 | #endif |
6879 | mEditorData->ReattachToWindow(this); |
6880 | 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" , 6880); MOZ_PretendNoReturn(); } } while (0); |
6881 | } |
6882 | } |
6883 | |
6884 | void nsDocShell::DetachEditorFromWindow() { |
6885 | if (!mEditorData || mEditorData->WaitingForLoad()) { |
6886 | // If there's nothing to detach, or if the editor data is actually set |
6887 | // up for the _new_ page that's coming in, don't detach. |
6888 | return; |
6889 | } |
6890 | |
6891 | 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" , 6892); MOZ_PretendNoReturn(); } } while (0) |
6892 | "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" , 6892); MOZ_PretendNoReturn(); } } while (0); |
6893 | |
6894 | nsresult res = mEditorData->DetachFromWindow(); |
6895 | 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" , 6895); MOZ_PretendNoReturn(); } } while (0); |
6896 | |
6897 | if (NS_SUCCEEDED(res)((bool)(__builtin_expect(!!(!NS_FAILED_impl(res)), 1)))) { |
6898 | // Make mOSHE hold the owning ref to the editor data. |
6899 | if (mOSHE) { |
6900 | 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" , 6902); 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) = 6902; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
6901 | "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" , 6902); 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) = 6902; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
6902 | "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" , 6902); 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) = 6902; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
6903 | mOSHE->SetEditorData(mEditorData.release()); |
6904 | } else { |
6905 | mEditorData = nullptr; |
6906 | } |
6907 | } |
6908 | |
6909 | #ifdef DEBUG1 |
6910 | { |
6911 | bool isEditable; |
6912 | GetEditable(&isEditable); |
6913 | 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" , 6914); MOZ_PretendNoReturn(); } } while (0) |
6914 | "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" , 6914); MOZ_PretendNoReturn(); } } while (0); |
6915 | } |
6916 | #endif // DEBUG |
6917 | } |
6918 | |
6919 | nsresult nsDocShell::CaptureState() { |
6920 | 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" , 6920); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()" ")"); do { *((volatile int*)__null) = 6920; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
6921 | |
6922 | if (!mOSHE || mOSHE == mLSHE) { |
6923 | // No entry to save into, or we're replacing the existing entry. |
6924 | return NS_ERROR_FAILURE; |
6925 | } |
6926 | |
6927 | if (!mScriptGlobal) { |
6928 | return NS_ERROR_FAILURE; |
6929 | } |
6930 | |
6931 | nsCOMPtr<nsISupports> windowState = mScriptGlobal->SaveWindowState(); |
6932 | 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" , 6932); return NS_ERROR_FAILURE; } } while (false); |
6933 | |
6934 | if (MOZ_UNLIKELY(MOZ_LOG_TEST(gPageCacheLog, LogLevel::Debug))(__builtin_expect(!!((__builtin_expect(!!(mozilla::detail::log_test (gPageCacheLog, LogLevel::Debug)), 0))), 0))) { |
6935 | nsAutoCString spec; |
6936 | nsCOMPtr<nsIURI> uri = mOSHE->GetURI(); |
6937 | if (uri) { |
6938 | uri->GetSpec(spec); |
6939 | } |
6940 | 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) |
6941 | ("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); |
6942 | } |
6943 | |
6944 | mOSHE->SetWindowState(windowState); |
6945 | |
6946 | // Suspend refresh URIs and save off the timer queue |
6947 | mOSHE->SetRefreshURIList(mSavedRefreshURIList); |
6948 | |
6949 | // Capture the current content viewer bounds. |
6950 | if (mDocumentViewer) { |
6951 | nsIntRect bounds; |
6952 | mDocumentViewer->GetBounds(bounds); |
6953 | mOSHE->SetViewerBounds(bounds); |
6954 | } |
6955 | |
6956 | // Capture the docshell hierarchy. |
6957 | mOSHE->ClearChildShells(); |
6958 | |
6959 | uint32_t childCount = mChildList.Length(); |
6960 | for (uint32_t i = 0; i < childCount; ++i) { |
6961 | nsCOMPtr<nsIDocShellTreeItem> childShell = do_QueryInterface(ChildAt(i)); |
6962 | 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" , 6962); MOZ_PretendNoReturn(); } } while (0); |
6963 | |
6964 | mOSHE->AddChildShell(childShell); |
6965 | } |
6966 | |
6967 | return NS_OK; |
6968 | } |
6969 | |
6970 | NS_IMETHODIMPnsresult |
6971 | nsDocShell::RestorePresentationEvent::Run() { |
6972 | 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" , 6972); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()" ")"); do { *((volatile int*)__null) = 6972; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
6973 | |
6974 | if (mDocShell && NS_FAILED(mDocShell->RestoreFromHistory())((bool)(__builtin_expect(!!(NS_FAILED_impl(mDocShell->RestoreFromHistory ())), 0)))) { |
6975 | NS_WARNING("RestoreFromHistory failed")NS_DebugBreak(NS_DEBUG_WARNING, "RestoreFromHistory failed", nullptr , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 6975); |
6976 | } |
6977 | return NS_OK; |
6978 | } |
6979 | |
6980 | NS_IMETHODIMPnsresult |
6981 | nsDocShell::BeginRestore(nsIDocumentViewer* aDocumentViewer, bool aTop) { |
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 | nsresult rv; |
6985 | if (!aDocumentViewer) { |
6986 | rv = EnsureDocumentViewer(); |
6987 | 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" , 6987); return rv; } } while (false); |
6988 | |
6989 | aDocumentViewer = mDocumentViewer; |
6990 | } |
6991 | |
6992 | // Dispatch events for restoring the presentation. We try to simulate |
6993 | // the progress notifications loading the document would cause, so we add |
6994 | // the document's channel to the loadgroup to initiate stateChange |
6995 | // notifications. |
6996 | |
6997 | RefPtr<Document> doc = aDocumentViewer->GetDocument(); |
6998 | if (doc) { |
6999 | nsIChannel* channel = doc->GetChannel(); |
7000 | if (channel) { |
7001 | mEODForCurrentDocument = false; |
7002 | mIsRestoringDocument = true; |
7003 | mLoadGroup->AddRequest(channel, nullptr); |
7004 | mIsRestoringDocument = false; |
7005 | } |
7006 | } |
7007 | |
7008 | if (!aTop) { |
7009 | // This point corresponds to us having gotten OnStartRequest or |
7010 | // STATE_START, so do the same thing that CreateDocumentViewer does at |
7011 | // this point to ensure that unload/pagehide events for this document |
7012 | // will fire when it's unloaded again. |
7013 | mFiredUnloadEvent = false; |
7014 | |
7015 | // For non-top frames, there is no notion of making sure that the |
7016 | // previous document is in the domwindow when STATE_START notifications |
7017 | // happen. We can just call BeginRestore for all of the child shells |
7018 | // now. |
7019 | rv = BeginRestoreChildren(); |
7020 | 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" , 7020); return rv; } } while (false); |
7021 | } |
7022 | |
7023 | return NS_OK; |
7024 | } |
7025 | |
7026 | nsresult nsDocShell::BeginRestoreChildren() { |
7027 | 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" , 7027); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()" ")"); do { *((volatile int*)__null) = 7027; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
7028 | |
7029 | for (auto* childDocLoader : mChildList.ForwardRange()) { |
7030 | nsCOMPtr<nsIDocShell> child = do_QueryObject(childDocLoader); |
7031 | if (child) { |
7032 | nsresult rv = child->BeginRestore(nullptr, false); |
7033 | 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" , 7033); return rv; } } while (false); |
7034 | } |
7035 | } |
7036 | return NS_OK; |
7037 | } |
7038 | |
7039 | NS_IMETHODIMPnsresult |
7040 | nsDocShell::FinishRestore() { |
7041 | 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" , 7041); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()" ")"); do { *((volatile int*)__null) = 7041; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
7042 | |
7043 | // First we call finishRestore() on our children. In the simulated load, |
7044 | // all of the child frames finish loading before the main document. |
7045 | |
7046 | for (auto* childDocLoader : mChildList.ForwardRange()) { |
7047 | nsCOMPtr<nsIDocShell> child = do_QueryObject(childDocLoader); |
7048 | if (child) { |
7049 | child->FinishRestore(); |
7050 | } |
7051 | } |
7052 | |
7053 | if (mOSHE && mOSHE->HasDetachedEditor()) { |
7054 | ReattachEditorToWindow(mOSHE); |
7055 | } |
7056 | |
7057 | RefPtr<Document> doc = GetDocument(); |
7058 | if (doc) { |
7059 | // Finally, we remove the request from the loadgroup. This will |
7060 | // cause onStateChange(STATE_STOP) to fire, which will fire the |
7061 | // pageshow event to the chrome. |
7062 | |
7063 | nsIChannel* channel = doc->GetChannel(); |
7064 | if (channel) { |
7065 | mIsRestoringDocument = true; |
7066 | mLoadGroup->RemoveRequest(channel, nullptr, NS_OK); |
7067 | mIsRestoringDocument = false; |
7068 | } |
7069 | } |
7070 | |
7071 | return NS_OK; |
7072 | } |
7073 | |
7074 | NS_IMETHODIMPnsresult |
7075 | nsDocShell::GetRestoringDocument(bool* aRestoring) { |
7076 | *aRestoring = mIsRestoringDocument; |
7077 | return NS_OK; |
7078 | } |
7079 | |
7080 | nsresult nsDocShell::RestorePresentation(nsISHEntry* aSHEntry, |
7081 | bool* aRestoring) { |
7082 | 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" , 7082); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()" ")"); do { *((volatile int*)__null) = 7082; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
7083 | 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" , 7083); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mIsBeingDestroyed" ")"); do { *((volatile int*)__null) = 7083; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
7084 | |
7085 | 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" , 7086); MOZ_PretendNoReturn(); } } while (0) |
7086 | "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" , 7086); MOZ_PretendNoReturn(); } } while (0); |
7087 | |
7088 | nsCOMPtr<nsIDocumentViewer> viewer = aSHEntry->GetDocumentViewer(); |
7089 | |
7090 | nsAutoCString spec; |
7091 | if (MOZ_UNLIKELY(MOZ_LOG_TEST(gPageCacheLog, LogLevel::Debug))(__builtin_expect(!!((__builtin_expect(!!(mozilla::detail::log_test (gPageCacheLog, LogLevel::Debug)), 0))), 0))) { |
7092 | nsCOMPtr<nsIURI> uri = aSHEntry->GetURI(); |
7093 | if (uri) { |
7094 | uri->GetSpec(spec); |
7095 | } |
7096 | } |
7097 | |
7098 | *aRestoring = false; |
7099 | |
7100 | if (!viewer) { |
7101 | 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) |
7102 | ("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); |
7103 | return NS_OK; |
7104 | } |
7105 | |
7106 | // We need to make sure the content viewer's container is this docshell. |
7107 | // In subframe navigation, it's possible for the docshell that the |
7108 | // content viewer was originally loaded into to be replaced with a |
7109 | // different one. We don't currently support restoring the presentation |
7110 | // in that case. |
7111 | |
7112 | nsCOMPtr<nsIDocShell> container; |
7113 | viewer->GetContainer(getter_AddRefs(container)); |
7114 | if (!::SameCOMIdentity(container, GetAsSupports(this))) { |
7115 | 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) |
7116 | ("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); |
7117 | aSHEntry->SetDocumentViewer(nullptr); |
7118 | return NS_ERROR_FAILURE; |
7119 | } |
7120 | |
7121 | 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" , 7121); MOZ_PretendNoReturn(); } } while (0); |
7122 | |
7123 | 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) |
7124 | ("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); |
7125 | |
7126 | SetHistoryEntryAndUpdateBC(Some(aSHEntry), Nothing()); |
7127 | |
7128 | // Post an event that will remove the request after we've returned |
7129 | // to the event loop. This mimics the way it is called by nsIChannel |
7130 | // implementations. |
7131 | |
7132 | // Revoke any pending restore (just in case). |
7133 | 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" , 7134); MOZ_PretendNoReturn(); } } while (0) |
7134 | "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" , 7134); MOZ_PretendNoReturn(); } } while (0); |
7135 | mRestorePresentationEvent.Revoke(); |
7136 | |
7137 | RefPtr<RestorePresentationEvent> evt = new RestorePresentationEvent(this); |
7138 | nsresult rv = Dispatch(do_AddRef(evt)); |
7139 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) { |
7140 | mRestorePresentationEvent = evt.get(); |
7141 | // The rest of the restore processing will happen on our event |
7142 | // callback. |
7143 | *aRestoring = true; |
7144 | } |
7145 | |
7146 | return rv; |
7147 | } |
7148 | |
7149 | namespace { |
7150 | class MOZ_STACK_CLASS PresentationEventForgetter { |
7151 | public: |
7152 | explicit PresentationEventForgetter( |
7153 | nsRevocableEventPtr<nsDocShell::RestorePresentationEvent>& |
7154 | aRestorePresentationEvent) |
7155 | : mRestorePresentationEvent(aRestorePresentationEvent), |
7156 | mEvent(aRestorePresentationEvent.get()) {} |
7157 | |
7158 | ~PresentationEventForgetter() { Forget(); } |
7159 | |
7160 | void Forget() { |
7161 | if (mRestorePresentationEvent.get() == mEvent) { |
7162 | mRestorePresentationEvent.Forget(); |
7163 | mEvent = nullptr; |
7164 | } |
7165 | } |
7166 | |
7167 | private: |
7168 | nsRevocableEventPtr<nsDocShell::RestorePresentationEvent>& |
7169 | mRestorePresentationEvent; |
7170 | RefPtr<nsDocShell::RestorePresentationEvent> mEvent; |
7171 | }; |
7172 | |
7173 | } // namespace |
7174 | |
7175 | bool nsDocShell::SandboxFlagsImplyCookies(const uint32_t& aSandboxFlags) { |
7176 | return (aSandboxFlags & (SANDBOXED_ORIGIN | SANDBOXED_SCRIPTS)) == 0; |
7177 | } |
7178 | |
7179 | nsresult nsDocShell::RestoreFromHistory() { |
7180 | 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" , 7180); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()" ")"); do { *((volatile int*)__null) = 7180; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
7181 | 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" , 7181); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mRestorePresentationEvent.IsPending()" ")"); do { *((volatile int*)__null) = 7181; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
7182 | PresentationEventForgetter forgetter(mRestorePresentationEvent); |
7183 | |
7184 | // This section of code follows the same ordering as CreateDocumentViewer. |
7185 | if (!mLSHE) { |
7186 | return NS_ERROR_FAILURE; |
7187 | } |
7188 | |
7189 | nsCOMPtr<nsIDocumentViewer> viewer = mLSHE->GetDocumentViewer(); |
7190 | if (!viewer) { |
7191 | return NS_ERROR_FAILURE; |
7192 | } |
7193 | |
7194 | if (mSavingOldViewer) { |
7195 | // We determined that it was safe to cache the document presentation |
7196 | // at the time we initiated the new load. We need to check whether |
7197 | // it's still safe to do so, since there may have been DOM mutations |
7198 | // or new requests initiated. |
7199 | RefPtr<Document> doc = viewer->GetDocument(); |
7200 | nsIRequest* request = nullptr; |
7201 | if (doc) { |
7202 | request = doc->GetChannel(); |
7203 | } |
7204 | mSavingOldViewer = CanSavePresentation( |
7205 | mLoadType, request, doc, /* aReportBFCacheComboTelemetry */ false); |
7206 | } |
7207 | |
7208 | // Protect against mLSHE going away via a load triggered from |
7209 | // pagehide or unload. |
7210 | nsCOMPtr<nsISHEntry> origLSHE = mLSHE; |
7211 | |
7212 | // Make sure to blow away our mLoadingURI just in case. No loads |
7213 | // from inside this pagehide. |
7214 | mLoadingURI = nullptr; |
7215 | |
7216 | // Notify the old content viewer that it's being hidden. |
7217 | FirePageHideNotification(!mSavingOldViewer); |
7218 | // pagehide notification might destroy this docshell. |
7219 | if (mIsBeingDestroyed) { |
7220 | return NS_ERROR_DOCSHELL_DYING; |
7221 | } |
7222 | |
7223 | // If mLSHE was changed as a result of the pagehide event, then |
7224 | // something else was loaded. Don't finish restoring. |
7225 | if (mLSHE != origLSHE) { |
7226 | return NS_OK; |
7227 | } |
7228 | |
7229 | // Add the request to our load group. We do this before swapping out |
7230 | // the content viewers so that consumers of STATE_START can access |
7231 | // the old document. We only deal with the toplevel load at this time -- |
7232 | // to be consistent with normal document loading, subframes cannot start |
7233 | // loading until after data arrives, which is after STATE_START completes. |
7234 | |
7235 | RefPtr<RestorePresentationEvent> currentPresentationRestoration = |
7236 | mRestorePresentationEvent.get(); |
7237 | Stop(); |
7238 | // Make sure we're still restoring the same presentation. |
7239 | // If we aren't, docshell is in process doing another load already. |
7240 | 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" , 7241); return NS_ERROR_UNEXPECTED; } } while (false) |
7241 | 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" , 7241); return NS_ERROR_UNEXPECTED; } } while (false); |
7242 | BeginRestore(viewer, true); |
7243 | 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" , 7244); return NS_ERROR_UNEXPECTED; } } while (false) |
7244 | 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" , 7244); return NS_ERROR_UNEXPECTED; } } while (false); |
7245 | forgetter.Forget(); |
7246 | |
7247 | // Set mFiredUnloadEvent = false so that the unload handler for the |
7248 | // *new* document will fire. |
7249 | mFiredUnloadEvent = false; |
7250 | |
7251 | mURIResultedInDocument = true; |
7252 | RefPtr<ChildSHistory> rootSH = GetRootSessionHistory(); |
7253 | if (rootSH) { |
7254 | mPreviousEntryIndex = rootSH->Index(); |
7255 | rootSH->LegacySHistory()->UpdateIndex(); |
7256 | mLoadedEntryIndex = rootSH->Index(); |
7257 | 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) |
7258 | ("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) |
7259 | 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); |
7260 | } |
7261 | |
7262 | // Rather than call Embed(), we will retrieve the viewer from the session |
7263 | // history entry and swap it in. |
7264 | // XXX can we refactor this so that we can just call Embed()? |
7265 | PersistLayoutHistoryState(); |
7266 | nsresult rv; |
7267 | if (mDocumentViewer) { |
7268 | if (mSavingOldViewer && NS_FAILED(CaptureState())((bool)(__builtin_expect(!!(NS_FAILED_impl(CaptureState())), 0 )))) { |
7269 | if (mOSHE) { |
7270 | mOSHE->SyncPresentationState(); |
7271 | } |
7272 | mSavingOldViewer = false; |
7273 | } |
7274 | } |
7275 | |
7276 | mSavedRefreshURIList = nullptr; |
7277 | |
7278 | // In cases where we use a transient about:blank viewer between loads, |
7279 | // we never show the transient viewer, so _its_ previous viewer is never |
7280 | // unhooked from the view hierarchy. Destroy any such previous viewer now, |
7281 | // before we grab the root view sibling, so that we don't grab a view |
7282 | // that's about to go away. |
7283 | |
7284 | if (mDocumentViewer) { |
7285 | // Make sure to hold a strong ref to previousViewer here while we |
7286 | // drop the reference to it from mDocumentViewer. |
7287 | nsCOMPtr<nsIDocumentViewer> previousViewer = |
7288 | mDocumentViewer->GetPreviousViewer(); |
7289 | if (previousViewer) { |
7290 | mDocumentViewer->SetPreviousViewer(nullptr); |
7291 | previousViewer->Destroy(); |
7292 | } |
7293 | } |
7294 | |
7295 | // Save off the root view's parent and sibling so that we can insert the |
7296 | // new content viewer's root view at the same position. Also save the |
7297 | // bounds of the root view's widget. |
7298 | |
7299 | nsView* rootViewSibling = nullptr; |
7300 | nsView* rootViewParent = nullptr; |
7301 | nsIntRect newBounds(0, 0, 0, 0); |
7302 | |
7303 | PresShell* oldPresShell = GetPresShell(); |
7304 | if (oldPresShell) { |
7305 | nsViewManager* vm = oldPresShell->GetViewManager(); |
7306 | if (vm) { |
7307 | nsView* oldRootView = vm->GetRootView(); |
7308 | |
7309 | if (oldRootView) { |
7310 | rootViewSibling = oldRootView->GetNextSibling(); |
7311 | rootViewParent = oldRootView->GetParent(); |
7312 | |
7313 | mDocumentViewer->GetBounds(newBounds); |
7314 | } |
7315 | } |
7316 | } |
7317 | |
7318 | nsCOMPtr<nsIContent> container; |
7319 | RefPtr<Document> sibling; |
7320 | if (rootViewParent && rootViewParent->GetParent()) { |
7321 | nsIFrame* frame = rootViewParent->GetParent()->GetFrame(); |
7322 | container = frame ? frame->GetContent() : nullptr; |
7323 | } |
7324 | if (rootViewSibling) { |
7325 | nsIFrame* frame = rootViewSibling->GetFrame(); |
7326 | sibling = frame ? frame->PresShell()->GetDocument() : nullptr; |
7327 | } |
7328 | |
7329 | // Transfer ownership to mDocumentViewer. By ensuring that either the |
7330 | // docshell or the session history, but not both, have references to the |
7331 | // content viewer, we prevent the viewer from being torn down after |
7332 | // Destroy() is called. |
7333 | |
7334 | if (mDocumentViewer) { |
7335 | mDocumentViewer->Close(mSavingOldViewer ? mOSHE.get() : nullptr); |
7336 | viewer->SetPreviousViewer(mDocumentViewer); |
7337 | } |
7338 | if (mOSHE && (!mDocumentViewer || !mSavingOldViewer)) { |
7339 | // We don't plan to save a viewer in mOSHE; tell it to drop |
7340 | // any other state it's holding. |
7341 | mOSHE->SyncPresentationState(); |
7342 | } |
7343 | |
7344 | // Order the mDocumentViewer setup just like Embed does. |
7345 | mDocumentViewer = nullptr; |
7346 | |
7347 | // Now that we're about to switch documents, forget all of our children. |
7348 | // Note that we cached them as needed up in CaptureState above. |
7349 | DestroyChildren(); |
7350 | |
7351 | mDocumentViewer.swap(viewer); |
7352 | |
7353 | // Grab all of the related presentation from the SHEntry now. |
7354 | // Clearing the viewer from the SHEntry will clear all of this state. |
7355 | nsCOMPtr<nsISupports> windowState = mLSHE->GetWindowState(); |
7356 | mLSHE->SetWindowState(nullptr); |
7357 | |
7358 | bool sticky = mLSHE->GetSticky(); |
7359 | |
7360 | RefPtr<Document> document = mDocumentViewer->GetDocument(); |
7361 | |
7362 | nsCOMArray<nsIDocShellTreeItem> childShells; |
7363 | int32_t i = 0; |
7364 | nsCOMPtr<nsIDocShellTreeItem> child; |
7365 | while (NS_SUCCEEDED(mLSHE->ChildShellAt(i++, getter_AddRefs(child)))((bool)(__builtin_expect(!!(!NS_FAILED_impl(mLSHE->ChildShellAt (i++, getter_AddRefs(child)))), 1))) && |
7366 | child) { |
7367 | childShells.AppendObject(child); |
7368 | } |
7369 | |
7370 | // get the previous content viewer size |
7371 | nsIntRect oldBounds(0, 0, 0, 0); |
7372 | mLSHE->GetViewerBounds(oldBounds); |
7373 | |
7374 | // Restore the refresh URI list. The refresh timers will be restarted |
7375 | // when EndPageLoad() is called. |
7376 | nsCOMPtr<nsIMutableArray> refreshURIList = mLSHE->GetRefreshURIList(); |
7377 | |
7378 | // Reattach to the window object. |
7379 | mIsRestoringDocument = true; // for MediaDocument::BecomeInteractive |
7380 | rv = mDocumentViewer->Open(windowState, mLSHE); |
7381 | mIsRestoringDocument = false; |
7382 | |
7383 | // Hack to keep nsDocShellEditorData alive across the |
7384 | // SetContentViewer(nullptr) call below. |
7385 | UniquePtr<nsDocShellEditorData> data(mLSHE->ForgetEditorData()); |
7386 | |
7387 | // Now remove it from the cached presentation. |
7388 | mLSHE->SetDocumentViewer(nullptr); |
7389 | mEODForCurrentDocument = false; |
7390 | |
7391 | mLSHE->SetEditorData(data.release()); |
7392 | |
7393 | #ifdef DEBUG1 |
7394 | { |
7395 | nsCOMPtr<nsIMutableArray> refreshURIs = mLSHE->GetRefreshURIList(); |
7396 | nsCOMPtr<nsIDocShellTreeItem> childShell; |
7397 | mLSHE->ChildShellAt(0, getter_AddRefs(childShell)); |
7398 | 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" , 7399); MOZ_PretendNoReturn(); } } while (0) |
7399 | "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" , 7399); MOZ_PretendNoReturn(); } } while (0); |
7400 | } |
7401 | #endif |
7402 | |
7403 | // Restore the sticky state of the viewer. The viewer has set this state |
7404 | // on the history entry in Destroy() just before marking itself non-sticky, |
7405 | // to avoid teardown of the presentation. |
7406 | mDocumentViewer->SetSticky(sticky); |
7407 | |
7408 | 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" , 7408); return rv; } } while (false); |
7409 | |
7410 | // mLSHE is now our currently-loaded document. |
7411 | SetHistoryEntryAndUpdateBC(Nothing(), Some<nsISHEntry*>(mLSHE)); |
7412 | |
7413 | // We aren't going to restore any items from the LayoutHistoryState, |
7414 | // but we don't want them to stay around in case the page is reloaded. |
7415 | SetLayoutHistoryState(nullptr); |
7416 | |
7417 | // This is the end of our Embed() replacement |
7418 | |
7419 | mSavingOldViewer = false; |
7420 | mEODForCurrentDocument = false; |
7421 | |
7422 | if (document) { |
7423 | RefPtr<nsDocShell> parent = GetInProcessParentDocshell(); |
7424 | if (parent) { |
7425 | RefPtr<Document> d = parent->GetDocument(); |
7426 | if (d) { |
7427 | if (d->EventHandlingSuppressed()) { |
7428 | document->SuppressEventHandling(d->EventHandlingSuppressed()); |
7429 | } |
7430 | } |
7431 | } |
7432 | |
7433 | // Use the uri from the mLSHE we had when we entered this function |
7434 | // (which need not match the document's URI if anchors are involved), |
7435 | // since that's the history entry we're loading. Note that if we use |
7436 | // origLSHE we don't have to worry about whether the entry in question |
7437 | // is still mLSHE or whether it's now mOSHE. |
7438 | nsCOMPtr<nsIURI> uri = origLSHE->GetURI(); |
7439 | SetCurrentURI(uri, document->GetChannel(), /* aFireLocationChange */ true, |
7440 | /* aIsInitialAboutBlank */ false, |
7441 | /* aLocationFlags */ 0); |
7442 | } |
7443 | |
7444 | // This is the end of our CreateDocumentViewer() replacement. |
7445 | // Now we simulate a load. First, we restore the state of the javascript |
7446 | // window object. |
7447 | nsCOMPtr<nsPIDOMWindowOuter> privWin = GetWindow(); |
7448 | 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" , 7448); MOZ_PretendNoReturn(); } } while (0); |
7449 | |
7450 | // Now, dispatch a title change event which would happen as the |
7451 | // <head> is parsed. |
7452 | document->NotifyPossibleTitleChange(false); |
7453 | |
7454 | // Now we simulate appending child docshells for subframes. |
7455 | for (i = 0; i < childShells.Count(); ++i) { |
7456 | nsIDocShellTreeItem* childItem = childShells.ObjectAt(i); |
7457 | nsCOMPtr<nsIDocShell> childShell = do_QueryInterface(childItem); |
7458 | |
7459 | // Make sure to not clobber the state of the child. Since AddChild |
7460 | // always clobbers it, save it off first. |
7461 | bool allowRedirects; |
7462 | childShell->GetAllowMetaRedirects(&allowRedirects); |
7463 | |
7464 | bool allowSubframes; |
7465 | childShell->GetAllowSubframes(&allowSubframes); |
7466 | |
7467 | bool allowImages; |
7468 | childShell->GetAllowImages(&allowImages); |
7469 | |
7470 | bool allowMedia = childShell->GetAllowMedia(); |
7471 | |
7472 | bool allowDNSPrefetch; |
7473 | childShell->GetAllowDNSPrefetch(&allowDNSPrefetch); |
7474 | |
7475 | bool allowContentRetargeting = childShell->GetAllowContentRetargeting(); |
7476 | bool allowContentRetargetingOnChildren = |
7477 | childShell->GetAllowContentRetargetingOnChildren(); |
7478 | |
7479 | // this.AddChild(child) calls child.SetDocLoaderParent(this), meaning that |
7480 | // the child inherits our state. Among other things, this means that the |
7481 | // child inherits our mPrivateBrowsingId, which is what we want. |
7482 | AddChild(childItem); |
7483 | |
7484 | childShell->SetAllowMetaRedirects(allowRedirects); |
7485 | childShell->SetAllowSubframes(allowSubframes); |
7486 | childShell->SetAllowImages(allowImages); |
7487 | childShell->SetAllowMedia(allowMedia); |
7488 | childShell->SetAllowDNSPrefetch(allowDNSPrefetch); |
7489 | childShell->SetAllowContentRetargeting(allowContentRetargeting); |
7490 | childShell->SetAllowContentRetargetingOnChildren( |
7491 | allowContentRetargetingOnChildren); |
7492 | |
7493 | rv = childShell->BeginRestore(nullptr, false); |
7494 | 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" , 7494); return rv; } } while (false); |
7495 | } |
7496 | |
7497 | // Make sure to restore the window state after adding the child shells back |
7498 | // to the tree. This is necessary for Thaw() and Resume() to propagate |
7499 | // properly. |
7500 | rv = privWin->RestoreWindowState(windowState); |
7501 | 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" , 7501); return rv; } } while (false); |
7502 | |
7503 | RefPtr<PresShell> presShell = GetPresShell(); |
7504 | |
7505 | // We may be displayed on a different monitor (or in a different |
7506 | // HiDPI mode) than when we got into the history list. So we need |
7507 | // to check if this has happened. See bug 838239. |
7508 | |
7509 | // Because the prescontext normally handles resolution changes via |
7510 | // a runnable (see nsPresContext::UIResolutionChanged), its device |
7511 | // context won't be -immediately- updated as a result of calling |
7512 | // presShell->BackingScaleFactorChanged(). |
7513 | |
7514 | // But we depend on that device context when adjusting the view size |
7515 | // via mDocumentViewer->SetBounds(newBounds) below. So we need to |
7516 | // explicitly tell it to check for changed resolution here. |
7517 | if (presShell) { |
7518 | RefPtr<nsPresContext> pc = presShell->GetPresContext(); |
7519 | if (pc->DeviceContext()->CheckDPIChange()) { |
7520 | presShell->BackingScaleFactorChanged(); |
7521 | } |
7522 | // Recompute zoom and text-zoom and such. |
7523 | pc->RecomputeBrowsingContextDependentData(); |
7524 | } |
7525 | |
7526 | nsViewManager* newVM = presShell ? presShell->GetViewManager() : nullptr; |
7527 | nsView* newRootView = newVM ? newVM->GetRootView() : nullptr; |
7528 | |
7529 | // Insert the new root view at the correct location in the view tree. |
7530 | if (container) { |
7531 | nsSubDocumentFrame* subDocFrame = |
7532 | do_QueryFrame(container->GetPrimaryFrame()); |
7533 | rootViewParent = subDocFrame ? subDocFrame->EnsureInnerView() : nullptr; |
7534 | } else { |
7535 | rootViewParent = nullptr; |
7536 | } |
7537 | if (sibling && sibling->GetPresShell() && |
7538 | sibling->GetPresShell()->GetViewManager()) { |
7539 | rootViewSibling = sibling->GetPresShell()->GetViewManager()->GetRootView(); |
7540 | } else { |
7541 | rootViewSibling = nullptr; |
7542 | } |
7543 | if (rootViewParent && newRootView && |
7544 | newRootView->GetParent() != rootViewParent) { |
7545 | nsViewManager* parentVM = rootViewParent->GetViewManager(); |
7546 | if (parentVM) { |
7547 | // InsertChild(parent, child, sib, true) inserts the child after |
7548 | // sib in content order, which is before sib in view order. BUT |
7549 | // when sib is null it inserts at the end of the the document |
7550 | // order, i.e., first in view order. But when oldRootSibling is |
7551 | // null, the old root as at the end of the view list --- last in |
7552 | // content order --- and we want to call InsertChild(parent, child, |
7553 | // nullptr, false) in that case. |
7554 | parentVM->InsertChild(rootViewParent, newRootView, rootViewSibling, |
7555 | rootViewSibling ? true : false); |
7556 | |
7557 | 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" , 7558); MOZ_PretendNoReturn(); } } while (0) |
7558 | "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" , 7558); MOZ_PretendNoReturn(); } } while (0); |
7559 | } |
7560 | } |
7561 | |
7562 | nsCOMPtr<nsPIDOMWindowInner> privWinInner = privWin->GetCurrentInnerWindow(); |
7563 | |
7564 | // If parent is suspended, increase suspension count. |
7565 | // This can't be done as early as event suppression since this |
7566 | // depends on docshell tree. |
7567 | privWinInner->SyncStateFromParentWindow(); |
7568 | |
7569 | // Now that all of the child docshells have been put into place, we can |
7570 | // restart the timers for the window and all of the child frames. |
7571 | privWinInner->Resume(); |
7572 | |
7573 | // Now that we have found the inner window of the page restored |
7574 | // from the history, we have to make sure that |
7575 | // performance.navigation.type is 2. |
7576 | Performance* performance = privWinInner->GetPerformance(); |
7577 | if (performance) { |
7578 | performance->GetDOMTiming()->NotifyRestoreStart(); |
7579 | } |
7580 | |
7581 | // Restore the refresh URI list. The refresh timers will be restarted |
7582 | // when EndPageLoad() is called. |
7583 | mRefreshURIList = refreshURIList; |
7584 | |
7585 | // Meta-refresh timers have been restarted for this shell, but not |
7586 | // for our children. Walk the child shells and restart their timers. |
7587 | for (auto* childDocLoader : mChildList.ForwardRange()) { |
7588 | nsCOMPtr<nsIDocShell> child = do_QueryObject(childDocLoader); |
7589 | if (child) { |
7590 | child->ResumeRefreshURIs(); |
7591 | } |
7592 | } |
7593 | |
7594 | // Make sure this presentation is the same size as the previous |
7595 | // presentation. If this is not the same size we showed it at last time, |
7596 | // then we need to resize the widget. |
7597 | |
7598 | // XXXbryner This interacts poorly with Firefox's infobar. If the old |
7599 | // presentation had the infobar visible, then we will resize the new |
7600 | // presentation to that smaller size. However, firing the locationchanged |
7601 | // event will hide the infobar, which will immediately resize the window |
7602 | // back to the larger size. A future optimization might be to restore |
7603 | // the presentation at the "wrong" size, then fire the locationchanged |
7604 | // event and check whether the docshell's new size is the same as the |
7605 | // cached viewer size (skipping the resize if they are equal). |
7606 | |
7607 | if (newRootView) { |
7608 | if (!newBounds.IsEmpty() && !newBounds.IsEqualEdges(oldBounds)) { |
7609 | 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) |
7610 | ("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) |
7611 | 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); |
7612 | mDocumentViewer->SetBounds(newBounds); |
7613 | } else if (ScrollContainerFrame* sf = |
7614 | presShell->GetRootScrollContainerFrame()) { |
7615 | sf->PostScrolledAreaEventForCurrentArea(); |
7616 | } |
7617 | } |
7618 | |
7619 | // The FinishRestore call below can kill these, null them out so we don't |
7620 | // have invalid pointer lying around. |
7621 | newRootView = rootViewSibling = rootViewParent = nullptr; |
7622 | newVM = nullptr; |
7623 | |
7624 | // If the IsUnderHiddenEmbedderElement() state has been changed, we need to |
7625 | // update it. |
7626 | if (oldPresShell && presShell && |
7627 | presShell->IsUnderHiddenEmbedderElement() != |
7628 | oldPresShell->IsUnderHiddenEmbedderElement()) { |
7629 | presShell->SetIsUnderHiddenEmbedderElement( |
7630 | oldPresShell->IsUnderHiddenEmbedderElement()); |
7631 | } |
7632 | |
7633 | // Simulate the completion of the load. |
7634 | nsDocShell::FinishRestore(); |
7635 | |
7636 | // Restart plugins, and paint the content. |
7637 | if (presShell) { |
7638 | presShell->Thaw(); |
7639 | } |
7640 | |
7641 | return privWin->FireDelayedDOMEvents(true); |
7642 | } |
7643 | |
7644 | nsresult nsDocShell::CreateDocumentViewer(const nsACString& aContentType, |
7645 | nsIRequest* aRequest, |
7646 | nsIStreamListener** aContentHandler) { |
7647 | *aContentHandler = nullptr; |
7648 | |
7649 | if (!mTreeOwner || mIsBeingDestroyed) { |
7650 | // If we don't have a tree owner, then we're in the process of being |
7651 | // destroyed. Rather than continue trying to load something, just give up. |
7652 | return NS_ERROR_DOCSHELL_DYING; |
7653 | } |
7654 | |
7655 | if (!mBrowsingContext->AncestorsAreCurrent() || |
7656 | mBrowsingContext->IsInBFCache()) { |
7657 | mBrowsingContext->RemoveRootFromBFCacheSync(); |
7658 | return NS_ERROR_NOT_AVAILABLE; |
7659 | } |
7660 | |
7661 | // Can we check the content type of the current content viewer |
7662 | // and reuse it without destroying it and re-creating it? |
7663 | |
7664 | 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" , 7664); MOZ_PretendNoReturn(); } } while (0); |
7665 | |
7666 | // Instantiate the content viewer object |
7667 | nsCOMPtr<nsIDocumentViewer> viewer; |
7668 | nsresult rv = NewDocumentViewerObj(aContentType, aRequest, mLoadGroup, |
7669 | aContentHandler, getter_AddRefs(viewer)); |
7670 | |
7671 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
7672 | return rv; |
7673 | } |
7674 | |
7675 | // Notify the current document that it is about to be unloaded!! |
7676 | // |
7677 | // It is important to fire the unload() notification *before* any state |
7678 | // is changed within the DocShell - otherwise, javascript will get the |
7679 | // wrong information :-( |
7680 | // |
7681 | |
7682 | if (mSavingOldViewer) { |
7683 | // We determined that it was safe to cache the document presentation |
7684 | // at the time we initiated the new load. We need to check whether |
7685 | // it's still safe to do so, since there may have been DOM mutations |
7686 | // or new requests initiated. |
7687 | RefPtr<Document> doc = viewer->GetDocument(); |
7688 | mSavingOldViewer = CanSavePresentation( |
7689 | mLoadType, aRequest, doc, /* aReportBFCacheComboTelemetry */ false); |
7690 | } |
7691 | |
7692 | 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" , 7692); MOZ_PretendNoReturn(); } } while (0); |
7693 | |
7694 | nsCOMPtr<nsIChannel> aOpenedChannel = do_QueryInterface(aRequest); |
7695 | if (aOpenedChannel) { |
7696 | aOpenedChannel->GetURI(getter_AddRefs(mLoadingURI)); |
7697 | } |
7698 | |
7699 | // Grab the current URI, we need to pass it to Embed, and OnNewURI will reset |
7700 | // it before we do call Embed. |
7701 | nsCOMPtr<nsIURI> previousURI = mCurrentURI; |
7702 | |
7703 | FirePageHideNotification(!mSavingOldViewer); |
7704 | if (mIsBeingDestroyed) { |
7705 | // Force to stop the newly created orphaned viewer. |
7706 | viewer->Stop(); |
7707 | return NS_ERROR_DOCSHELL_DYING; |
7708 | } |
7709 | mLoadingURI = nullptr; |
7710 | |
7711 | // Set mFiredUnloadEvent = false so that the unload handler for the |
7712 | // *new* document will fire. |
7713 | mFiredUnloadEvent = false; |
7714 | |
7715 | // we've created a new document so go ahead and call |
7716 | // OnNewURI(), but don't fire OnLocationChange() |
7717 | // notifications before we've called Embed(). See bug 284993. |
7718 | mURIResultedInDocument = true; |
7719 | bool errorOnLocationChangeNeeded = false; |
7720 | nsCOMPtr<nsIChannel> failedChannel = mFailedChannel; |
7721 | nsCOMPtr<nsIURI> failedURI; |
7722 | |
7723 | if (mLoadType == LOAD_ERROR_PAGE) { |
7724 | // We need to set the SH entry and our current URI here and not |
7725 | // at the moment we load the page. We want the same behavior |
7726 | // of Stop() as for a normal page load. See bug 514232 for details. |
7727 | |
7728 | // Revert mLoadType to load type to state the page load failed, |
7729 | // following function calls need it. |
7730 | mLoadType = mFailedLoadType; |
7731 | |
7732 | Document* doc = viewer->GetDocument(); |
7733 | if (doc) { |
7734 | doc->SetFailedChannel(failedChannel); |
7735 | } |
7736 | |
7737 | nsCOMPtr<nsIPrincipal> triggeringPrincipal; |
7738 | if (failedChannel) { |
7739 | // Make sure we have a URI to set currentURI. |
7740 | NS_GetFinalChannelURI(failedChannel, getter_AddRefs(failedURI)); |
7741 | } else { |
7742 | // if there is no failed channel we have to explicitly provide |
7743 | // a triggeringPrincipal for the history entry. |
7744 | triggeringPrincipal = nsContentUtils::GetSystemPrincipal(); |
7745 | } |
7746 | |
7747 | if (!failedURI) { |
7748 | failedURI = mFailedURI; |
7749 | } |
7750 | if (!failedURI) { |
7751 | // We need a URI object to store a session history entry, so make up a URI |
7752 | NS_NewURI(getter_AddRefs(failedURI), "about:blank"); |
7753 | } |
7754 | |
7755 | // When we don't have failedURI, something wrong will happen. See |
7756 | // bug 291876. |
7757 | 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" , 7757); AnnotateMozCrashReason("MOZ_ASSERT" "(" "failedURI" ") (" "We don't have a URI for history APIs." ")"); do { *((volatile int*)__null) = 7757; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
7758 | |
7759 | mFailedChannel = nullptr; |
7760 | mFailedURI = nullptr; |
7761 | |
7762 | // Create an shistory entry for the old load. |
7763 | if (failedURI) { |
7764 | errorOnLocationChangeNeeded = |
7765 | OnNewURI(failedURI, failedChannel, triggeringPrincipal, nullptr, |
7766 | nullptr, nullptr, false, false); |
7767 | } |
7768 | |
7769 | // Be sure to have a correct mLSHE, it may have been cleared by |
7770 | // EndPageLoad. See bug 302115. |
7771 | ChildSHistory* shistory = GetSessionHistory(); |
7772 | if (!mozilla::SessionHistoryInParent() && shistory && !mLSHE) { |
7773 | int32_t idx = shistory->LegacySHistory()->GetRequestedIndex(); |
7774 | if (idx == -1) { |
7775 | idx = shistory->Index(); |
7776 | } |
7777 | shistory->LegacySHistory()->GetEntryAtIndex(idx, getter_AddRefs(mLSHE)); |
7778 | } |
7779 | |
7780 | mLoadType = LOAD_ERROR_PAGE; |
7781 | } |
7782 | |
7783 | nsCOMPtr<nsIURI> finalURI; |
7784 | // If this a redirect, use the final url (uri) |
7785 | // else use the original url |
7786 | // |
7787 | // Note that this should match what documents do (see Document::Reset). |
7788 | NS_GetFinalChannelURI(aOpenedChannel, getter_AddRefs(finalURI)); |
7789 | |
7790 | bool onLocationChangeNeeded = false; |
7791 | if (finalURI) { |
7792 | // Pass false for aCloneSHChildren, since we're loading a new page here. |
7793 | onLocationChangeNeeded = OnNewURI(finalURI, aOpenedChannel, nullptr, |
7794 | nullptr, nullptr, nullptr, true, false); |
7795 | } |
7796 | |
7797 | // let's try resetting the load group if we need to... |
7798 | nsCOMPtr<nsILoadGroup> currentLoadGroup; |
7799 | 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" , 7801); return NS_ERROR_FAILURE; } } while (false) |
7800 | 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" , 7801); return NS_ERROR_FAILURE; } } while (false) |
7801 | 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" , 7801); return NS_ERROR_FAILURE; } } while (false); |
7802 | |
7803 | if (currentLoadGroup != mLoadGroup) { |
7804 | nsLoadFlags loadFlags = 0; |
7805 | |
7806 | // Cancel any URIs that are currently loading... |
7807 | // XXX: Need to do this eventually Stop(); |
7808 | // |
7809 | // Retarget the document to this loadgroup... |
7810 | // |
7811 | /* First attach the channel to the right loadgroup |
7812 | * and then remove from the old loadgroup. This |
7813 | * puts the notifications in the right order and |
7814 | * we don't null-out mLSHE in OnStateChange() for |
7815 | * all redirected urls |
7816 | */ |
7817 | aOpenedChannel->SetLoadGroup(mLoadGroup); |
7818 | |
7819 | // Mark the channel as being a document URI... |
7820 | aOpenedChannel->GetLoadFlags(&loadFlags); |
7821 | loadFlags |= nsIChannel::LOAD_DOCUMENT_URI; |
7822 | nsCOMPtr<nsILoadInfo> loadInfo = aOpenedChannel->LoadInfo(); |
7823 | if (SandboxFlagsImplyCookies(loadInfo->GetSandboxFlags())) { |
7824 | loadFlags |= nsIRequest::LOAD_DOCUMENT_NEEDS_COOKIE; |
7825 | } |
7826 | |
7827 | aOpenedChannel->SetLoadFlags(loadFlags); |
7828 | |
7829 | mLoadGroup->AddRequest(aRequest, nullptr); |
7830 | if (currentLoadGroup) { |
7831 | currentLoadGroup->RemoveRequest(aRequest, nullptr, NS_BINDING_RETARGETED); |
7832 | } |
7833 | |
7834 | // Update the notification callbacks, so that progress and |
7835 | // status information are sent to the right docshell... |
7836 | aOpenedChannel->SetNotificationCallbacks(this); |
7837 | } |
7838 | |
7839 | 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" , 7842); return NS_ERROR_FAILURE; } } while (false) |
7840 | 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" , 7842); return NS_ERROR_FAILURE; } } while (false) |
7841 | 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" , 7842); return NS_ERROR_FAILURE; } } while (false) |
7842 | 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" , 7842); return NS_ERROR_FAILURE; } } while (false); |
7843 | |
7844 | if (!mBrowsingContext->GetHasLoadedNonInitialDocument()) { |
7845 | 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" , 7845); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false" ") (" "NS_SUCCEEDED(mBrowsingContext->SetHasLoadedNonInitialDocument(true))" ")"); do { *((volatile int*)__null) = 7845; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); |
7846 | } |
7847 | |
7848 | mSavedRefreshURIList = nullptr; |
7849 | mSavingOldViewer = false; |
7850 | mEODForCurrentDocument = false; |
7851 | |
7852 | // if this document is part of a multipart document, |
7853 | // the ID can be used to distinguish it from the other parts. |
7854 | nsCOMPtr<nsIMultiPartChannel> multiPartChannel(do_QueryInterface(aRequest)); |
7855 | if (multiPartChannel) { |
7856 | if (PresShell* presShell = GetPresShell()) { |
7857 | if (Document* doc = presShell->GetDocument()) { |
7858 | uint32_t partID; |
7859 | multiPartChannel->GetPartID(&partID); |
7860 | doc->SetPartID(partID); |
7861 | } |
7862 | } |
7863 | } |
7864 | |
7865 | if (errorOnLocationChangeNeeded) { |
7866 | FireOnLocationChange(this, failedChannel, failedURI, |
7867 | LOCATION_CHANGE_ERROR_PAGE); |
7868 | } else if (onLocationChangeNeeded) { |
7869 | uint32_t locationFlags = |
7870 | (mLoadType & LOAD_CMD_RELOAD) ? uint32_t(LOCATION_CHANGE_RELOAD) : 0; |
7871 | FireOnLocationChange(this, aRequest, mCurrentURI, locationFlags); |
7872 | } |
7873 | |
7874 | return NS_OK; |
7875 | } |
7876 | |
7877 | nsresult nsDocShell::NewDocumentViewerObj(const nsACString& aContentType, |
7878 | nsIRequest* aRequest, |
7879 | nsILoadGroup* aLoadGroup, |
7880 | nsIStreamListener** aContentHandler, |
7881 | nsIDocumentViewer** aViewer) { |
7882 | nsCOMPtr<nsIChannel> aOpenedChannel = do_QueryInterface(aRequest); |
7883 | |
7884 | nsCOMPtr<nsIDocumentLoaderFactory> docLoaderFactory = |
7885 | nsContentUtils::FindInternalDocumentViewer(aContentType); |
7886 | if (!docLoaderFactory) { |
7887 | return NS_ERROR_FAILURE; |
7888 | } |
7889 | |
7890 | // Now create an instance of the content viewer nsLayoutDLF makes the |
7891 | // determination if it should be a "view-source" instead of "view" |
7892 | nsresult rv = docLoaderFactory->CreateInstance( |
7893 | "view", aOpenedChannel, aLoadGroup, aContentType, this, nullptr, |
7894 | aContentHandler, aViewer); |
7895 | 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" , 7895); return rv; } } while (false); |
7896 | |
7897 | (*aViewer)->SetContainer(this); |
7898 | return NS_OK; |
7899 | } |
7900 | |
7901 | nsresult nsDocShell::SetupNewViewer(nsIDocumentViewer* aNewViewer, |
7902 | WindowGlobalChild* aWindowActor) { |
7903 | 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" , 7903); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mIsBeingDestroyed" ")"); do { *((volatile int*)__null) = 7903; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
7904 | |
7905 | // |
7906 | // Copy content viewer state from previous or parent content viewer. |
7907 | // |
7908 | // The following logic is mirrored in nsHTMLDocument::StartDocumentLoad! |
7909 | // |
7910 | // Do NOT to maintain a reference to the old content viewer outside |
7911 | // of this "copying" block, or it will not be destroyed until the end of |
7912 | // this routine and all <SCRIPT>s and event handlers fail! (bug 20315) |
7913 | // |
7914 | // In this block of code, if we get an error result, we return it |
7915 | // but if we get a null pointer, that's perfectly legal for parent |
7916 | // and parentContentViewer. |
7917 | // |
7918 | |
7919 | int32_t x = 0; |
7920 | int32_t y = 0; |
7921 | int32_t cx = 0; |
7922 | int32_t cy = 0; |
7923 | |
7924 | // This will get the size from the current content viewer or from the |
7925 | // Init settings |
7926 | DoGetPositionAndSize(&x, &y, &cx, &cy); |
7927 | |
7928 | nsCOMPtr<nsIDocShellTreeItem> parentAsItem; |
7929 | 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" , 7930); return NS_ERROR_FAILURE; } } while (false) |
7930 | 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" , 7930); return NS_ERROR_FAILURE; } } while (false); |
7931 | nsCOMPtr<nsIDocShell> parent(do_QueryInterface(parentAsItem)); |
7932 | |
7933 | const Encoding* reloadEncoding = nullptr; |
7934 | int32_t reloadEncodingSource = kCharsetUninitialized; |
7935 | // |newMUDV| also serves as a flag to set the data from the above vars |
7936 | nsCOMPtr<nsIDocumentViewer> newViewer; |
7937 | |
7938 | if (mDocumentViewer || parent) { |
7939 | nsCOMPtr<nsIDocumentViewer> oldViewer; |
7940 | if (mDocumentViewer) { |
7941 | // Get any interesting state from old content viewer |
7942 | // XXX: it would be far better to just reuse the document viewer , |
7943 | // since we know we're just displaying the same document as before |
7944 | oldViewer = mDocumentViewer; |
7945 | |
7946 | // Tell the old content viewer to hibernate in session history when |
7947 | // it is destroyed. |
7948 | |
7949 | if (mSavingOldViewer && NS_FAILED(CaptureState())((bool)(__builtin_expect(!!(NS_FAILED_impl(CaptureState())), 0 )))) { |
7950 | if (mOSHE) { |
7951 | mOSHE->SyncPresentationState(); |
7952 | } |
7953 | mSavingOldViewer = false; |
7954 | } |
7955 | } else { |
7956 | // No old content viewer, so get state from parent's content viewer |
7957 | parent->GetDocViewer(getter_AddRefs(oldViewer)); |
7958 | } |
7959 | |
7960 | if (oldViewer) { |
7961 | newViewer = aNewViewer; |
7962 | if (newViewer) { |
7963 | reloadEncoding = |
7964 | oldViewer->GetReloadEncodingAndSource(&reloadEncodingSource); |
7965 | } |
7966 | } |
7967 | } |
7968 | |
7969 | nscolor bgcolor = NS_RGBA(0, 0, 0, 0)((nscolor)(((0) << 24) | ((0) << 16) | ((0) << 8) | (0))); |
7970 | bool isUnderHiddenEmbedderElement = false; |
7971 | // Ensure that the content viewer is destroyed *after* the GC - bug 71515 |
7972 | nsCOMPtr<nsIDocumentViewer> viewer = mDocumentViewer; |
7973 | if (viewer) { |
7974 | // Stop any activity that may be happening in the old document before |
7975 | // releasing it... |
7976 | viewer->Stop(); |
7977 | |
7978 | // Try to extract the canvas background color from the old |
7979 | // presentation shell, so we can use it for the next document. |
7980 | if (PresShell* presShell = viewer->GetPresShell()) { |
7981 | bgcolor = presShell->GetCanvasBackground(); |
7982 | isUnderHiddenEmbedderElement = presShell->IsUnderHiddenEmbedderElement(); |
7983 | } |
7984 | |
7985 | viewer->Close(mSavingOldViewer ? mOSHE.get() : nullptr); |
7986 | aNewViewer->SetPreviousViewer(viewer); |
7987 | } |
7988 | if (mOSHE && (!mDocumentViewer || !mSavingOldViewer)) { |
7989 | // We don't plan to save a viewer in mOSHE; tell it to drop |
7990 | // any other state it's holding. |
7991 | mOSHE->SyncPresentationState(); |
7992 | } |
7993 | |
7994 | mDocumentViewer = nullptr; |
7995 | |
7996 | // Now that we're about to switch documents, forget all of our children. |
7997 | // Note that we cached them as needed up in CaptureState above. |
7998 | DestroyChildren(); |
7999 | |
8000 | mDocumentViewer = aNewViewer; |
8001 | |
8002 | nsCOMPtr<nsIWidget> widget; |
8003 | 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" , 8003); return NS_ERROR_FAILURE; } } while (false); |
8004 | |
8005 | nsIntRect bounds(x, y, cx, cy); |
8006 | |
8007 | mDocumentViewer->SetNavigationTiming(mTiming); |
8008 | |
8009 | if (NS_FAILED(mDocumentViewer->Init(widget, bounds, aWindowActor))((bool)(__builtin_expect(!!(NS_FAILED_impl(mDocumentViewer-> Init(widget, bounds, aWindowActor))), 0)))) { |
8010 | nsCOMPtr<nsIDocumentViewer> viewer = mDocumentViewer; |
8011 | viewer->Close(nullptr); |
8012 | viewer->Destroy(); |
8013 | mDocumentViewer = nullptr; |
8014 | SetCurrentURIInternal(nullptr); |
8015 | 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" , 8015); |
8016 | return NS_ERROR_FAILURE; |
8017 | } |
8018 | |
8019 | // If we have old state to copy, set the old state onto the new content |
8020 | // viewer |
8021 | if (newViewer) { |
8022 | newViewer->SetReloadEncodingAndSource(reloadEncoding, reloadEncodingSource); |
8023 | } |
8024 | |
8025 | 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" , 8025); return NS_ERROR_FAILURE; } } while (false); |
8026 | |
8027 | // Stuff the bgcolor from the old pres shell into the new |
8028 | // pres shell. This improves page load continuity. |
8029 | if (RefPtr<PresShell> presShell = mDocumentViewer->GetPresShell()) { |
8030 | presShell->SetCanvasBackground(bgcolor); |
8031 | presShell->ActivenessMaybeChanged(); |
8032 | if (isUnderHiddenEmbedderElement) { |
8033 | presShell->SetIsUnderHiddenEmbedderElement(isUnderHiddenEmbedderElement); |
8034 | } |
8035 | } |
8036 | |
8037 | // XXX: It looks like the LayoutState gets restored again in Embed() |
8038 | // right after the call to SetupNewViewer(...) |
8039 | |
8040 | // We don't show the mDocumentViewer yet, since we want to draw the old page |
8041 | // until we have enough of the new page to show. Just return with the new |
8042 | // viewer still set to hidden. |
8043 | |
8044 | return NS_OK; |
8045 | } |
8046 | |
8047 | void nsDocShell::SetDocCurrentStateObj(nsISHEntry* aShEntry, |
8048 | SessionHistoryInfo* aInfo) { |
8049 | 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" , 8049); return; } } while (false); |
8050 | |
8051 | RefPtr<Document> document = GetDocument(); |
8052 | 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" , 8052); return; } } while (false); |
8053 | |
8054 | nsCOMPtr<nsIStructuredCloneContainer> scContainer; |
8055 | if (mozilla::SessionHistoryInParent()) { |
8056 | // If aInfo is null, just set the document's state object to null. |
8057 | if (aInfo) { |
8058 | scContainer = aInfo->GetStateData(); |
8059 | } |
8060 | 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) |
8061 | ("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); |
8062 | } else { |
8063 | if (aShEntry) { |
8064 | scContainer = aShEntry->GetStateData(); |
8065 | |
8066 | // If aShEntry is null, just set the document's state object to null. |
8067 | } |
8068 | } |
8069 | |
8070 | // It's OK for scContainer too be null here; that just means there's no |
8071 | // state data associated with this history entry. |
8072 | document->SetStateObject(scContainer); |
8073 | } |
8074 | |
8075 | nsresult nsDocShell::CheckLoadingPermissions() { |
8076 | // This method checks whether the caller may load content into |
8077 | // this docshell. Even though we've done our best to hide windows |
8078 | // from code that doesn't have the right to access them, it's |
8079 | // still possible for an evil site to open a window and access |
8080 | // frames in the new window through window.frames[] (which is |
8081 | // allAccess for historic reasons), so we still need to do this |
8082 | // check on load. |
8083 | nsresult rv = NS_OK; |
8084 | |
8085 | if (!IsSubframe()) { |
8086 | // We're not a frame. Permit all loads. |
8087 | return rv; |
8088 | } |
8089 | |
8090 | // Note - The check for a current JSContext here isn't necessarily sensical. |
8091 | // It's just designed to preserve the old semantics during a mass-conversion |
8092 | // patch. |
8093 | if (!nsContentUtils::GetCurrentJSContext()) { |
8094 | return NS_OK; |
8095 | } |
8096 | |
8097 | // Check if the caller is from the same origin as this docshell, |
8098 | // or any of its ancestors. |
8099 | for (RefPtr<BrowsingContext> bc = mBrowsingContext; bc; |
8100 | bc = bc->GetParent()) { |
8101 | // If the BrowsingContext is not in process, then it |
8102 | // is true by construction that its principal will not |
8103 | // subsume the current docshell principal. |
8104 | if (!bc->IsInProcess()) { |
8105 | continue; |
8106 | } |
8107 | |
8108 | nsCOMPtr<nsIScriptGlobalObject> sgo = |
8109 | bc->GetDocShell()->GetScriptGlobalObject(); |
8110 | nsCOMPtr<nsIScriptObjectPrincipal> sop(do_QueryInterface(sgo)); |
8111 | |
8112 | nsIPrincipal* p; |
8113 | if (!sop || !(p = sop->GetPrincipal())) { |
8114 | return NS_ERROR_UNEXPECTED; |
8115 | } |
8116 | |
8117 | if (nsContentUtils::SubjectPrincipal()->Subsumes(p)) { |
8118 | // Same origin, permit load |
8119 | return NS_OK; |
8120 | } |
8121 | } |
8122 | |
8123 | return NS_ERROR_DOM_PROP_ACCESS_DENIED; |
8124 | } |
8125 | |
8126 | //***************************************************************************** |
8127 | // nsDocShell: Site Loading |
8128 | //***************************************************************************** |
8129 | |
8130 | void nsDocShell::CopyFavicon(nsIURI* aOldURI, nsIURI* aNewURI, |
8131 | bool aInPrivateBrowsing) { |
8132 | if (XRE_IsContentProcess()) { |
8133 | dom::ContentChild* contentChild = dom::ContentChild::GetSingleton(); |
8134 | if (contentChild) { |
8135 | contentChild->SendCopyFavicon(aOldURI, aNewURI, aInPrivateBrowsing); |
8136 | } |
8137 | return; |
8138 | } |
8139 | |
8140 | #ifdef MOZ_PLACES1 |
8141 | nsCOMPtr<nsIFaviconService> favSvc = |
8142 | do_GetService("@mozilla.org/browser/favicon-service;1"); |
8143 | if (favSvc) { |
8144 | favSvc->CopyFavicons(aOldURI, aNewURI, |
8145 | aInPrivateBrowsing |
8146 | ? nsIFaviconService::FAVICON_LOAD_PRIVATE |
8147 | : nsIFaviconService::FAVICON_LOAD_NON_PRIVATE, |
8148 | nullptr); |
8149 | } |
8150 | #endif |
8151 | } |
8152 | |
8153 | class InternalLoadEvent : public Runnable { |
8154 | public: |
8155 | InternalLoadEvent(nsDocShell* aDocShell, nsDocShellLoadState* aLoadState) |
8156 | : mozilla::Runnable("InternalLoadEvent"), |
8157 | mDocShell(aDocShell), |
8158 | mLoadState(aLoadState) { |
8159 | // For events, both target and filename should be the version of "null" they |
8160 | // expect. By the time the event is fired, both window targeting and file |
8161 | // downloading have been handled, so we should never have an internal load |
8162 | // event that retargets or had a download. |
8163 | mLoadState->SetTarget(u""_ns); |
8164 | mLoadState->SetFileName(VoidString()); |
8165 | } |
8166 | |
8167 | NS_IMETHODvirtual nsresult |
8168 | Run() override { |
8169 | #ifndef ANDROID |
8170 | 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" , 8171); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLoadState->TriggeringPrincipal()" ") (" "InternalLoadEvent: Should always have a principal here" ")"); do { *((volatile int*)__null) = 8171; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
8171 | "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" , 8171); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLoadState->TriggeringPrincipal()" ") (" "InternalLoadEvent: Should always have a principal here" ")"); do { *((volatile int*)__null) = 8171; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
8172 | #endif |
8173 | return mDocShell->InternalLoad(mLoadState); |
8174 | } |
8175 | |
8176 | private: |
8177 | RefPtr<nsDocShell> mDocShell; |
8178 | RefPtr<nsDocShellLoadState> mLoadState; |
8179 | }; |
8180 | |
8181 | /** |
8182 | * Returns true if we started an asynchronous load (i.e., from the network), but |
8183 | * the document we're loading there hasn't yet become this docshell's active |
8184 | * document. |
8185 | * |
8186 | * When JustStartedNetworkLoad is true, you should be careful about modifying |
8187 | * mLoadType and mLSHE. These are both set when the asynchronous load first |
8188 | * starts, and the load expects that, when it eventually runs InternalLoad, |
8189 | * mLoadType and mLSHE will have their original values. |
8190 | */ |
8191 | bool nsDocShell::JustStartedNetworkLoad() { |
8192 | return mDocumentRequest && mDocumentRequest != GetCurrentDocChannel(); |
8193 | } |
8194 | |
8195 | // The contentType will be INTERNAL_(I)FRAME if this docshell is for a |
8196 | // non-toplevel browsing context in spec terms. (frame, iframe, <object>, |
8197 | // <embed>, etc) |
8198 | // |
8199 | // This return value will be used when we call NS_CheckContentLoadPolicy, and |
8200 | // later when we call DoURILoad. |
8201 | nsContentPolicyType nsDocShell::DetermineContentType() { |
8202 | if (!IsSubframe()) { |
8203 | return nsIContentPolicy::TYPE_DOCUMENT; |
8204 | } |
8205 | |
8206 | const auto& maybeEmbedderElementType = |
8207 | GetBrowsingContext()->GetEmbedderElementType(); |
8208 | if (!maybeEmbedderElementType) { |
8209 | // If the EmbedderElementType hasn't been set yet, just assume we're |
8210 | // an iframe since that's more common. |
8211 | return nsIContentPolicy::TYPE_INTERNAL_IFRAME; |
8212 | } |
8213 | |
8214 | return maybeEmbedderElementType->EqualsLiteral("iframe") |
8215 | ? nsIContentPolicy::TYPE_INTERNAL_IFRAME |
8216 | : nsIContentPolicy::TYPE_INTERNAL_FRAME; |
8217 | } |
8218 | |
8219 | bool nsDocShell::NoopenerForceEnabled() { |
8220 | // If current's top-level browsing context's active document's |
8221 | // cross-origin-opener-policy is "same-origin" or "same-origin + COEP" then |
8222 | // if currentDoc's origin is not same origin with currentDoc's top-level |
8223 | // origin, noopener is force enabled, and name is cleared to "_blank". |
8224 | auto topPolicy = mBrowsingContext->Top()->GetOpenerPolicy(); |
8225 | return (topPolicy == nsILoadInfo::OPENER_POLICY_SAME_ORIGIN || |
8226 | topPolicy == |
8227 | nsILoadInfo:: |
8228 | OPENER_POLICY_SAME_ORIGIN_EMBEDDER_POLICY_REQUIRE_CORP) && |
8229 | !mBrowsingContext->SameOriginWithTop(); |
8230 | } |
8231 | |
8232 | nsresult nsDocShell::PerformRetargeting(nsDocShellLoadState* aLoadState) { |
8233 | 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" , 8233); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState" ") (" "need a load state!" ")"); do { *((volatile int*)__null ) = 8233; __attribute__((nomerge)) ::abort(); } while (false) ; } } while (false); |
8234 | 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" , 8234); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aLoadState->Target().IsEmpty()" ") (" "should have a target here!" ")"); do { *((volatile int *)__null) = 8234; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
8235 | 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" , 8236); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->TargetBrowsingContext().IsNull()" ") (" "should not have picked target yet" ")"); do { *((volatile int*)__null) = 8236; __attribute__((nomerge)) ::abort(); } while (false); } } while (false) |
8236 | "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" , 8236); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->TargetBrowsingContext().IsNull()" ") (" "should not have picked target yet" ")"); do { *((volatile int*)__null) = 8236; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
8237 | |
8238 | nsresult rv = NS_OK; |
8239 | RefPtr<BrowsingContext> targetContext; |
8240 | |
8241 | // Only _self, _parent, and _top are supported in noopener case. But we |
8242 | // have to be careful to not apply that to the noreferrer case. See bug |
8243 | // 1358469. |
8244 | bool allowNamedTarget = |
8245 | !aLoadState->HasInternalLoadFlags(INTERNAL_LOAD_FLAGS_NO_OPENER) || |
8246 | aLoadState->HasInternalLoadFlags(INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER); |
8247 | if (allowNamedTarget || |
8248 | aLoadState->Target().LowerCaseEqualsLiteral("_self") || |
8249 | aLoadState->Target().LowerCaseEqualsLiteral("_parent") || |
8250 | aLoadState->Target().LowerCaseEqualsLiteral("_top")) { |
8251 | Document* document = GetDocument(); |
8252 | 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" , 8252); return NS_ERROR_FAILURE; } } while (false); |
8253 | WindowGlobalChild* wgc = document->GetWindowGlobalChild(); |
8254 | 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" , 8254); return NS_ERROR_FAILURE; } } while (false); |
8255 | targetContext = wgc->FindBrowsingContextWithName( |
8256 | aLoadState->Target(), /* aUseEntryGlobalForAccessCheck */ false); |
8257 | } |
8258 | |
8259 | if (!targetContext) { |
8260 | // If the targetContext doesn't exist, then this is a new docShell and we |
8261 | // should consider this a TYPE_DOCUMENT load |
8262 | // |
8263 | // For example, when target="_blank" |
8264 | |
8265 | // If there's no targetContext, that means we are about to create a new |
8266 | // window. Perform a content policy check before creating the window. Please |
8267 | // note for all other docshell loads content policy checks are performed |
8268 | // within the contentSecurityManager when the channel is about to be |
8269 | // openend. |
8270 | nsISupports* requestingContext = nullptr; |
8271 | if (XRE_IsContentProcess()) { |
8272 | // In e10s the child process doesn't have access to the element that |
8273 | // contains the browsing context (because that element is in the chrome |
8274 | // process). So we just pass mScriptGlobal. |
8275 | requestingContext = ToSupports(mScriptGlobal); |
8276 | } else { |
8277 | // This is for loading non-e10s tabs and toplevel windows of various |
8278 | // sorts. |
8279 | // For the toplevel window cases, requestingElement will be null. |
8280 | nsCOMPtr<Element> requestingElement = |
8281 | mScriptGlobal->GetFrameElementInternal(); |
8282 | requestingContext = requestingElement; |
8283 | } |
8284 | |
8285 | // Ideally we should use the same loadinfo as within DoURILoad which |
8286 | // should match this one when both are applicable. |
8287 | nsCOMPtr<nsILoadInfo> secCheckLoadInfo = |
8288 | new LoadInfo(mScriptGlobal, aLoadState->URI(), |
8289 | aLoadState->TriggeringPrincipal(), requestingContext, |
8290 | nsILoadInfo::SEC_ONLY_FOR_EXPLICIT_CONTENTSEC_CHECK, 0); |
8291 | |
8292 | // Since Content Policy checks are performed within docShell as well as |
8293 | // the ContentSecurityManager we need a reliable way to let certain |
8294 | // nsIContentPolicy consumers ignore duplicate calls. |
8295 | secCheckLoadInfo->SetSkipContentPolicyCheckForWebRequest(true); |
8296 | |
8297 | int16_t shouldLoad = nsIContentPolicy::ACCEPT; |
8298 | rv = NS_CheckContentLoadPolicy(aLoadState->URI(), secCheckLoadInfo, |
8299 | &shouldLoad); |
8300 | |
8301 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || NS_CP_REJECTED(shouldLoad)((shouldLoad) != nsIContentPolicy::ACCEPT)) { |
8302 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) { |
8303 | if (shouldLoad == nsIContentPolicy::REJECT_TYPE) { |
8304 | return NS_ERROR_CONTENT_BLOCKED_SHOW_ALT; |
8305 | } |
8306 | if (shouldLoad == nsIContentPolicy::REJECT_POLICY) { |
8307 | return NS_ERROR_BLOCKED_BY_POLICY; |
8308 | } |
8309 | } |
8310 | |
8311 | return NS_ERROR_CONTENT_BLOCKED; |
8312 | } |
8313 | } |
8314 | |
8315 | // |
8316 | // Resolve the window target before going any further... |
8317 | // If the load has been targeted to another DocShell, then transfer the |
8318 | // load to it... |
8319 | // |
8320 | |
8321 | // We've already done our owner-inheriting. Mask out that bit, so we |
8322 | // don't try inheriting an owner from the target window if we came up |
8323 | // with a null owner above. |
8324 | aLoadState->UnsetInternalLoadFlag(INTERNAL_LOAD_FLAGS_INHERIT_PRINCIPAL); |
8325 | |
8326 | if (!targetContext) { |
8327 | // If the docshell's document is sandboxed, only open a new window |
8328 | // if the document's SANDBOXED_AUXILLARY_NAVIGATION flag is not set. |
8329 | // (i.e. if allow-popups is specified) |
8330 | 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" , 8330); return NS_ERROR_FAILURE; } } while (false); |
8331 | Document* doc = mDocumentViewer->GetDocument(); |
8332 | |
8333 | const bool isDocumentAuxSandboxed = |
8334 | doc && (doc->GetSandboxFlags() & SANDBOXED_AUXILIARY_NAVIGATION); |
8335 | |
8336 | if (isDocumentAuxSandboxed) { |
8337 | return NS_ERROR_DOM_INVALID_ACCESS_ERR; |
8338 | } |
8339 | |
8340 | nsCOMPtr<nsPIDOMWindowOuter> win = GetWindow(); |
8341 | 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" , 8341); return NS_ERROR_NOT_AVAILABLE; } } while (false); |
8342 | |
8343 | RefPtr<BrowsingContext> newBC; |
8344 | nsAutoCString spec; |
8345 | aLoadState->URI()->GetSpec(spec); |
8346 | |
8347 | // If we are a noopener load, we just hand the whole thing over to our |
8348 | // window. |
8349 | if (aLoadState->HasInternalLoadFlags(INTERNAL_LOAD_FLAGS_NO_OPENER) || |
8350 | NoopenerForceEnabled()) { |
8351 | // Various asserts that we know to hold because NO_OPENER loads can only |
8352 | // happen for links. |
8353 | 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" , 8353); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aLoadState->LoadReplace()" ")"); do { *((volatile int*)__null) = 8353; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
8354 | 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" , 8355); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->PrincipalToInherit() == aLoadState->TriggeringPrincipal()" ")"); do { *((volatile int*)__null) = 8355; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
8355 | 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" , 8355); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->PrincipalToInherit() == aLoadState->TriggeringPrincipal()" ")"); do { *((volatile int*)__null) = 8355; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
8356 | 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" , 8360); 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) = 8360; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
8357 | ~(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" , 8360); 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) = 8360; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
8358 | 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" , 8360); 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) = 8360; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
8359 | "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" , 8360); 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) = 8360; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
8360 | "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" , 8360); 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) = 8360; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
8361 | 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" , 8362); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->IsFormSubmission()" ")"); do { *((volatile int*)__null) = 8362; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) |
8362 | 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" , 8362); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->IsFormSubmission()" ")"); do { *((volatile int*)__null) = 8362; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); |
8363 | 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" , 8363); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aLoadState->HeadersStream()" ")"); do { *((volatile int*)__null) = 8363; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
8364 | // If OnLinkClickSync was invoked inside the onload handler, the load |
8365 | // type would be set to LOAD_NORMAL_REPLACE; otherwise it should be |
8366 | // LOAD_LINK. |
8367 | 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" , 8368); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->LoadType() == LOAD_LINK || aLoadState->LoadType() == LOAD_NORMAL_REPLACE" ")"); do { *((volatile int*)__null) = 8368; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
8368 | 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" , 8368); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->LoadType() == LOAD_LINK || aLoadState->LoadType() == LOAD_NORMAL_REPLACE" ")"); do { *((volatile int*)__null) = 8368; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
8369 | 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" , 8369); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aLoadState->LoadIsFromSessionHistory()" ")"); do { *((volatile int*)__null) = 8369; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
8370 | 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" , 8370); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->FirstParty()" ")"); do { *((volatile int*)__null) = 8370; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); // Windowwatcher will assume this. |
8371 | |
8372 | RefPtr<nsDocShellLoadState> loadState = |
8373 | new nsDocShellLoadState(aLoadState->URI()); |
8374 | |
8375 | // Set up our loadinfo so it will do the load as much like we would have |
8376 | // as possible. |
8377 | loadState->SetReferrerInfo(aLoadState->GetReferrerInfo()); |
8378 | loadState->SetOriginalURI(aLoadState->OriginalURI()); |
8379 | |
8380 | Maybe<nsCOMPtr<nsIURI>> resultPrincipalURI; |
8381 | aLoadState->GetMaybeResultPrincipalURI(resultPrincipalURI); |
8382 | |
8383 | loadState->SetMaybeResultPrincipalURI(resultPrincipalURI); |
8384 | loadState->SetKeepResultPrincipalURIIfSet( |
8385 | aLoadState->KeepResultPrincipalURIIfSet()); |
8386 | // LoadReplace will always be false due to asserts above, skip setting |
8387 | // it. |
8388 | loadState->SetTriggeringPrincipal(aLoadState->TriggeringPrincipal()); |
8389 | loadState->SetTriggeringSandboxFlags( |
8390 | aLoadState->TriggeringSandboxFlags()); |
8391 | loadState->SetTriggeringWindowId(aLoadState->TriggeringWindowId()); |
8392 | loadState->SetTriggeringStorageAccess( |
8393 | aLoadState->TriggeringStorageAccess()); |
8394 | loadState->SetCsp(aLoadState->Csp()); |
8395 | loadState->SetInheritPrincipal(aLoadState->HasInternalLoadFlags( |
8396 | INTERNAL_LOAD_FLAGS_INHERIT_PRINCIPAL)); |
8397 | // Explicit principal because we do not want any guesses as to what the |
8398 | // principal to inherit is: it should be aTriggeringPrincipal. |
8399 | loadState->SetPrincipalIsExplicit(true); |
8400 | loadState->SetLoadType(aLoadState->LoadType()); |
8401 | loadState->SetForceAllowDataURI(aLoadState->HasInternalLoadFlags( |
8402 | INTERNAL_LOAD_FLAGS_FORCE_ALLOW_DATA_URI)); |
8403 | |
8404 | loadState->SetHasValidUserGestureActivation( |
8405 | aLoadState->HasValidUserGestureActivation()); |
8406 | |
8407 | loadState->SetTextDirectiveUserActivation( |
8408 | aLoadState->GetTextDirectiveUserActivation()); |
8409 | |
8410 | // Propagate POST data to the new load. |
8411 | loadState->SetPostDataStream(aLoadState->PostDataStream()); |
8412 | loadState->SetIsFormSubmission(aLoadState->IsFormSubmission()); |
8413 | |
8414 | rv = win->Open(NS_ConvertUTF8toUTF16(spec), |
8415 | aLoadState->Target(), // window name |
8416 | u""_ns, // Features |
8417 | loadState, |
8418 | true, // aForceNoOpener |
8419 | getter_AddRefs(newBC)); |
8420 | 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" , 8420); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!newBC" ")" ); do { *((volatile int*)__null) = 8420; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
8421 | return rv; |
8422 | } |
8423 | |
8424 | rv = win->OpenNoNavigate(NS_ConvertUTF8toUTF16(spec), |
8425 | aLoadState->Target(), // window name |
8426 | u""_ns, // Features |
8427 | getter_AddRefs(newBC)); |
8428 | |
8429 | // In some cases the Open call doesn't actually result in a new |
8430 | // window being opened. We can detect these cases by examining the |
8431 | // document in |newBC|, if any. |
8432 | nsCOMPtr<nsPIDOMWindowOuter> piNewWin = |
8433 | newBC ? newBC->GetDOMWindow() : nullptr; |
8434 | if (piNewWin) { |
8435 | RefPtr<Document> newDoc = piNewWin->GetExtantDoc(); |
8436 | if (!newDoc || newDoc->IsInitialDocument()) { |
8437 | aLoadState->SetInternalLoadFlag(INTERNAL_LOAD_FLAGS_FIRST_LOAD); |
8438 | } |
8439 | } |
8440 | |
8441 | if (newBC) { |
8442 | targetContext = newBC; |
8443 | } |
8444 | } |
8445 | 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" , 8445); return rv; } } while (false); |
8446 | 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" , 8446); return rv; } } while (false); |
8447 | |
8448 | // If our target BrowsingContext is still pending initialization, ignore the |
8449 | // navigation request targeting it. |
8450 | 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" , 8450)) { |
8451 | return NS_OK; |
8452 | } |
8453 | |
8454 | aLoadState->SetTargetBrowsingContext(targetContext); |
8455 | if (aLoadState->IsFormSubmission()) { |
8456 | aLoadState->SetLoadType( |
8457 | GetLoadTypeForFormSubmission(targetContext, aLoadState)); |
8458 | } |
8459 | |
8460 | // |
8461 | // Transfer the load to the target BrowsingContext... Clear the window target |
8462 | // name to the empty string to prevent recursive retargeting! |
8463 | // |
8464 | // No window target |
8465 | aLoadState->SetTarget(u""_ns); |
8466 | // No forced download |
8467 | aLoadState->SetFileName(VoidString()); |
8468 | return targetContext->InternalLoad(aLoadState); |
8469 | } |
8470 | |
8471 | static nsAutoCString RefMaybeNull(nsIURI* aURI) { |
8472 | nsAutoCString result; |
8473 | if (NS_FAILED(aURI->GetRef(result))((bool)(__builtin_expect(!!(NS_FAILED_impl(aURI->GetRef(result ))), 0)))) { |
8474 | result.SetIsVoid(true); |
8475 | } |
8476 | return result; |
8477 | } |
8478 | |
8479 | uint32_t nsDocShell::GetSameDocumentNavigationFlags(nsIURI* aNewURI) { |
8480 | uint32_t flags = LOCATION_CHANGE_SAME_DOCUMENT; |
8481 | |
8482 | bool equal = false; |
8483 | if (mCurrentURI && |
8484 | NS_SUCCEEDED(mCurrentURI->EqualsExceptRef(aNewURI, &equal))((bool)(__builtin_expect(!!(!NS_FAILED_impl(mCurrentURI->EqualsExceptRef (aNewURI, &equal))), 1))) && equal && |
8485 | RefMaybeNull(mCurrentURI) != RefMaybeNull(aNewURI)) { |
8486 | flags |= LOCATION_CHANGE_HASHCHANGE; |
8487 | } |
8488 | |
8489 | return flags; |
8490 | } |
8491 | |
8492 | bool nsDocShell::IsSameDocumentNavigation(nsDocShellLoadState* aLoadState, |
8493 | SameDocumentNavigationState& aState) { |
8494 | 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" , 8494); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState" ")"); do { *((volatile int*)__null) = 8494; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
8495 | if (!(aLoadState->LoadType() == LOAD_NORMAL || |
8496 | aLoadState->LoadType() == LOAD_STOP_CONTENT || |
8497 | LOAD_TYPE_HAS_FLAGS(aLoadState->LoadType(),((aLoadState->LoadType()) & ((LOAD_FLAGS_REPLACE_HISTORY ) << 16)) |
8498 | LOAD_FLAGS_REPLACE_HISTORY)((aLoadState->LoadType()) & ((LOAD_FLAGS_REPLACE_HISTORY ) << 16)) || |
8499 | aLoadState->LoadType() == LOAD_HISTORY || |
8500 | aLoadState->LoadType() == LOAD_LINK)) { |
8501 | return false; |
8502 | } |
8503 | |
8504 | nsCOMPtr<nsIURI> currentURI = mCurrentURI; |
8505 | |
8506 | nsresult rvURINew = aLoadState->URI()->GetRef(aState.mNewHash); |
8507 | if (NS_SUCCEEDED(rvURINew)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rvURINew)), 1)))) { |
8508 | rvURINew = aLoadState->URI()->GetHasRef(&aState.mNewURIHasRef); |
8509 | } |
8510 | |
8511 | // A Fragment Directive must be removed from the new hash in order to allow |
8512 | // fallback element id scroll. Additionally, the extracted parsed text |
8513 | // directives need to be stored for further use. |
8514 | nsTArray<TextDirective> textDirectives; |
8515 | if (FragmentDirective::ParseAndRemoveFragmentDirectiveFromFragmentString( |
8516 | aState.mNewHash, &textDirectives, aLoadState->URI())) { |
8517 | if (Document* doc = GetDocument()) { |
8518 | doc->FragmentDirective()->SetTextDirectives(std::move(textDirectives)); |
8519 | } |
8520 | } |
8521 | |
8522 | if (currentURI && NS_SUCCEEDED(rvURINew)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rvURINew)), 1)))) { |
8523 | nsresult rvURIOld = currentURI->GetRef(aState.mCurrentHash); |
8524 | if (NS_SUCCEEDED(rvURIOld)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rvURIOld)), 1)))) { |
8525 | rvURIOld = currentURI->GetHasRef(&aState.mCurrentURIHasRef); |
8526 | } |
8527 | if (NS_SUCCEEDED(rvURIOld)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rvURIOld)), 1)))) { |
8528 | if (NS_FAILED(currentURI->EqualsExceptRef(aLoadState->URI(),((bool)(__builtin_expect(!!(NS_FAILED_impl(currentURI->EqualsExceptRef (aLoadState->URI(), &aState.mSameExceptHashes))), 0))) |
8529 | &aState.mSameExceptHashes))((bool)(__builtin_expect(!!(NS_FAILED_impl(currentURI->EqualsExceptRef (aLoadState->URI(), &aState.mSameExceptHashes))), 0)))) { |
8530 | aState.mSameExceptHashes = false; |
8531 | } |
8532 | } |
8533 | } |
8534 | |
8535 | if (!aState.mSameExceptHashes && currentURI && NS_SUCCEEDED(rvURINew)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rvURINew)), 1)))) { |
8536 | // Maybe aLoadState->URI() came from the exposable form of currentURI? |
8537 | nsCOMPtr<nsIURI> currentExposableURI = |
8538 | nsIOService::CreateExposableURI(currentURI); |
8539 | nsresult rvURIOld = currentExposableURI->GetRef(aState.mCurrentHash); |
8540 | if (NS_SUCCEEDED(rvURIOld)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rvURIOld)), 1)))) { |
8541 | rvURIOld = currentExposableURI->GetHasRef(&aState.mCurrentURIHasRef); |
8542 | } |
8543 | if (NS_SUCCEEDED(rvURIOld)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rvURIOld)), 1)))) { |
8544 | if (NS_FAILED(currentExposableURI->EqualsExceptRef(((bool)(__builtin_expect(!!(NS_FAILED_impl(currentExposableURI ->EqualsExceptRef( aLoadState->URI(), &aState.mSameExceptHashes ))), 0))) |
8545 | aLoadState->URI(), &aState.mSameExceptHashes))((bool)(__builtin_expect(!!(NS_FAILED_impl(currentExposableURI ->EqualsExceptRef( aLoadState->URI(), &aState.mSameExceptHashes ))), 0)))) { |
8546 | aState.mSameExceptHashes = false; |
8547 | } |
8548 | // HTTPS-Only Mode upgrades schemes from http to https in Necko, hence we |
8549 | // have to perform a special check here to avoid an actual navigation. If |
8550 | // HTTPS-Only Mode is enabled and the two URIs are same-origin (modulo the |
8551 | // fact that the new URI is currently http), then set mSameExceptHashes to |
8552 | // true and only perform a fragment navigation. |
8553 | if (!aState.mSameExceptHashes) { |
8554 | if (nsCOMPtr<nsIChannel> docChannel = GetCurrentDocChannel()) { |
8555 | nsCOMPtr<nsILoadInfo> docLoadInfo = docChannel->LoadInfo(); |
8556 | if (!docLoadInfo->GetLoadErrorPage() && |
8557 | nsHTTPSOnlyUtils::ShouldUpgradeConnection(docLoadInfo) && |
8558 | nsHTTPSOnlyUtils::IsHttpDowngrade(currentExposableURI, |
8559 | aLoadState->URI())) { |
8560 | uint32_t status = docLoadInfo->GetHttpsOnlyStatus(); |
8561 | if (status & (nsILoadInfo::HTTPS_ONLY_UPGRADED_LISTENER_REGISTERED | |
8562 | nsILoadInfo::HTTPS_ONLY_UPGRADED_HTTPS_FIRST)) { |
8563 | // At this point the requested URI is for sure a fragment |
8564 | // navigation via HTTP and HTTPS-Only mode or HTTPS-First is |
8565 | // enabled. Also it is not interfering the upgrade order of |
8566 | // https://searchfox.org/mozilla-central/source/netwerk/base/nsNetUtil.cpp#2948-2953. |
8567 | // Since we are on an HTTPS site the fragment |
8568 | // navigation should also be an HTTPS. |
8569 | // For that reason we should upgrade the URI to HTTPS. |
8570 | aState.mSecureUpgradeURI = true; |
8571 | aState.mSameExceptHashes = true; |
8572 | } |
8573 | } |
8574 | } |
8575 | } |
8576 | } |
8577 | } |
8578 | |
8579 | if (mozilla::SessionHistoryInParent()) { |
8580 | if (mActiveEntry && aLoadState->LoadIsFromSessionHistory()) { |
8581 | aState.mHistoryNavBetweenSameDoc = mActiveEntry->SharesDocumentWith( |
8582 | aLoadState->GetLoadingSessionHistoryInfo()->mInfo); |
8583 | } |
8584 | 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) |
8585 | ("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) |
8586 | 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); |
8587 | } else { |
8588 | if (mOSHE && aLoadState->LoadIsFromSessionHistory()) { |
8589 | // We're doing a history load. |
8590 | |
8591 | mOSHE->SharesDocumentWith(aLoadState->SHEntry(), |
8592 | &aState.mHistoryNavBetweenSameDoc); |
8593 | } |
8594 | } |
8595 | |
8596 | // A same document navigation happens when we navigate between two SHEntries |
8597 | // for the same document. We do a same document navigation under two |
8598 | // circumstances. Either |
8599 | // |
8600 | // a) we're navigating between two different SHEntries which share a |
8601 | // document, or |
8602 | // |
8603 | // b) we're navigating to a new shentry whose URI differs from the |
8604 | // current URI only in its hash, the new hash is non-empty, and |
8605 | // we're not doing a POST. |
8606 | // |
8607 | // The restriction that the SHEntries in (a) must be different ensures |
8608 | // that history.go(0) and the like trigger full refreshes, rather than |
8609 | // same document navigations. |
8610 | if (!mozilla::SessionHistoryInParent()) { |
8611 | bool doSameDocumentNavigation = |
8612 | (aState.mHistoryNavBetweenSameDoc && mOSHE != aLoadState->SHEntry()) || |
8613 | (!aLoadState->SHEntry() && !aLoadState->PostDataStream() && |
8614 | aState.mSameExceptHashes && aState.mNewURIHasRef); |
8615 | 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) |
8616 | ("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) |
8617 | 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); |
8618 | return doSameDocumentNavigation; |
8619 | } |
8620 | |
8621 | if (aState.mHistoryNavBetweenSameDoc && |
8622 | !aLoadState->GetLoadingSessionHistoryInfo()->mLoadingCurrentEntry) { |
8623 | return true; |
8624 | } |
8625 | |
8626 | 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) |
8627 | 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) |
8628 | ("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) |
8629 | "!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) |
8630 | 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) |
8631 | !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) |
8632 | 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) |
8633 | 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); |
8634 | return !aLoadState->LoadIsFromSessionHistory() && |
8635 | !aLoadState->PostDataStream() && aState.mSameExceptHashes && |
8636 | aState.mNewURIHasRef; |
8637 | } |
8638 | |
8639 | nsresult nsDocShell::HandleSameDocumentNavigation( |
8640 | nsDocShellLoadState* aLoadState, SameDocumentNavigationState& aState, |
8641 | bool& aSameDocument) { |
8642 | aSameDocument = true; |
8643 | #ifdef DEBUG1 |
8644 | SameDocumentNavigationState state; |
8645 | 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" , 8645); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsSameDocumentNavigation(aLoadState, state)" ")"); do { *((volatile int*)__null) = 8645; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
8646 | #endif |
8647 | |
8648 | 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) |
8649 | ("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) |
8650 | 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) |
8651 | 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); |
8652 | |
8653 | RefPtr<Document> doc = GetDocument(); |
8654 | 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" , 8654); return NS_ERROR_FAILURE; } } while (false); |
8655 | doc->DoNotifyPossibleTitleChange(); |
8656 | |
8657 | nsCOMPtr<nsIURI> currentURI = mCurrentURI; |
8658 | |
8659 | // We need to upgrade the new URI from http: to https: |
8660 | nsCOMPtr<nsIURI> newURI = aLoadState->URI(); |
8661 | if (aState.mSecureUpgradeURI) { |
8662 | 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); |
8663 | 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) |
8664 | ("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); |
8665 | } |
8666 | |
8667 | if (StaticPrefs::dom_security_setdocumenturi()) { |
8668 | // check if aLoadState->URI(), principalURI, mCurrentURI are same origin |
8669 | // skip handling otherwise |
8670 | nsCOMPtr<nsIPrincipal> origPrincipal = doc->NodePrincipal(); |
8671 | nsCOMPtr<nsIURI> principalURI = origPrincipal->GetURI(); |
8672 | if (origPrincipal->GetIsNullPrincipal()) { |
8673 | nsCOMPtr<nsIPrincipal> precursor = origPrincipal->GetPrecursorPrincipal(); |
8674 | if (precursor) { |
8675 | principalURI = precursor->GetURI(); |
8676 | } |
8677 | } |
8678 | |
8679 | if (nsScriptSecurityManager::IsHttpOrHttpsAndCrossOrigin(principalURI, |
8680 | newURI) || |
8681 | nsScriptSecurityManager::IsHttpOrHttpsAndCrossOrigin(principalURI, |
8682 | mCurrentURI) || |
8683 | nsScriptSecurityManager::IsHttpOrHttpsAndCrossOrigin(mCurrentURI, |
8684 | newURI)) { |
8685 | aSameDocument = false; |
8686 | 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) |
8687 | ("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) |
8688 | "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) |
8689 | 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); |
8690 | return NS_OK; |
8691 | } |
8692 | } |
8693 | |
8694 | #ifdef DEBUG1 |
8695 | if (aState.mSameExceptHashes) { |
8696 | bool sameExceptHashes = false; |
8697 | currentURI->EqualsExceptRef(newURI, &sameExceptHashes); |
8698 | 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" , 8698); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sameExceptHashes" ")"); do { *((volatile int*)__null) = 8698; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
8699 | } |
8700 | #endif |
8701 | const nsCOMPtr<nsILoadInfo> loadInfo = |
8702 | doc->GetChannel() ? doc->GetChannel()->LoadInfo() : nullptr; |
8703 | if (loadInfo) { |
8704 | loadInfo->SetIsSameDocumentNavigation(true); |
8705 | } |
8706 | // Save the position of the scrollers. |
8707 | nsPoint scrollPos = GetCurScrollPos(); |
8708 | |
8709 | // Reset mLoadType to its original value once we exit this block, because this |
8710 | // same document navigation might have started after a normal, network load, |
8711 | // and we don't want to clobber its load type. See bug 737307. |
8712 | AutoRestore<uint32_t> loadTypeResetter(mLoadType); |
8713 | |
8714 | // If a non-same-document-navigation (i.e., a network load) is pending, make |
8715 | // this a replacement load, so that we don't add a SHEntry here and the |
8716 | // network load goes into the SHEntry it expects to. |
8717 | if (JustStartedNetworkLoad() && (aLoadState->LoadType() & LOAD_CMD_NORMAL)) { |
8718 | mLoadType = LOAD_NORMAL_REPLACE; |
8719 | } else { |
8720 | mLoadType = aLoadState->LoadType(); |
8721 | } |
8722 | |
8723 | mURIResultedInDocument = true; |
8724 | |
8725 | nsCOMPtr<nsISHEntry> oldLSHE = mLSHE; |
8726 | |
8727 | // we need to assign aLoadState->SHEntry() to mLSHE right here, so that on |
8728 | // History loads, SetCurrentURI() called from OnNewURI() will send proper |
8729 | // onLocationChange() notifications to the browser to update back/forward |
8730 | // buttons. |
8731 | SetHistoryEntryAndUpdateBC(Some<nsISHEntry*>(aLoadState->SHEntry()), |
8732 | Nothing()); |
8733 | UniquePtr<mozilla::dom::LoadingSessionHistoryInfo> oldLoadingEntry; |
8734 | mLoadingEntry.swap(oldLoadingEntry); |
8735 | if (aLoadState->GetLoadingSessionHistoryInfo()) { |
8736 | mLoadingEntry = MakeUnique<LoadingSessionHistoryInfo>( |
8737 | *aLoadState->GetLoadingSessionHistoryInfo()); |
8738 | mNeedToReportActiveAfterLoadingBecomesActive = false; |
8739 | } |
8740 | |
8741 | // Set the doc's URI according to the new history entry's URI. |
8742 | doc->SetDocumentURI(newURI); |
8743 | |
8744 | /* This is a anchor traversal within the same page. |
8745 | * call OnNewURI() so that, this traversal will be |
8746 | * recorded in session and global history. |
8747 | */ |
8748 | nsCOMPtr<nsIPrincipal> newURITriggeringPrincipal, newURIPrincipalToInherit, |
8749 | newURIPartitionedPrincipalToInherit; |
8750 | nsCOMPtr<nsIContentSecurityPolicy> newCsp; |
8751 | if (mozilla::SessionHistoryInParent() ? !!mActiveEntry : !!mOSHE) { |
8752 | if (mozilla::SessionHistoryInParent()) { |
8753 | newURITriggeringPrincipal = mActiveEntry->GetTriggeringPrincipal(); |
8754 | newURIPrincipalToInherit = mActiveEntry->GetPrincipalToInherit(); |
8755 | newURIPartitionedPrincipalToInherit = |
8756 | mActiveEntry->GetPartitionedPrincipalToInherit(); |
8757 | newCsp = mActiveEntry->GetCsp(); |
8758 | } else { |
8759 | newURITriggeringPrincipal = mOSHE->GetTriggeringPrincipal(); |
8760 | newURIPrincipalToInherit = mOSHE->GetPrincipalToInherit(); |
8761 | newURIPartitionedPrincipalToInherit = |
8762 | mOSHE->GetPartitionedPrincipalToInherit(); |
8763 | newCsp = mOSHE->GetCsp(); |
8764 | } |
8765 | } else { |
8766 | newURITriggeringPrincipal = aLoadState->TriggeringPrincipal(); |
8767 | newURIPrincipalToInherit = doc->NodePrincipal(); |
8768 | newURIPartitionedPrincipalToInherit = doc->PartitionedPrincipal(); |
8769 | newCsp = doc->GetCsp(); |
8770 | } |
8771 | |
8772 | uint32_t locationChangeFlags = GetSameDocumentNavigationFlags(newURI); |
8773 | |
8774 | // Pass true for aCloneSHChildren, since we're not |
8775 | // changing documents here, so all of our subframes are |
8776 | // still relevant to the new session history entry. |
8777 | // |
8778 | // It also makes OnNewURI(...) set LOCATION_CHANGE_SAME_DOCUMENT |
8779 | // flag on firing onLocationChange(...). |
8780 | // Anyway, aCloneSHChildren param is simply reflecting |
8781 | // doSameDocumentNavigation in this scope. |
8782 | // |
8783 | // Note: we'll actually fire onLocationChange later, in order to preserve |
8784 | // ordering of HistoryCommit() in the parent vs onLocationChange (bug |
8785 | // 1668126) |
8786 | bool locationChangeNeeded = OnNewURI( |
8787 | newURI, nullptr, newURITriggeringPrincipal, newURIPrincipalToInherit, |
8788 | newURIPartitionedPrincipalToInherit, newCsp, true, true); |
8789 | |
8790 | nsCOMPtr<nsIInputStream> postData; |
8791 | nsCOMPtr<nsIReferrerInfo> referrerInfo; |
8792 | uint32_t cacheKey = 0; |
8793 | |
8794 | bool scrollRestorationIsManual = false; |
8795 | if (!mozilla::SessionHistoryInParent()) { |
8796 | if (mOSHE) { |
8797 | /* save current position of scroller(s) (bug 59774) */ |
8798 | mOSHE->SetScrollPosition(scrollPos.x, scrollPos.y); |
8799 | scrollRestorationIsManual = mOSHE->GetScrollRestorationIsManual(); |
8800 | // Get the postdata, page ident and referrer info from the current page, |
8801 | // if the new load is being done via normal means. Note that "normal |
8802 | // means" can be checked for just by checking for LOAD_CMD_NORMAL, given |
8803 | // the loadType and allowScroll check above -- it filters out some |
8804 | // LOAD_CMD_NORMAL cases that we wouldn't want here. |
8805 | if (aLoadState->LoadType() & LOAD_CMD_NORMAL) { |
8806 | postData = mOSHE->GetPostData(); |
8807 | cacheKey = mOSHE->GetCacheKey(); |
8808 | referrerInfo = mOSHE->GetReferrerInfo(); |
8809 | } |
8810 | |
8811 | // Link our new SHEntry to the old SHEntry's back/forward |
8812 | // cache data, since the two SHEntries correspond to the |
8813 | // same document. |
8814 | if (mLSHE) { |
8815 | if (!aLoadState->LoadIsFromSessionHistory()) { |
8816 | // If we're not doing a history load, scroll restoration |
8817 | // should be inherited from the previous session history entry. |
8818 | SetScrollRestorationIsManualOnHistoryEntry(mLSHE, |
8819 | scrollRestorationIsManual); |
8820 | } |
8821 | mLSHE->AdoptBFCacheEntry(mOSHE); |
8822 | } |
8823 | } |
8824 | } else { |
8825 | if (mActiveEntry) { |
8826 | mActiveEntry->SetScrollPosition(scrollPos.x, scrollPos.y); |
8827 | if (mBrowsingContext) { |
8828 | CollectWireframe(); |
8829 | if (XRE_IsParentProcess()) { |
8830 | SessionHistoryEntry* entry = |
8831 | mBrowsingContext->Canonical()->GetActiveSessionHistoryEntry(); |
8832 | if (entry) { |
8833 | entry->SetScrollPosition(scrollPos.x, scrollPos.y); |
8834 | } |
8835 | } else { |
8836 | mozilla::Unused << ContentChild::GetSingleton() |
8837 | ->SendSessionHistoryEntryScrollPosition( |
8838 | mBrowsingContext, scrollPos.x, |
8839 | scrollPos.y); |
8840 | } |
8841 | } |
8842 | } |
8843 | if (mLoadingEntry) { |
8844 | if (!mLoadingEntry->mLoadIsFromSessionHistory) { |
8845 | // If we're not doing a history load, scroll restoration |
8846 | // should be inherited from the previous session history entry. |
8847 | // XXX This needs most probably tweaks once fragment navigation is |
8848 | // fixed to work with session-history-in-parent. |
8849 | SetScrollRestorationIsManualOnHistoryEntry(nullptr, |
8850 | scrollRestorationIsManual); |
8851 | } |
8852 | } |
8853 | } |
8854 | |
8855 | // If we're doing a history load, use its scroll restoration state. |
8856 | if (aLoadState->LoadIsFromSessionHistory()) { |
8857 | if (mozilla::SessionHistoryInParent()) { |
8858 | scrollRestorationIsManual = aLoadState->GetLoadingSessionHistoryInfo() |
8859 | ->mInfo.GetScrollRestorationIsManual(); |
8860 | } else { |
8861 | scrollRestorationIsManual = |
8862 | aLoadState->SHEntry()->GetScrollRestorationIsManual(); |
8863 | } |
8864 | } |
8865 | |
8866 | /* Assign mLSHE to mOSHE. This will either be a new entry created |
8867 | * by OnNewURI() for normal loads or aLoadState->SHEntry() for history |
8868 | * loads. |
8869 | */ |
8870 | if (!mozilla::SessionHistoryInParent()) { |
8871 | if (mLSHE) { |
8872 | SetHistoryEntryAndUpdateBC(Nothing(), Some<nsISHEntry*>(mLSHE)); |
8873 | // Save the postData obtained from the previous page |
8874 | // in to the session history entry created for the |
8875 | // anchor page, so that any history load of the anchor |
8876 | // page will restore the appropriate postData. |
8877 | if (postData) { |
8878 | mOSHE->SetPostData(postData); |
8879 | } |
8880 | |
8881 | // Make sure we won't just repost without hitting the |
8882 | // cache first |
8883 | if (cacheKey != 0) { |
8884 | mOSHE->SetCacheKey(cacheKey); |
8885 | } |
8886 | |
8887 | // As the document has not changed, the referrer info hasn't changed too, |
8888 | // so we can just copy it over. |
8889 | if (referrerInfo) { |
8890 | mOSHE->SetReferrerInfo(referrerInfo); |
8891 | } |
8892 | } |
8893 | |
8894 | /* Set the title for the SH entry for this target url so that |
8895 | * SH menus in go/back/forward buttons won't be empty for this. |
8896 | * Note, this happens on mOSHE (and mActiveEntry in the future) because of |
8897 | * the code above. |
8898 | * Note, when session history lives in the parent process, this does not |
8899 | * update the title there. |
8900 | */ |
8901 | SetTitleOnHistoryEntry(false); |
8902 | } else { |
8903 | if (aLoadState->LoadIsFromSessionHistory()) { |
8904 | 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) |
8905 | 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) |
8906 | ("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) |
8907 | "%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) |
8908 | 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); |
8909 | |
8910 | nsCOMPtr<nsILayoutHistoryState> currentLayoutHistoryState; |
8911 | if (mActiveEntry) { |
8912 | currentLayoutHistoryState = mActiveEntry->GetLayoutHistoryState(); |
8913 | } |
8914 | |
8915 | UniquePtr<SessionHistoryInfo> previousActiveEntry(mActiveEntry.release()); |
8916 | mActiveEntry = MakeUnique<SessionHistoryInfo>(mLoadingEntry->mInfo); |
8917 | if (currentLayoutHistoryState) { |
8918 | // Restore the existing nsILayoutHistoryState object, since it is |
8919 | // possibly being used by the layout. When doing a new load, the |
8920 | // shared state is copied from the existing active entry, so this |
8921 | // special case is needed only with the history loads. |
8922 | mActiveEntry->SetLayoutHistoryState(currentLayoutHistoryState); |
8923 | } |
8924 | |
8925 | if (cacheKey != 0) { |
8926 | mActiveEntry->SetCacheKey(cacheKey); |
8927 | } |
8928 | // We're passing in mCurrentURI, which could be null. SessionHistoryCommit |
8929 | // does require a non-null uri if this is for a refresh load of the same |
8930 | // URI, but in that case mCurrentURI won't be null here. |
8931 | mBrowsingContext->SessionHistoryCommit( |
8932 | *mLoadingEntry, mLoadType, mCurrentURI, previousActiveEntry.get(), |
8933 | true, true, |
8934 | /* No expiration update on the same document loads*/ |
8935 | false, cacheKey); |
8936 | // FIXME Need to set postdata. |
8937 | |
8938 | // Set the title for the SH entry for this target url so that |
8939 | // SH menus in go/back/forward buttons won't be empty for this. |
8940 | // Note, when session history lives in the parent process, this does not |
8941 | // update the title there. |
8942 | SetTitleOnHistoryEntry(false); |
8943 | } else { |
8944 | Maybe<bool> scrollRestorationIsManual; |
8945 | if (mActiveEntry) { |
8946 | scrollRestorationIsManual.emplace( |
8947 | mActiveEntry->GetScrollRestorationIsManual()); |
8948 | |
8949 | // Get the postdata, page ident and referrer info from the current page, |
8950 | // if the new load is being done via normal means. Note that "normal |
8951 | // means" can be checked for just by checking for LOAD_CMD_NORMAL, given |
8952 | // the loadType and allowScroll check above -- it filters out some |
8953 | // LOAD_CMD_NORMAL cases that we wouldn't want here. |
8954 | if (aLoadState->LoadType() & LOAD_CMD_NORMAL) { |
8955 | postData = mActiveEntry->GetPostData(); |
8956 | cacheKey = mActiveEntry->GetCacheKey(); |
8957 | referrerInfo = mActiveEntry->GetReferrerInfo(); |
8958 | } |
8959 | } |
8960 | |
8961 | 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) |
8962 | ("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) |
8963 | 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); |
8964 | if (mActiveEntry) { |
8965 | mActiveEntry = MakeUnique<SessionHistoryInfo>(*mActiveEntry, newURI); |
8966 | } else { |
8967 | mActiveEntry = MakeUnique<SessionHistoryInfo>( |
8968 | newURI, newURITriggeringPrincipal, newURIPrincipalToInherit, |
8969 | newURIPartitionedPrincipalToInherit, newCsp, mContentTypeHint); |
8970 | } |
8971 | |
8972 | // Save the postData obtained from the previous page in to the session |
8973 | // history entry created for the anchor page, so that any history load of |
8974 | // the anchor page will restore the appropriate postData. |
8975 | if (postData) { |
8976 | mActiveEntry->SetPostData(postData); |
8977 | } |
8978 | |
8979 | // Make sure we won't just repost without hitting the |
8980 | // cache first |
8981 | if (cacheKey != 0) { |
8982 | mActiveEntry->SetCacheKey(cacheKey); |
8983 | } |
8984 | |
8985 | // As the document has not changed, the referrer info hasn't changed too, |
8986 | // so we can just copy it over. |
8987 | if (referrerInfo) { |
8988 | mActiveEntry->SetReferrerInfo(referrerInfo); |
8989 | } |
8990 | |
8991 | // Set the title for the SH entry for this target url so that |
8992 | // SH menus in go/back/forward buttons won't be empty for this. |
8993 | mActiveEntry->SetTitle(mTitle); |
8994 | |
8995 | if (scrollRestorationIsManual.isSome()) { |
8996 | mActiveEntry->SetScrollRestorationIsManual( |
8997 | scrollRestorationIsManual.value()); |
8998 | } |
8999 | |
9000 | if (LOAD_TYPE_HAS_FLAGS(mLoadType, LOAD_FLAGS_REPLACE_HISTORY)((mLoadType) & ((LOAD_FLAGS_REPLACE_HISTORY) << 16) )) { |
9001 | mBrowsingContext->ReplaceActiveSessionHistoryEntry(mActiveEntry.get()); |
9002 | } else { |
9003 | mBrowsingContext->IncrementHistoryEntryCountForBrowsingContext(); |
9004 | // FIXME We should probably just compute mChildOffset in the parent |
9005 | // instead of passing it over IPC here. |
9006 | mBrowsingContext->SetActiveSessionHistoryEntry( |
9007 | Some(scrollPos), mActiveEntry.get(), mLoadType, cacheKey); |
9008 | // FIXME Do we need to update mPreviousEntryIndex and mLoadedEntryIndex? |
9009 | } |
9010 | } |
9011 | } |
9012 | |
9013 | if (locationChangeNeeded) { |
9014 | FireOnLocationChange(this, nullptr, newURI, locationChangeFlags); |
9015 | } |
9016 | |
9017 | /* Restore the original LSHE if we were loading something |
9018 | * while same document navigation was initiated. |
9019 | */ |
9020 | SetHistoryEntryAndUpdateBC(Some<nsISHEntry*>(oldLSHE), Nothing()); |
9021 | mLoadingEntry.swap(oldLoadingEntry); |
9022 | |
9023 | /* Set the title for the Global History entry for this anchor url. |
9024 | */ |
9025 | UpdateGlobalHistoryTitle(newURI); |
9026 | |
9027 | SetDocCurrentStateObj(mOSHE, mActiveEntry.get()); |
9028 | |
9029 | // Inform the favicon service that the favicon for oldURI also |
9030 | // applies to newURI. |
9031 | CopyFavicon(currentURI, newURI, UsePrivateBrowsing()); |
9032 | |
9033 | RefPtr<nsGlobalWindowOuter> scriptGlobal = mScriptGlobal; |
9034 | nsCOMPtr<nsPIDOMWindowInner> win = |
9035 | scriptGlobal ? scriptGlobal->GetCurrentInnerWindow() : nullptr; |
9036 | |
9037 | // ScrollToAnchor doesn't necessarily cause us to scroll the window; |
9038 | // the function decides whether a scroll is appropriate based on the |
9039 | // arguments it receives. But even if we don't end up scrolling, |
9040 | // ScrollToAnchor performs other important tasks, such as informing |
9041 | // the presShell that we have a new hash. See bug 680257. |
9042 | nsresult rv = ScrollToAnchor(aState.mCurrentURIHasRef, aState.mNewURIHasRef, |
9043 | aState.mNewHash, aLoadState->LoadType()); |
9044 | 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" , 9044); return rv; } } while (false); |
9045 | |
9046 | /* restore previous position of scroller(s), if we're moving |
9047 | * back in history (bug 59774) |
9048 | */ |
9049 | nscoord bx = 0; |
9050 | nscoord by = 0; |
9051 | bool needsScrollPosUpdate = false; |
9052 | if ((mozilla::SessionHistoryInParent() ? !!mActiveEntry : !!mOSHE) && |
9053 | (aLoadState->LoadType() == LOAD_HISTORY || |
9054 | aLoadState->LoadType() == LOAD_RELOAD_NORMAL) && |
9055 | !scrollRestorationIsManual) { |
9056 | needsScrollPosUpdate = true; |
9057 | if (mozilla::SessionHistoryInParent()) { |
9058 | mActiveEntry->GetScrollPosition(&bx, &by); |
9059 | } else { |
9060 | mOSHE->GetScrollPosition(&bx, &by); |
9061 | } |
9062 | } |
9063 | |
9064 | // Dispatch the popstate and hashchange events, as appropriate. |
9065 | // |
9066 | // The event dispatch below can cause us to re-enter script and |
9067 | // destroy the docshell, nulling out mScriptGlobal. Hold a stack |
9068 | // reference to avoid null derefs. See bug 914521. |
9069 | if (win) { |
9070 | // Fire a hashchange event URIs differ, and only in their hashes. |
9071 | bool doHashchange = aState.mSameExceptHashes && |
9072 | (aState.mCurrentURIHasRef != aState.mNewURIHasRef || |
9073 | !aState.mCurrentHash.Equals(aState.mNewHash)); |
9074 | |
9075 | if (aState.mHistoryNavBetweenSameDoc || doHashchange) { |
9076 | win->DispatchSyncPopState(); |
9077 | } |
9078 | |
9079 | if (needsScrollPosUpdate && win->HasActiveDocument()) { |
9080 | SetCurScrollPosEx(bx, by); |
9081 | } |
9082 | |
9083 | if (doHashchange) { |
9084 | // Note that currentURI hasn't changed because it's on the |
9085 | // stack, so we can just use it directly as the old URI. |
9086 | win->DispatchAsyncHashchange(currentURI, newURI); |
9087 | } |
9088 | } |
9089 | |
9090 | return NS_OK; |
9091 | } |
9092 | |
9093 | static bool NavigationShouldTakeFocus(nsDocShell* aDocShell, |
9094 | nsDocShellLoadState* aLoadState) { |
9095 | if (!aLoadState->AllowFocusMove()) { |
9096 | return false; |
9097 | } |
9098 | if (!aLoadState->HasValidUserGestureActivation()) { |
9099 | return false; |
9100 | } |
9101 | const auto& sourceBC = aLoadState->SourceBrowsingContext(); |
9102 | if (!sourceBC || !sourceBC->IsActive()) { |
9103 | // If the navigation didn't come from a foreground tab, then we don't steal |
9104 | // focus. |
9105 | return false; |
9106 | } |
9107 | auto* bc = aDocShell->GetBrowsingContext(); |
9108 | if (sourceBC.get() == bc) { |
9109 | // If it comes from the same tab / frame, don't steal focus either. |
9110 | return false; |
9111 | } |
9112 | auto* fm = nsFocusManager::GetFocusManager(); |
9113 | if (fm && bc->IsActive() && fm->IsInActiveWindow(bc)) { |
9114 | // If we're already on the foreground tab of the foreground window, then we |
9115 | // don't need to do this. This helps to e.g. not steal focus from the |
9116 | // browser chrome unnecessarily. |
9117 | return false; |
9118 | } |
9119 | if (auto* doc = aDocShell->GetExtantDocument()) { |
9120 | if (doc->IsInitialDocument()) { |
9121 | // If we're the initial load for the browsing context, the browser |
9122 | // chrome determines what to focus. This is important because the |
9123 | // browser chrome may want to e.g focus the url-bar |
9124 | return false; |
9125 | } |
9126 | } |
9127 | // Take loadDivertedInBackground into account so the behavior would be the |
9128 | // same as how the tab first opened. |
9129 | return !Preferences::GetBool("browser.tabs.loadDivertedInBackground", false); |
9130 | } |
9131 | |
9132 | uint32_t nsDocShell::GetLoadTypeForFormSubmission( |
9133 | BrowsingContext* aTargetBC, nsDocShellLoadState* aLoadState) { |
9134 | 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" , 9134); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->IsFormSubmission()" ")"); do { *((volatile int*)__null) = 9134; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
9135 | |
9136 | // https://html.spec.whatwg.org/#form-submission-algorithm |
9137 | // 22. Let historyHandling be "push". |
9138 | // 23. If form document equals targetNavigable's active document, and |
9139 | // form document has not yet completely loaded, then set |
9140 | // historyHandling to "replace". |
9141 | return GetBrowsingContext() == aTargetBC && !mEODForCurrentDocument |
9142 | ? LOAD_NORMAL_REPLACE |
9143 | : LOAD_LINK; |
9144 | } |
9145 | |
9146 | nsresult nsDocShell::InternalLoad(nsDocShellLoadState* aLoadState, |
9147 | Maybe<uint32_t> aCacheKey) { |
9148 | 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" , 9148); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState" ") (" "need a load state!" ")"); do { *((volatile int*)__null ) = 9148; __attribute__((nomerge)) ::abort(); } while (false) ; } } while (false); |
9149 | 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" , 9150); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->TriggeringPrincipal()" ") (" "need a valid TriggeringPrincipal" ")"); do { *((volatile int*)__null) = 9150; __attribute__((nomerge)) ::abort(); } while (false); } } while (false) |
9150 | "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" , 9150); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->TriggeringPrincipal()" ") (" "need a valid TriggeringPrincipal" ")"); do { *((volatile int*)__null) = 9150; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
9151 | |
9152 | if (!aLoadState->TriggeringPrincipal()) { |
9153 | 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" , 9153); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "InternalLoad needs a valid triggeringPrincipal" ")"); do { * ((volatile int*)__null) = 9153; __attribute__((nomerge)) ::abort (); } while (false); } } while (false); |
9154 | return NS_ERROR_FAILURE; |
9155 | } |
9156 | 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" , 9156)) { |
9157 | return NS_ERROR_NOT_AVAILABLE; |
9158 | } |
9159 | |
9160 | const bool shouldTakeFocus = NavigationShouldTakeFocus(this, aLoadState); |
9161 | |
9162 | mOriginalUriString.Truncate(); |
9163 | |
9164 | 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) |
9165 | ("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) |
9166 | 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); |
9167 | |
9168 | 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" , 9168); return NS_ERROR_INVALID_ARG; } } while (false); |
9169 | |
9170 | // Cancel loads coming from Docshells that are being destroyed. |
9171 | if (mIsBeingDestroyed) { |
9172 | return NS_ERROR_NOT_AVAILABLE; |
9173 | } |
9174 | |
9175 | nsresult rv = EnsureScriptEnvironment(); |
9176 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
9177 | return rv; |
9178 | } |
9179 | |
9180 | // If we have a target to move to, do that now. |
9181 | if (!aLoadState->Target().IsEmpty()) { |
9182 | return PerformRetargeting(aLoadState); |
9183 | } |
9184 | |
9185 | // This is the non-retargeting load path, we've already set the right loadtype |
9186 | // for form submissions in nsDocShell::OnLinkClickSync. |
9187 | if (aLoadState->TargetBrowsingContext().IsNull()) { |
9188 | aLoadState->SetTargetBrowsingContext(GetBrowsingContext()); |
9189 | } |
9190 | |
9191 | 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" , 9193); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "aLoadState->TargetBrowsingContext() == GetBrowsingContext()" ") (" "Load must be targeting this BrowsingContext" ")"); do { *((volatile int*)__null) = 9193; __attribute__((nomerge)) :: abort(); } while (false); } } while (false) |
9192 | 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" , 9193); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "aLoadState->TargetBrowsingContext() == GetBrowsingContext()" ") (" "Load must be targeting this BrowsingContext" ")"); do { *((volatile int*)__null) = 9193; __attribute__((nomerge)) :: abort(); } while (false); } } while (false) |
9193 | "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" , 9193); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "aLoadState->TargetBrowsingContext() == GetBrowsingContext()" ") (" "Load must be targeting this BrowsingContext" ")"); do { *((volatile int*)__null) = 9193; __attribute__((nomerge)) :: abort(); } while (false); } } while (false); |
9194 | |
9195 | MOZ_TRY(CheckDisallowedJavascriptLoad(aLoadState))do { auto mozTryTempResult_ = ::mozilla::ToResult(CheckDisallowedJavascriptLoad (aLoadState)); if ((__builtin_expect(!!(mozTryTempResult_.isErr ()), 0))) { return mozTryTempResult_.propagateErr(); } } while (0); |
9196 | |
9197 | // If we don't have a target, we're loading into ourselves, and our load |
9198 | // delegate may want to intercept that load. |
9199 | SameDocumentNavigationState sameDocumentNavigationState; |
9200 | bool sameDocument = |
9201 | IsSameDocumentNavigation(aLoadState, sameDocumentNavigationState) && |
9202 | !aLoadState->GetPendingRedirectedChannel(); |
9203 | |
9204 | // Note: We do this check both here and in BrowsingContext:: |
9205 | // LoadURI/InternalLoad, since document-specific sandbox flags are only |
9206 | // available in the process triggering the load, and we don't want the target |
9207 | // process to have to trust the triggering process to do the appropriate |
9208 | // checks for the BrowsingContext's sandbox flags. |
9209 | MOZ_TRY(mBrowsingContext->CheckSandboxFlags(aLoadState))do { auto mozTryTempResult_ = ::mozilla::ToResult(mBrowsingContext ->CheckSandboxFlags(aLoadState)); if ((__builtin_expect(!! (mozTryTempResult_.isErr()), 0))) { return mozTryTempResult_. propagateErr(); } } while (0); |
9210 | |
9211 | 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" , 9211); return NS_ERROR_UNEXPECTED; } } while (false); |
9212 | |
9213 | rv = CheckLoadingPermissions(); |
9214 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
9215 | return rv; |
9216 | } |
9217 | |
9218 | if (mFiredUnloadEvent) { |
9219 | if (IsOKToLoadURI(aLoadState->URI())) { |
9220 | 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" , 9221); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->Target().IsEmpty()" ") (" "Shouldn't have a window target here!" ")"); do { *((volatile int*)__null) = 9221; __attribute__((nomerge)) ::abort(); } while (false); } } while (false) |
9221 | "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" , 9221); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->Target().IsEmpty()" ") (" "Shouldn't have a window target here!" ")"); do { *((volatile int*)__null) = 9221; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
9222 | |
9223 | // If this is a replace load, make whatever load triggered |
9224 | // the unload event also a replace load, so we don't |
9225 | // create extra history entries. |
9226 | if (LOAD_TYPE_HAS_FLAGS(aLoadState->LoadType(),((aLoadState->LoadType()) & ((LOAD_FLAGS_REPLACE_HISTORY ) << 16)) |
9227 | LOAD_FLAGS_REPLACE_HISTORY)((aLoadState->LoadType()) & ((LOAD_FLAGS_REPLACE_HISTORY ) << 16))) { |
9228 | mLoadType = LOAD_NORMAL_REPLACE; |
9229 | } |
9230 | |
9231 | // Do this asynchronously |
9232 | nsCOMPtr<nsIRunnable> ev = new InternalLoadEvent(this, aLoadState); |
9233 | return Dispatch(ev.forget()); |
9234 | } |
9235 | |
9236 | // Just ignore this load attempt |
9237 | return NS_OK; |
9238 | } |
9239 | |
9240 | // If we are loading a URI that should inherit a security context (basically |
9241 | // javascript: at this point), and the caller has said that principal |
9242 | // inheritance is allowed, there are a few possible cases: |
9243 | // |
9244 | // 1) We are provided with the principal to inherit. In that case, we just use |
9245 | // it. |
9246 | // |
9247 | // 2) The load is coming from some other application. In this case we don't |
9248 | // want to inherit from whatever document we have loaded now, since the |
9249 | // load is unrelated to it. |
9250 | // |
9251 | // 3) It's a load from our application, but does not provide an explicit |
9252 | // principal to inherit. In that case, we want to inherit the principal of |
9253 | // our current document, or of our parent document (if any) if we don't |
9254 | // have a current document. |
9255 | { |
9256 | bool inherits; |
9257 | |
9258 | if (!aLoadState->HasLoadFlags(LOAD_FLAGS_FROM_EXTERNAL) && |
9259 | !aLoadState->PrincipalToInherit() && |
9260 | (aLoadState->HasInternalLoadFlags( |
9261 | INTERNAL_LOAD_FLAGS_INHERIT_PRINCIPAL)) && |
9262 | NS_SUCCEEDED(nsContentUtils::URIInheritsSecurityContext(((bool)(__builtin_expect(!!(!NS_FAILED_impl(nsContentUtils::URIInheritsSecurityContext ( aLoadState->URI(), &inherits))), 1))) |
9263 | aLoadState->URI(), &inherits))((bool)(__builtin_expect(!!(!NS_FAILED_impl(nsContentUtils::URIInheritsSecurityContext ( aLoadState->URI(), &inherits))), 1))) && |
9264 | inherits) { |
9265 | aLoadState->SetPrincipalToInherit(GetInheritedPrincipal(true)); |
9266 | } |
9267 | // If principalToInherit is still null (e.g. if some of the conditions of |
9268 | // were not satisfied), then no inheritance of any sort will happen: the |
9269 | // load will just get a principal based on the URI being loaded. |
9270 | } |
9271 | |
9272 | // If this docshell is owned by a frameloader, make sure to cancel |
9273 | // possible frameloader initialization before loading a new page. |
9274 | nsCOMPtr<nsIDocShellTreeItem> parent = GetInProcessParentDocshell(); |
9275 | if (parent) { |
9276 | RefPtr<Document> doc = parent->GetDocument(); |
9277 | if (doc) { |
9278 | doc->TryCancelFrameLoaderInitialization(this); |
9279 | } |
9280 | } |
9281 | |
9282 | // Before going any further vet loads initiated by external programs. |
9283 | if (aLoadState->HasLoadFlags(LOAD_FLAGS_FROM_EXTERNAL)) { |
9284 | 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" , 9284); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "aLoadState->LoadType() == LOAD_NORMAL" ")"); do { *((volatile int*)__null) = 9284; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
9285 | |
9286 | // Disallow external chrome: loads targetted at content windows |
9287 | if (SchemeIsChrome(aLoadState->URI())) { |
9288 | 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" , 9288); |
9289 | return NS_ERROR_FAILURE; |
9290 | } |
9291 | |
9292 | // clear the decks to prevent context bleed-through (bug 298255) |
9293 | rv = CreateAboutBlankDocumentViewer(nullptr, nullptr, nullptr, nullptr, |
9294 | /* aIsInitialDocument */ false); |
9295 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
9296 | return NS_ERROR_FAILURE; |
9297 | } |
9298 | } |
9299 | |
9300 | mAllowKeywordFixup = aLoadState->HasInternalLoadFlags( |
9301 | INTERNAL_LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP); |
9302 | mURIResultedInDocument = false; // reset the clock... |
9303 | |
9304 | // See if this is actually a load between two history entries for the same |
9305 | // document. If the process fails, or if we successfully navigate within the |
9306 | // same document, return. |
9307 | if (sameDocument) { |
9308 | nsresult rv = HandleSameDocumentNavigation( |
9309 | aLoadState, sameDocumentNavigationState, sameDocument); |
9310 | 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" , 9310); return rv; } } while (false); |
9311 | if (shouldTakeFocus) { |
9312 | mBrowsingContext->Focus(CallerType::System, IgnoreErrors()); |
9313 | } |
9314 | if (sameDocument) { |
9315 | return rv; |
9316 | } |
9317 | } |
9318 | |
9319 | // mDocumentViewer->PermitUnload can destroy |this| docShell, which |
9320 | // causes the next call of CanSavePresentation to crash. |
9321 | // Hold onto |this| until we return, to prevent a crash from happening. |
9322 | // (bug#331040) |
9323 | nsCOMPtr<nsIDocShell> kungFuDeathGrip(this); |
9324 | |
9325 | // Don't init timing for javascript:, since it generally doesn't |
9326 | // actually start a load or anything. If it does, we'll init |
9327 | // timing then, from OnStateChange. |
9328 | |
9329 | // XXXbz mTiming should know what channel it's for, so we don't |
9330 | // need this hackery. |
9331 | bool toBeReset = false; |
9332 | bool isJavaScript = SchemeIsJavascript(aLoadState->URI()); |
9333 | |
9334 | if (!isJavaScript) { |
9335 | toBeReset = MaybeInitTiming(); |
9336 | } |
9337 | bool isNotDownload = aLoadState->FileName().IsVoid(); |
9338 | if (mTiming && isNotDownload) { |
9339 | mTiming->NotifyBeforeUnload(); |
9340 | } |
9341 | // Check if the page doesn't want to be unloaded. The javascript: |
9342 | // protocol handler deals with this for javascript: URLs. |
9343 | if (!isJavaScript && isNotDownload && |
9344 | !aLoadState->NotifiedBeforeUnloadListeners() && mDocumentViewer) { |
9345 | bool okToUnload; |
9346 | |
9347 | // Check if request is exempted from HTTPSOnlyMode and if https-first is |
9348 | // enabled, if so it means: |
9349 | // * https-first failed to upgrade request to https |
9350 | // * we already asked for permission to unload and the user accepted |
9351 | // otherwise we wouldn't be here. |
9352 | bool isPrivateWin = GetOriginAttributes().IsPrivateBrowsing(); |
9353 | bool isHistoryOrReload = false; |
9354 | uint32_t loadType = aLoadState->LoadType(); |
9355 | |
9356 | // Check if request is a reload. |
9357 | if (loadType == LOAD_RELOAD_NORMAL || |
9358 | loadType == LOAD_RELOAD_BYPASS_CACHE || |
9359 | loadType == LOAD_RELOAD_BYPASS_PROXY || |
9360 | loadType == LOAD_RELOAD_BYPASS_PROXY_AND_CACHE || |
9361 | loadType == LOAD_HISTORY) { |
9362 | isHistoryOrReload = true; |
9363 | } |
9364 | |
9365 | // If it isn't a reload, the request already failed to be upgraded and |
9366 | // https-first is enabled then don't ask the user again for permission to |
9367 | // unload and just unload. |
9368 | if (!isHistoryOrReload && aLoadState->IsExemptFromHTTPSFirstMode() && |
9369 | nsHTTPSOnlyUtils::IsHttpsFirstModeEnabled(isPrivateWin)) { |
9370 | rv = mDocumentViewer->PermitUnload( |
9371 | nsIDocumentViewer::PermitUnloadAction::eDontPromptAndUnload, |
9372 | &okToUnload); |
9373 | } else { |
9374 | rv = mDocumentViewer->PermitUnload(&okToUnload); |
9375 | } |
9376 | |
9377 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && !okToUnload) { |
9378 | // The user chose not to unload the page, interrupt the |
9379 | // load. |
9380 | MaybeResetInitTiming(toBeReset); |
9381 | return NS_OK; |
9382 | } |
9383 | } |
9384 | |
9385 | if (mTiming && isNotDownload) { |
9386 | mTiming->NotifyUnloadAccepted(mCurrentURI); |
9387 | } |
9388 | |
9389 | // In e10s, in the parent process, we refuse to load anything other than |
9390 | // "safe" resources that we ship or trust enough to give "special" URLs. |
9391 | // Similar check will be performed by the ParentProcessDocumentChannel if in |
9392 | // use. |
9393 | if (XRE_IsE10sParentProcess() && |
9394 | !DocumentChannel::CanUseDocumentChannel(aLoadState->URI()) && |
9395 | !CanLoadInParentProcess(aLoadState->URI())) { |
9396 | return NS_ERROR_FAILURE; |
9397 | } |
9398 | |
9399 | // Whenever a top-level browsing context is navigated, the user agent MUST |
9400 | // lock the orientation of the document to the document's default |
9401 | // orientation. We don't explicitly check for a top-level browsing context |
9402 | // here because orientation is only set on top-level browsing contexts. |
9403 | if (mBrowsingContext->GetOrientationLock() != hal::ScreenOrientation::None) { |
9404 | 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" , 9404); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mBrowsingContext->IsTop()" ")"); do { *((volatile int*)__null) = 9404; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
9405 | 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" , 9406); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false" ") (" "NS_SUCCEEDED(mBrowsingContext->SetOrientationLock(hal::ScreenOrientation::None))" ")"); do { *((volatile int*)__null) = 9406; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) |
9406 | 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" , 9406); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false" ") (" "NS_SUCCEEDED(mBrowsingContext->SetOrientationLock(hal::ScreenOrientation::None))" ")"); do { *((volatile int*)__null) = 9406; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); |
9407 | if (mBrowsingContext->IsActive()) { |
9408 | ScreenOrientation::UpdateActiveOrientationLock( |
9409 | hal::ScreenOrientation::None); |
9410 | } |
9411 | } |
9412 | |
9413 | // Check for saving the presentation here, before calling Stop(). |
9414 | // This is necessary so that we can catch any pending requests. |
9415 | // Since the new request has not been created yet, we pass null for the |
9416 | // new request parameter. |
9417 | // Also pass nullptr for the document, since it doesn't affect the return |
9418 | // value for our purposes here. |
9419 | bool savePresentation = |
9420 | CanSavePresentation(aLoadState->LoadType(), nullptr, nullptr, |
9421 | /* aReportBFCacheComboTelemetry */ true); |
9422 | |
9423 | // nsDocShell::CanSavePresentation is for non-SHIP version only. Do a |
9424 | // separate check for SHIP so that we know if there are ongoing requests |
9425 | // before calling Stop() below. |
9426 | if (mozilla::SessionHistoryInParent()) { |
9427 | Document* document = GetDocument(); |
9428 | uint32_t flags = 0; |
9429 | if (document && !document->CanSavePresentation(nullptr, flags, true)) { |
9430 | // This forces some flags into the WindowGlobalParent's mBFCacheStatus, |
9431 | // which we'll then use in CanonicalBrowsingContext::AllowedInBFCache, |
9432 | // and in particular we'll store BFCacheStatus::REQUEST if needed. |
9433 | // Also, we want to report all the flags to the parent process here (and |
9434 | // not just BFCacheStatus::NOT_ALLOWED), so that it can update the |
9435 | // telemetry data correctly. |
9436 | document->DisallowBFCaching(flags); |
9437 | } |
9438 | } |
9439 | |
9440 | // Don't stop current network activity for javascript: URL's since |
9441 | // they might not result in any data, and thus nothing should be |
9442 | // stopped in those cases. In the case where they do result in |
9443 | // data, the javascript: URL channel takes care of stopping |
9444 | // current network activity. |
9445 | if (!isJavaScript && isNotDownload) { |
9446 | // Stop any current network activity. |
9447 | // Also stop content if this is a zombie doc. otherwise |
9448 | // the onload will be delayed by other loads initiated in the |
9449 | // background by the first document that |
9450 | // didn't fully load before the next load was initiated. |
9451 | // If not a zombie, don't stop content until data |
9452 | // starts arriving from the new URI... |
9453 | |
9454 | if ((mDocumentViewer && mDocumentViewer->GetPreviousViewer()) || |
9455 | LOAD_TYPE_HAS_FLAGS(aLoadState->LoadType(), LOAD_FLAGS_STOP_CONTENT)((aLoadState->LoadType()) & ((LOAD_FLAGS_STOP_CONTENT) << 16))) { |
9456 | rv = Stop(nsIWebNavigation::STOP_ALL); |
9457 | } else { |
9458 | rv = Stop(nsIWebNavigation::STOP_NETWORK); |
9459 | } |
9460 | |
9461 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
9462 | return rv; |
9463 | } |
9464 | } |
9465 | |
9466 | mLoadType = aLoadState->LoadType(); |
9467 | |
9468 | // aLoadState->SHEntry() should be assigned to mLSHE, only after Stop() has |
9469 | // been called. But when loading an error page, do not clear the |
9470 | // mLSHE for the real page. |
9471 | if (mLoadType != LOAD_ERROR_PAGE) { |
9472 | SetHistoryEntryAndUpdateBC(Some<nsISHEntry*>(aLoadState->SHEntry()), |
9473 | Nothing()); |
9474 | if (aLoadState->LoadIsFromSessionHistory() && |
9475 | !mozilla::SessionHistoryInParent()) { |
9476 | // We're making history navigation or a reload. Make sure our history ID |
9477 | // points to the same ID as SHEntry's docshell ID. |
9478 | nsID historyID = {}; |
9479 | aLoadState->SHEntry()->GetDocshellID(historyID); |
9480 | |
9481 | Unused << mBrowsingContext->SetHistoryID(historyID); |
9482 | } |
9483 | } |
9484 | |
9485 | mSavingOldViewer = savePresentation; |
9486 | |
9487 | // If we have a saved content viewer in history, restore and show it now. |
9488 | if (aLoadState->LoadIsFromSessionHistory() && |
9489 | (mLoadType & LOAD_CMD_HISTORY)) { |
9490 | // https://html.spec.whatwg.org/#history-traversal: |
9491 | // To traverse the history |
9492 | // "If entry has a different Document object than the current entry, then |
9493 | // run the following substeps: Remove any tasks queued by the history |
9494 | // traversal task source..." |
9495 | // Same document object case was handled already above with |
9496 | // HandleSameDocumentNavigation call. |
9497 | RefPtr<ChildSHistory> shistory = GetRootSessionHistory(); |
9498 | if (shistory) { |
9499 | shistory->RemovePendingHistoryNavigations(); |
9500 | } |
9501 | if (!mozilla::SessionHistoryInParent()) { |
9502 | // It's possible that the previous viewer of mDocumentViewer is the |
9503 | // viewer that will end up in aLoadState->SHEntry() when it gets closed. |
9504 | // If that's the case, we need to go ahead and force it into its shentry |
9505 | // so we can restore it. |
9506 | if (mDocumentViewer) { |
9507 | nsCOMPtr<nsIDocumentViewer> prevViewer = |
9508 | mDocumentViewer->GetPreviousViewer(); |
9509 | if (prevViewer) { |
9510 | #ifdef DEBUG1 |
9511 | nsCOMPtr<nsIDocumentViewer> prevPrevViewer = |
9512 | prevViewer->GetPreviousViewer(); |
9513 | 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" , 9513); MOZ_PretendNoReturn(); } } while (0); |
9514 | #endif |
9515 | nsCOMPtr<nsISHEntry> viewerEntry; |
9516 | prevViewer->GetHistoryEntry(getter_AddRefs(viewerEntry)); |
9517 | if (viewerEntry == aLoadState->SHEntry()) { |
9518 | // Make sure this viewer ends up in the right place |
9519 | mDocumentViewer->SetPreviousViewer(nullptr); |
9520 | prevViewer->Destroy(); |
9521 | } |
9522 | } |
9523 | } |
9524 | nsCOMPtr<nsISHEntry> oldEntry = mOSHE; |
9525 | bool restoring; |
9526 | rv = RestorePresentation(aLoadState->SHEntry(), &restoring); |
9527 | if (restoring) { |
9528 | Telemetry::Accumulate(Telemetry::BFCACHE_PAGE_RESTORED, true); |
9529 | return rv; |
9530 | } |
9531 | Telemetry::Accumulate(Telemetry::BFCACHE_PAGE_RESTORED, false); |
9532 | |
9533 | // We failed to restore the presentation, so clean up. |
9534 | // Both the old and new history entries could potentially be in |
9535 | // an inconsistent state. |
9536 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
9537 | if (oldEntry) { |
9538 | oldEntry->SyncPresentationState(); |
9539 | } |
9540 | |
9541 | aLoadState->SHEntry()->SyncPresentationState(); |
9542 | } |
9543 | } |
9544 | } |
9545 | |
9546 | bool isTopLevelDoc = mBrowsingContext->IsTopContent(); |
9547 | |
9548 | OriginAttributes attrs = GetOriginAttributes(); |
9549 | attrs.SetFirstPartyDomain(isTopLevelDoc, aLoadState->URI()); |
9550 | |
9551 | PredictorLearn(aLoadState->URI(), nullptr, |
9552 | nsINetworkPredictor::LEARN_LOAD_TOPLEVEL, attrs); |
9553 | PredictorPredict(aLoadState->URI(), nullptr, |
9554 | nsINetworkPredictor::PREDICT_LOAD, attrs, nullptr); |
9555 | |
9556 | nsCOMPtr<nsIRequest> req; |
9557 | rv = DoURILoad(aLoadState, aCacheKey, getter_AddRefs(req)); |
9558 | |
9559 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) { |
9560 | if (shouldTakeFocus) { |
9561 | mBrowsingContext->Focus(CallerType::System, IgnoreErrors()); |
9562 | } |
9563 | } |
9564 | |
9565 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
9566 | nsCOMPtr<nsIChannel> chan(do_QueryInterface(req)); |
9567 | UnblockEmbedderLoadEventForFailure(); |
9568 | nsCOMPtr<nsIURI> uri = aLoadState->URI(); |
9569 | if (DisplayLoadError(rv, uri, nullptr, chan) && |
9570 | // FIXME: At this point code was using internal load flags, but checking |
9571 | // non-internal load flags? |
9572 | aLoadState->HasLoadFlags(LOAD_FLAGS_ERROR_LOAD_CHANGES_RV)) { |
9573 | return NS_ERROR_LOAD_SHOWED_ERRORPAGE; |
9574 | } |
9575 | |
9576 | // We won't report any error if this is an unknown protocol error. The |
9577 | // reason behind this is that it will allow enumeration of external |
9578 | // protocols if we report an error for each unknown protocol. |
9579 | if (NS_ERROR_UNKNOWN_PROTOCOL == rv) { |
9580 | return NS_OK; |
9581 | } |
9582 | } |
9583 | |
9584 | return rv; |
9585 | } |
9586 | |
9587 | /* static */ |
9588 | bool nsDocShell::CanLoadInParentProcess(nsIURI* aURI) { |
9589 | nsCOMPtr<nsIURI> uri = aURI; |
9590 | // In e10s, in the parent process, we refuse to load anything other than |
9591 | // "safe" resources that we ship or trust enough to give "special" URLs. |
9592 | bool canLoadInParent = false; |
9593 | if (NS_SUCCEEDED(NS_URIChainHasFlags(((bool)(__builtin_expect(!!(!NS_FAILED_impl(NS_URIChainHasFlags ( uri, nsIProtocolHandler::URI_IS_UI_RESOURCE, &canLoadInParent ))), 1))) |
9594 | uri, nsIProtocolHandler::URI_IS_UI_RESOURCE, &canLoadInParent))((bool)(__builtin_expect(!!(!NS_FAILED_impl(NS_URIChainHasFlags ( uri, nsIProtocolHandler::URI_IS_UI_RESOURCE, &canLoadInParent ))), 1))) && |
9595 | canLoadInParent) { |
9596 | // We allow UI resources. |
9597 | return true; |
9598 | } |
9599 | // For about: and extension-based URIs, which don't get |
9600 | // URI_IS_UI_RESOURCE, first remove layers of view-source:, if present. |
9601 | while (uri && uri->SchemeIs("view-source")) { |
9602 | nsCOMPtr<nsINestedURI> nested = do_QueryInterface(uri); |
9603 | if (nested) { |
9604 | nested->GetInnerURI(getter_AddRefs(uri)); |
9605 | } else { |
9606 | break; |
9607 | } |
9608 | } |
9609 | // Allow about: URIs, and allow moz-extension ones if we're running |
9610 | // extension content in the parent process. |
9611 | if (!uri || uri->SchemeIs("about") || |
9612 | (!StaticPrefs::extensions_webextensions_remote() && |
9613 | uri->SchemeIs("moz-extension"))) { |
9614 | return true; |
9615 | } |
9616 | #ifdef MOZ_THUNDERBIRD |
9617 | if (uri->SchemeIs("imap") || uri->SchemeIs("mailbox") || |
9618 | uri->SchemeIs("news") || uri->SchemeIs("nntp") || |
9619 | uri->SchemeIs("snews") || uri->SchemeIs("x-moz-ews")) { |
9620 | return true; |
9621 | } |
9622 | #endif |
9623 | nsAutoCString scheme; |
9624 | uri->GetScheme(scheme); |
9625 | // Allow ext+foo URIs (extension-registered custom protocols). See |
9626 | // https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/protocol_handlers |
9627 | if (StringBeginsWith(scheme, "ext+"_ns) && |
9628 | !StaticPrefs::extensions_webextensions_remote()) { |
9629 | return true; |
9630 | } |
9631 | // Final exception for some legacy automated tests: |
9632 | if (xpc::IsInAutomation() && |
9633 | StaticPrefs::security_allow_unsafe_parent_loads()) { |
9634 | return true; |
9635 | } |
9636 | return false; |
9637 | } |
9638 | |
9639 | nsIPrincipal* nsDocShell::GetInheritedPrincipal( |
9640 | bool aConsiderCurrentDocument, bool aConsiderPartitionedPrincipal) { |
9641 | RefPtr<Document> document; |
9642 | bool inheritedFromCurrent = false; |
9643 | |
9644 | if (aConsiderCurrentDocument && mDocumentViewer) { |
9645 | document = mDocumentViewer->GetDocument(); |
9646 | inheritedFromCurrent = true; |
9647 | } |
9648 | |
9649 | if (!document) { |
9650 | nsCOMPtr<nsIDocShellTreeItem> parentItem; |
9651 | GetInProcessSameTypeParent(getter_AddRefs(parentItem)); |
9652 | if (parentItem) { |
9653 | document = parentItem->GetDocument(); |
9654 | } |
9655 | } |
9656 | |
9657 | if (!document) { |
9658 | if (!aConsiderCurrentDocument) { |
9659 | return nullptr; |
9660 | } |
9661 | |
9662 | // Make sure we end up with _something_ as the principal no matter |
9663 | // what.If this fails, we'll just get a null docViewer and bail. |
9664 | EnsureDocumentViewer(); |
9665 | if (!mDocumentViewer) { |
9666 | return nullptr; |
9667 | } |
9668 | document = mDocumentViewer->GetDocument(); |
9669 | } |
9670 | |
9671 | //-- Get the document's principal |
9672 | if (document) { |
9673 | nsIPrincipal* docPrincipal = aConsiderPartitionedPrincipal |
9674 | ? document->PartitionedPrincipal() |
9675 | : document->NodePrincipal(); |
9676 | |
9677 | // Don't allow loads in typeContent docShells to inherit the system |
9678 | // principal from existing documents. |
9679 | if (inheritedFromCurrent && mItemType == typeContent && |
9680 | docPrincipal->IsSystemPrincipal()) { |
9681 | return nullptr; |
9682 | } |
9683 | |
9684 | return docPrincipal; |
9685 | } |
9686 | |
9687 | return nullptr; |
9688 | } |
9689 | |
9690 | /* static */ nsresult nsDocShell::CreateRealChannelForDocument( |
9691 | nsIChannel** aChannel, nsIURI* aURI, nsILoadInfo* aLoadInfo, |
9692 | nsIInterfaceRequestor* aCallbacks, nsLoadFlags aLoadFlags, |
9693 | const nsAString& aSrcdoc, nsIURI* aBaseURI) { |
9694 | nsCOMPtr<nsIChannel> channel; |
9695 | if (aSrcdoc.IsVoid()) { |
9696 | 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) |
9697 | 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) |
9698 | 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) |
9699 | 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); |
9700 | |
9701 | if (aBaseURI) { |
9702 | nsCOMPtr<nsIViewSourceChannel> vsc = do_QueryInterface(channel); |
9703 | if (vsc) { |
9704 | 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" , 9704); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false" ") (" "NS_SUCCEEDED(vsc->SetBaseURI(aBaseURI))" ")"); do { *((volatile int*)__null) = 9704; __attribute__((nomerge)) :: abort(); } while (false); } } while (false); } } while (false ); |
9705 | } |
9706 | } |
9707 | } else if (SchemeIsViewSource(aURI)) { |
9708 | // Instantiate view source handler protocol, if it doesn't exist already. |
9709 | nsCOMPtr<nsIIOService> io(do_GetIOService()); |
9710 | 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" , 9710); AnnotateMozCrashReason("MOZ_ASSERT" "(" "io" ")"); do { *((volatile int*)__null) = 9710; __attribute__((nomerge)) :: abort(); } while (false); } } while (false); |
9711 | nsCOMPtr<nsIProtocolHandler> handler; |
9712 | nsresult rv = |
9713 | io->GetProtocolHandler("view-source", getter_AddRefs(handler)); |
9714 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
9715 | return rv; |
9716 | } |
9717 | |
9718 | nsViewSourceHandler* vsh = nsViewSourceHandler::GetInstance(); |
9719 | if (!vsh) { |
9720 | return NS_ERROR_FAILURE; |
9721 | } |
9722 | |
9723 | 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) |
9724 | 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); |
9725 | } else { |
9726 | 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) |
9727 | 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) |
9728 | 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); |
9729 | nsCOMPtr<nsIInputStreamChannel> isc = do_QueryInterface(channel); |
9730 | 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" , 9730); AnnotateMozCrashReason("MOZ_ASSERT" "(" "isc" ")"); do { *((volatile int*)__null) = 9730; __attribute__((nomerge)) :: abort(); } while (false); } } while (false); |
9731 | isc->SetBaseURI(aBaseURI); |
9732 | } |
9733 | |
9734 | if (aLoadFlags != nsIRequest::LOAD_NORMAL) { |
9735 | nsresult rv = channel->SetLoadFlags(aLoadFlags); |
9736 | 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" , 9736); return rv; } } while (false); |
9737 | } |
9738 | |
9739 | channel.forget(aChannel); |
9740 | return NS_OK; |
9741 | } |
9742 | |
9743 | /* static */ bool nsDocShell::CreateAndConfigureRealChannelForLoadState( |
9744 | BrowsingContext* aBrowsingContext, nsDocShellLoadState* aLoadState, |
9745 | LoadInfo* aLoadInfo, nsIInterfaceRequestor* aCallbacks, |
9746 | nsDocShell* aDocShell, const OriginAttributes& aOriginAttributes, |
9747 | nsLoadFlags aLoadFlags, uint32_t aCacheKey, nsresult& aRv, |
9748 | nsIChannel** aChannel) { |
9749 | 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" , 9749); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadInfo" ")" ); do { *((volatile int*)__null) = 9749; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
9750 | |
9751 | nsString srcdoc = VoidString(); |
9752 | bool isSrcdoc = |
9753 | aLoadState->HasInternalLoadFlags(INTERNAL_LOAD_FLAGS_IS_SRCDOC); |
9754 | if (isSrcdoc) { |
9755 | srcdoc = aLoadState->SrcdocData(); |
9756 | } |
9757 | |
9758 | aLoadInfo->SetTriggeringRemoteType( |
9759 | aLoadState->GetEffectiveTriggeringRemoteType()); |
9760 | |
9761 | if (aLoadState->PrincipalToInherit()) { |
9762 | aLoadInfo->SetPrincipalToInherit(aLoadState->PrincipalToInherit()); |
9763 | } |
9764 | aLoadInfo->SetLoadTriggeredFromExternal( |
9765 | aLoadState->HasLoadFlags(LOAD_FLAGS_FROM_EXTERNAL)); |
9766 | aLoadInfo->SetForceAllowDataURI(aLoadState->HasInternalLoadFlags( |
9767 | INTERNAL_LOAD_FLAGS_FORCE_ALLOW_DATA_URI)); |
9768 | aLoadInfo->SetOriginalFrameSrcLoad( |
9769 | aLoadState->HasInternalLoadFlags(INTERNAL_LOAD_FLAGS_ORIGINAL_FRAME_SRC)); |
9770 | |
9771 | bool inheritAttrs = false; |
9772 | if (aLoadState->PrincipalToInherit()) { |
9773 | inheritAttrs = nsContentUtils::ChannelShouldInheritPrincipal( |
9774 | aLoadState->PrincipalToInherit(), aLoadState->URI(), |
9775 | true, // aInheritForAboutBlank |
9776 | isSrcdoc); |
9777 | } |
9778 | |
9779 | // Strip the target query parameters before creating the channel. |
9780 | aLoadState->MaybeStripTrackerQueryStrings(aBrowsingContext); |
9781 | |
9782 | OriginAttributes attrs; |
9783 | |
9784 | // Inherit origin attributes from PrincipalToInherit if inheritAttrs is |
9785 | // true. Otherwise we just use the origin attributes from docshell. |
9786 | if (inheritAttrs) { |
9787 | 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" , 9788); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->PrincipalToInherit()" ") (" "We should have PrincipalToInherit here." ")"); do { * ((volatile int*)__null) = 9788; __attribute__((nomerge)) ::abort (); } while (false); } } while (false) |
9788 | "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" , 9788); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->PrincipalToInherit()" ") (" "We should have PrincipalToInherit here." ")"); do { * ((volatile int*)__null) = 9788; __attribute__((nomerge)) ::abort (); } while (false); } } while (false); |
9789 | attrs = aLoadState->PrincipalToInherit()->OriginAttributesRef(); |
9790 | // If firstPartyIsolation is not enabled, then PrincipalToInherit should |
9791 | // have the same origin attributes with docshell. |
9792 | 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" , 9793); AnnotateMozCrashReason("MOZ_ASSERT" "(" "attrs == aOriginAttributes" ")"); do { *((volatile int*)__null) = 9793; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) |
9793 | 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" , 9793); AnnotateMozCrashReason("MOZ_ASSERT" "(" "attrs == aOriginAttributes" ")"); do { *((volatile int*)__null) = 9793; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); |
9794 | } else { |
9795 | attrs = aOriginAttributes; |
9796 | attrs.SetFirstPartyDomain(IsTopLevelDoc(aBrowsingContext, aLoadInfo), |
9797 | aLoadState->URI()); |
9798 | } |
9799 | |
9800 | aRv = aLoadInfo->SetOriginAttributes(attrs); |
9801 | 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" , 9801)) { |
9802 | return false; |
9803 | } |
9804 | |
9805 | if (aLoadState->GetIsFromProcessingFrameAttributes()) { |
9806 | aLoadInfo->SetIsFromProcessingFrameAttributes(); |
9807 | } |
9808 | |
9809 | // Propagate the IsFormSubmission flag to the loadInfo. |
9810 | if (aLoadState->IsFormSubmission()) { |
9811 | aLoadInfo->SetIsFormSubmission(true); |
9812 | } |
9813 | |
9814 | aLoadInfo->SetUnstrippedURI(aLoadState->GetUnstrippedURI()); |
9815 | |
9816 | nsCOMPtr<nsIChannel> channel; |
9817 | aRv = CreateRealChannelForDocument(getter_AddRefs(channel), aLoadState->URI(), |
9818 | aLoadInfo, aCallbacks, aLoadFlags, srcdoc, |
9819 | aLoadState->BaseURI()); |
9820 | 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" , 9820); return false; } } while (false); |
9821 | |
9822 | if (!channel) { |
9823 | return false; |
9824 | } |
9825 | |
9826 | // If the HTTPS-Only mode is enabled, every insecure request gets upgraded to |
9827 | // HTTPS by default. This behavior can be disabled through the loadinfo flag |
9828 | // HTTPS_ONLY_EXEMPT. |
9829 | nsHTTPSOnlyUtils::TestSitePermissionAndPotentiallyAddExemption(channel); |
9830 | |
9831 | // hack |
9832 | nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(channel)); |
9833 | nsCOMPtr<nsIHttpChannelInternal> httpChannelInternal( |
9834 | do_QueryInterface(channel)); |
9835 | nsCOMPtr<nsIURI> referrer; |
9836 | nsIReferrerInfo* referrerInfo = aLoadState->GetReferrerInfo(); |
9837 | if (referrerInfo) { |
9838 | referrerInfo->GetOriginalReferrer(getter_AddRefs(referrer)); |
9839 | } |
9840 | if (httpChannelInternal) { |
9841 | if (aLoadState->HasInternalLoadFlags( |
9842 | INTERNAL_LOAD_FLAGS_FORCE_ALLOW_COOKIES)) { |
9843 | aRv = httpChannelInternal->SetThirdPartyFlags( |
9844 | nsIHttpChannelInternal::THIRD_PARTY_FORCE_ALLOW); |
9845 | 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" , 9845); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1)))" ")"); do { *((volatile int*)__null) = 9845; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
9846 | } |
9847 | if (aLoadState->FirstParty()) { |
9848 | aRv = httpChannelInternal->SetDocumentURI(aLoadState->URI()); |
9849 | 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" , 9849); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1)))" ")"); do { *((volatile int*)__null) = 9849; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
9850 | } else { |
9851 | aRv = httpChannelInternal->SetDocumentURI(referrer); |
9852 | 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" , 9852); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1)))" ")"); do { *((volatile int*)__null) = 9852; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
9853 | } |
9854 | aRv = httpChannelInternal->SetRedirectMode( |
9855 | nsIHttpChannelInternal::REDIRECT_MODE_MANUAL); |
9856 | 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" , 9856); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1)))" ")"); do { *((volatile int*)__null) = 9856; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
9857 | } |
9858 | |
9859 | if (httpChannel) { |
9860 | if (aLoadState->HeadersStream()) { |
9861 | aRv = AddHeadersToChannel(aLoadState->HeadersStream(), httpChannel); |
9862 | } |
9863 | // Set the referrer explicitly |
9864 | // Referrer is currenly only set for link clicks here. |
9865 | if (referrerInfo) { |
9866 | aRv = httpChannel->SetReferrerInfo(referrerInfo); |
9867 | 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" , 9867); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1)))" ")"); do { *((volatile int*)__null) = 9867; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
9868 | } |
9869 | |
9870 | // Mark the http channel as UrgentStart for top level document loading in |
9871 | // active tab. |
9872 | if (IsUrgentStart(aBrowsingContext, aLoadInfo, aLoadState->LoadType())) { |
9873 | nsCOMPtr<nsIClassOfService> cos(do_QueryInterface(channel)); |
9874 | if (cos) { |
9875 | cos->AddClassFlags(nsIClassOfService::UrgentStart); |
9876 | if (StaticPrefs::dom_document_priority_incremental()) { |
9877 | cos->SetIncremental(true); |
9878 | } |
9879 | } |
9880 | } |
9881 | } |
9882 | |
9883 | channel->SetOriginalURI(aLoadState->OriginalURI() ? aLoadState->OriginalURI() |
9884 | : aLoadState->URI()); |
9885 | |
9886 | const nsACString& typeHint = aLoadState->TypeHint(); |
9887 | if (!typeHint.IsVoid()) { |
9888 | channel->SetContentType(typeHint); |
9889 | } |
9890 | |
9891 | const nsAString& fileName = aLoadState->FileName(); |
9892 | if (!fileName.IsVoid()) { |
9893 | aRv = channel->SetContentDisposition(nsIChannel::DISPOSITION_ATTACHMENT); |
9894 | 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" , 9894); return false; } } while (false); |
9895 | if (!fileName.IsEmpty()) { |
9896 | aRv = channel->SetContentDispositionFilename(fileName); |
9897 | 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" , 9897); return false; } } while (false); |
9898 | } |
9899 | } |
9900 | |
9901 | if (nsCOMPtr<nsIWritablePropertyBag2> props = do_QueryInterface(channel)) { |
9902 | nsCOMPtr<nsIURI> referrer; |
9903 | nsIReferrerInfo* referrerInfo = aLoadState->GetReferrerInfo(); |
9904 | if (referrerInfo) { |
9905 | referrerInfo->GetOriginalReferrer(getter_AddRefs(referrer)); |
9906 | } |
9907 | // save true referrer for those who need it (e.g. xpinstall whitelisting) |
9908 | // Currently only http and ftp channels support this. |
9909 | props->SetPropertyAsInterface(u"docshell.internalReferrer"_ns, referrer); |
9910 | |
9911 | if (aLoadState->HasInternalLoadFlags(INTERNAL_LOAD_FLAGS_FIRST_LOAD)) { |
9912 | props->SetPropertyAsBool(u"docshell.newWindowTarget"_ns, true); |
9913 | } |
9914 | } |
9915 | |
9916 | nsCOMPtr<nsICacheInfoChannel> cacheChannel(do_QueryInterface(channel)); |
9917 | auto loadType = aLoadState->LoadType(); |
9918 | |
9919 | if (loadType == LOAD_RELOAD_NORMAL && |
9920 | StaticPrefs:: |
9921 | browser_soft_reload_only_force_validate_top_level_document()) { |
9922 | nsCOMPtr<nsICacheInfoChannel> cachingChannel = do_QueryInterface(channel); |
9923 | if (cachingChannel) { |
9924 | cachingChannel->SetForceValidateCacheContent(true); |
9925 | } |
9926 | } |
9927 | |
9928 | // figure out if we need to set the post data stream on the channel... |
9929 | if (aLoadState->PostDataStream()) { |
9930 | if (nsCOMPtr<nsIFormPOSTActionChannel> postChannel = |
9931 | do_QueryInterface(channel)) { |
9932 | // XXX it's a bit of a hack to rewind the postdata stream here but |
9933 | // it has to be done in case the post data is being reused multiple |
9934 | // times. |
9935 | nsCOMPtr<nsISeekableStream> postDataSeekable = |
9936 | do_QueryInterface(aLoadState->PostDataStream()); |
9937 | if (postDataSeekable) { |
9938 | aRv = postDataSeekable->Seek(nsISeekableStream::NS_SEEK_SET, 0); |
9939 | 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" , 9939); return false; } } while (false); |
9940 | } |
9941 | |
9942 | // we really need to have a content type associated with this stream!! |
9943 | postChannel->SetUploadStream(aLoadState->PostDataStream(), ""_ns, -1); |
9944 | |
9945 | // Ownership of the stream has transferred to the channel, clear our |
9946 | // reference. |
9947 | aLoadState->SetPostDataStream(nullptr); |
9948 | } |
9949 | |
9950 | /* If there is a valid postdata *and* it is a History Load, |
9951 | * set up the cache key on the channel, to retrieve the |
9952 | * data *only* from the cache. If it is a normal reload, the |
9953 | * cache is free to go to the server for updated postdata. |
9954 | */ |
9955 | if (cacheChannel && aCacheKey != 0) { |
9956 | if (loadType == LOAD_HISTORY || loadType == LOAD_RELOAD_CHARSET_CHANGE) { |
9957 | cacheChannel->SetCacheKey(aCacheKey); |
9958 | uint32_t loadFlags; |
9959 | if (NS_SUCCEEDED(channel->GetLoadFlags(&loadFlags))((bool)(__builtin_expect(!!(!NS_FAILED_impl(channel->GetLoadFlags (&loadFlags))), 1)))) { |
9960 | channel->SetLoadFlags(loadFlags | |
9961 | nsICachingChannel::LOAD_ONLY_FROM_CACHE); |
9962 | } |
9963 | } else if (loadType == LOAD_RELOAD_NORMAL) { |
9964 | cacheChannel->SetCacheKey(aCacheKey); |
9965 | } |
9966 | } |
9967 | } else { |
9968 | /* If there is no postdata, set the cache key on the channel, and |
9969 | * do not set the LOAD_ONLY_FROM_CACHE flag, so that the channel |
9970 | * will be free to get it from net if it is not found in cache. |
9971 | * New cache may use it creatively on CGI pages with GET |
9972 | * method and even on those that say "no-cache" |
9973 | */ |
9974 | if (loadType == LOAD_HISTORY || loadType == LOAD_RELOAD_NORMAL || |
9975 | loadType == LOAD_RELOAD_CHARSET_CHANGE || |
9976 | loadType == LOAD_RELOAD_CHARSET_CHANGE_BYPASS_CACHE || |
9977 | loadType == LOAD_RELOAD_CHARSET_CHANGE_BYPASS_PROXY_AND_CACHE) { |
9978 | if (cacheChannel && aCacheKey != 0) { |
9979 | cacheChannel->SetCacheKey(aCacheKey); |
9980 | } |
9981 | } |
9982 | } |
9983 | |
9984 | if (nsCOMPtr<nsIScriptChannel> scriptChannel = do_QueryInterface(channel)) { |
9985 | // Allow execution against our context if the principals match |
9986 | scriptChannel->SetExecutionPolicy(nsIScriptChannel::EXECUTE_NORMAL); |
9987 | } |
9988 | |
9989 | if (nsCOMPtr<nsITimedChannel> timedChannel = do_QueryInterface(channel)) { |
9990 | timedChannel->SetTimingEnabled(true); |
9991 | |
9992 | nsString initiatorType; |
9993 | switch (aLoadInfo->InternalContentPolicyType()) { |
9994 | case nsIContentPolicy::TYPE_INTERNAL_EMBED: |
9995 | initiatorType = u"embed"_ns; |
9996 | break; |
9997 | case nsIContentPolicy::TYPE_INTERNAL_OBJECT: |
9998 | initiatorType = u"object"_ns; |
9999 | break; |
10000 | default: { |
10001 | const auto& embedderElementType = |
10002 | aBrowsingContext->GetEmbedderElementType(); |
10003 | if (embedderElementType) { |
10004 | initiatorType = *embedderElementType; |
10005 | } |
10006 | break; |
10007 | } |
10008 | } |
10009 | |
10010 | if (!initiatorType.IsEmpty()) { |
10011 | timedChannel->SetInitiatorType(initiatorType); |
10012 | } |
10013 | } |
10014 | |
10015 | nsCOMPtr<nsIURI> rpURI; |
10016 | aLoadInfo->GetResultPrincipalURI(getter_AddRefs(rpURI)); |
10017 | Maybe<nsCOMPtr<nsIURI>> originalResultPrincipalURI; |
10018 | aLoadState->GetMaybeResultPrincipalURI(originalResultPrincipalURI); |
10019 | if (originalResultPrincipalURI && |
10020 | (!aLoadState->KeepResultPrincipalURIIfSet() || !rpURI)) { |
10021 | // Unconditionally override, we want the replay to be equal to what has |
10022 | // been captured. |
10023 | aLoadInfo->SetResultPrincipalURI(originalResultPrincipalURI.ref()); |
10024 | } |
10025 | |
10026 | if (aLoadState->OriginalURI() && aLoadState->LoadReplace()) { |
10027 | // The LOAD_REPLACE flag and its handling here will be removed as part |
10028 | // of bug 1319110. For now preserve its restoration here to not break |
10029 | // any code expecting it being set specially on redirected channels. |
10030 | // If the flag has originally been set to change result of |
10031 | // NS_GetFinalChannelURI it won't have any effect and also won't cause |
10032 | // any harm. |
10033 | uint32_t loadFlags; |
10034 | aRv = channel->GetLoadFlags(&loadFlags); |
10035 | 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" , 10035); return false; } } while (false); |
10036 | channel->SetLoadFlags(loadFlags | nsIChannel::LOAD_REPLACE); |
10037 | } |
10038 | |
10039 | nsCOMPtr<nsIContentSecurityPolicy> csp = aLoadState->Csp(); |
10040 | if (csp) { |
10041 | // Navigational requests that are same origin need to be upgraded in case |
10042 | // upgrade-insecure-requests is present. Please note that for document |
10043 | // navigations that bit is re-computed in case we encounter a server |
10044 | // side redirect so the navigation is not same-origin anymore. |
10045 | bool upgradeInsecureRequests = false; |
10046 | csp->GetUpgradeInsecureRequests(&upgradeInsecureRequests); |
10047 | if (upgradeInsecureRequests) { |
10048 | // only upgrade if the navigation is same origin |
10049 | nsCOMPtr<nsIPrincipal> resultPrincipal; |
10050 | aRv = nsContentUtils::GetSecurityManager()->GetChannelResultPrincipal( |
10051 | channel, getter_AddRefs(resultPrincipal)); |
10052 | 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" , 10052); return false; } } while (false); |
10053 | if (nsContentSecurityUtils::IsConsideredSameOriginForUIR( |
10054 | aLoadState->TriggeringPrincipal(), resultPrincipal)) { |
10055 | aLoadInfo->SetUpgradeInsecureRequests(true); |
10056 | } |
10057 | } |
10058 | |
10059 | // For document loads we store the CSP that potentially needs to |
10060 | // be inherited by the new document, e.g. in case we are loading |
10061 | // an opaque origin like a data: URI. The actual inheritance |
10062 | // check happens within Document::InitCSP(). |
10063 | // Please create an actual copy of the CSP (do not share the same |
10064 | // reference) otherwise a Meta CSP of an opaque origin will |
10065 | // incorrectly be propagated to the embedding document. |
10066 | RefPtr<nsCSPContext> cspToInherit = new nsCSPContext(); |
10067 | cspToInherit->InitFromOther(static_cast<nsCSPContext*>(csp.get())); |
10068 | aLoadInfo->SetCSPToInherit(cspToInherit); |
10069 | } |
10070 | |
10071 | channel.forget(aChannel); |
10072 | return true; |
10073 | } |
10074 | |
10075 | bool nsDocShell::IsAboutBlankLoadOntoInitialAboutBlank( |
10076 | nsIURI* aURI, bool aInheritPrincipal, nsIPrincipal* aPrincipalToInherit) { |
10077 | return NS_IsAboutBlankAllowQueryAndFragment(aURI) && aInheritPrincipal && |
10078 | (aPrincipalToInherit == GetInheritedPrincipal(false)) && |
10079 | (!mDocumentViewer || !mDocumentViewer->GetDocument() || |
10080 | mDocumentViewer->GetDocument()->IsInitialDocument()); |
10081 | } |
10082 | |
10083 | nsresult nsDocShell::DoURILoad(nsDocShellLoadState* aLoadState, |
10084 | Maybe<uint32_t> aCacheKey, |
10085 | nsIRequest** aRequest) { |
10086 | // Double-check that we're still around to load this URI. |
10087 | if (mIsBeingDestroyed) { |
10088 | // Return NS_OK despite not doing anything to avoid throwing exceptions |
10089 | // from nsLocation::SetHref if the unload handler of the existing page |
10090 | // tears us down. |
10091 | return NS_OK; |
10092 | } |
10093 | |
10094 | nsCOMPtr<nsIURILoader> uriLoader = components::URILoader::Service(); |
10095 | if (NS_WARN_IF(!uriLoader)NS_warn_if_impl(!uriLoader, "!uriLoader", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 10095)) { |
10096 | return NS_ERROR_UNEXPECTED; |
10097 | } |
10098 | |
10099 | // Persist and sync layout history state before we load a new uri, as this |
10100 | // might be our last chance to do so, in the content process. |
10101 | PersistLayoutHistoryState(); |
10102 | SynchronizeLayoutHistoryState(); |
10103 | |
10104 | nsresult rv; |
10105 | nsContentPolicyType contentPolicyType = DetermineContentType(); |
10106 | |
10107 | if (IsSubframe()) { |
10108 | 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" , 10110); 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) = 10110; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false) |
10109 | 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" , 10110); 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) = 10110; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false) |
10110 | "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" , 10110); 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) = 10110; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
10111 | |
10112 | if (StaticPrefs::dom_block_external_protocol_in_iframes()) { |
10113 | // Only allow URLs able to return data in iframes. |
10114 | if (nsContentUtils::IsExternalProtocol(aLoadState->URI())) { |
10115 | // The context to check user-interaction with for the purposes of |
10116 | // popup-blocking. |
10117 | // |
10118 | // We generally want to check the context that initiated the navigation. |
10119 | WindowContext* sourceWindowContext = [&] { |
10120 | const MaybeDiscardedBrowsingContext& sourceBC = |
10121 | aLoadState->SourceBrowsingContext(); |
10122 | if (!sourceBC.IsNullOrDiscarded()) { |
10123 | if (WindowContext* wc = sourceBC.get()->GetCurrentWindowContext()) { |
10124 | return wc; |
10125 | } |
10126 | } |
10127 | return mBrowsingContext->GetParentWindowContext(); |
10128 | }(); |
10129 | |
10130 | 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" , 10130); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sourceWindowContext" ")"); do { *((volatile int*)__null) = 10130; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
10131 | // FIXME: We can't check user-interaction against an OOP window. This is |
10132 | // the next best thing we can really do. The load state keeps whether |
10133 | // the navigation had a user interaction in process |
10134 | // (aLoadState->HasValidUserGestureActivation()), but we can't really |
10135 | // consume it, which we want to prevent popup-spamming from the same |
10136 | // click event. |
10137 | WindowContext* context = |
10138 | sourceWindowContext->IsInProcess() |
10139 | ? sourceWindowContext |
10140 | : mBrowsingContext->GetCurrentWindowContext(); |
10141 | const bool popupBlocked = [&] { |
10142 | const bool active = mBrowsingContext->IsActive(); |
10143 | |
10144 | // For same-origin-with-top windows, we grant a single free popup |
10145 | // without user activation, see bug 1680721. |
10146 | // |
10147 | // We consume the flag now even if there's no user activation. |
10148 | const bool hasFreePass = [&] { |
10149 | if (!active || |
10150 | !(context->IsInProcess() && context->SameOriginWithTop())) { |
10151 | return false; |
10152 | } |
10153 | nsGlobalWindowInner* win = |
10154 | context->TopWindowContext()->GetInnerWindow(); |
10155 | return win && win->TryOpenExternalProtocolIframe(); |
10156 | }(); |
10157 | |
10158 | if (context->IsInProcess() && |
10159 | context->ConsumeTransientUserGestureActivation()) { |
10160 | // If the user has interacted with the page, consume it. |
10161 | return false; |
10162 | } |
10163 | |
10164 | // TODO(emilio): Can we remove this check? It seems like what prompted |
10165 | // this code (bug 1514547) should be covered by transient user |
10166 | // activation, see bug 1514547. |
10167 | if (active && |
10168 | PopupBlocker::ConsumeTimerTokenForExternalProtocolIframe()) { |
10169 | return false; |
10170 | } |
10171 | |
10172 | if (sourceWindowContext->CanShowPopup()) { |
10173 | return false; |
10174 | } |
10175 | |
10176 | if (hasFreePass) { |
10177 | return false; |
10178 | } |
10179 | |
10180 | return true; |
10181 | }(); |
10182 | |
10183 | // No error must be returned when iframes are blocked. |
10184 | if (popupBlocked) { |
10185 | nsAutoString message; |
10186 | nsresult rv = nsContentUtils::GetLocalizedString( |
10187 | nsContentUtils::eDOM_PROPERTIES, |
10188 | "ExternalProtocolFrameBlockedNoUserActivation", message); |
10189 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) { |
10190 | nsContentUtils::ReportToConsoleByWindowID( |
10191 | message, nsIScriptError::warningFlag, "DOM"_ns, |
10192 | context->InnerWindowId()); |
10193 | } |
10194 | return NS_OK; |
10195 | } |
10196 | } |
10197 | } |
10198 | |
10199 | // Only allow view-source scheme in top-level docshells. view-source is |
10200 | // the only scheme to which this applies at the moment due to potential |
10201 | // timing attacks to read data from cross-origin iframes. If this widens |
10202 | // we should add a protocol flag for whether the scheme is allowed in |
10203 | // frames and use something like nsNetUtil::NS_URIChainHasFlags. |
10204 | nsCOMPtr<nsIURI> tempURI = aLoadState->URI(); |
10205 | nsCOMPtr<nsINestedURI> nestedURI = do_QueryInterface(tempURI); |
10206 | while (nestedURI) { |
10207 | // view-source should always be an nsINestedURI, loop and check the |
10208 | // scheme on this and all inner URIs that are also nested URIs. |
10209 | if (SchemeIsViewSource(tempURI)) { |
10210 | return NS_ERROR_UNKNOWN_PROTOCOL; |
10211 | } |
10212 | nestedURI->GetInnerURI(getter_AddRefs(tempURI)); |
10213 | nestedURI = do_QueryInterface(tempURI); |
10214 | } |
10215 | } else { |
10216 | 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" , 10217); AnnotateMozCrashReason("MOZ_ASSERT" "(" "contentPolicyType == nsIContentPolicy::TYPE_DOCUMENT" ") (" "DoURILoad thinks this is a document and InternalLoad does not" ")"); do { *((volatile int*)__null) = 10217; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false) |
10217 | "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" , 10217); AnnotateMozCrashReason("MOZ_ASSERT" "(" "contentPolicyType == nsIContentPolicy::TYPE_DOCUMENT" ") (" "DoURILoad thinks this is a document and InternalLoad does not" ")"); do { *((volatile int*)__null) = 10217; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
10218 | } |
10219 | |
10220 | // We want to inherit aLoadState->PrincipalToInherit() when: |
10221 | // 1. ChannelShouldInheritPrincipal returns true. |
10222 | // 2. aLoadState->URI() is not data: URI, or data: URI is not |
10223 | // configured as unique opaque origin. |
10224 | bool inheritPrincipal = false; |
10225 | |
10226 | if (aLoadState->PrincipalToInherit()) { |
10227 | bool isSrcdoc = |
10228 | aLoadState->HasInternalLoadFlags(INTERNAL_LOAD_FLAGS_IS_SRCDOC); |
10229 | bool inheritAttrs = nsContentUtils::ChannelShouldInheritPrincipal( |
10230 | aLoadState->PrincipalToInherit(), aLoadState->URI(), |
10231 | true, // aInheritForAboutBlank |
10232 | isSrcdoc); |
10233 | |
10234 | inheritPrincipal = inheritAttrs && !SchemeIsData(aLoadState->URI()); |
10235 | } |
10236 | |
10237 | // See https://bugzilla.mozilla.org/show_bug.cgi?id=1736570 |
10238 | const bool isAboutBlankLoadOntoInitialAboutBlank = |
10239 | IsAboutBlankLoadOntoInitialAboutBlank(aLoadState->URI(), inheritPrincipal, |
10240 | aLoadState->PrincipalToInherit()); |
10241 | |
10242 | // FIXME We still have a ton of codepaths that don't pass through |
10243 | // DocumentLoadListener, so probably need to create session history info |
10244 | // in more places. |
10245 | if (aLoadState->GetLoadingSessionHistoryInfo()) { |
10246 | SetLoadingSessionHistoryInfo(*aLoadState->GetLoadingSessionHistoryInfo()); |
10247 | } else if (isAboutBlankLoadOntoInitialAboutBlank && |
10248 | mozilla::SessionHistoryInParent()) { |
10249 | // Materialize LoadingSessionHistoryInfo here, because DocumentChannel |
10250 | // loads have it, and later history behavior depends on it existing. |
10251 | UniquePtr<SessionHistoryInfo> entry = MakeUnique<SessionHistoryInfo>( |
10252 | aLoadState->URI(), aLoadState->TriggeringPrincipal(), |
10253 | aLoadState->PrincipalToInherit(), |
10254 | aLoadState->PartitionedPrincipalToInherit(), aLoadState->Csp(), |
10255 | mContentTypeHint); |
10256 | mozilla::dom::LoadingSessionHistoryInfo info(*entry); |
10257 | SetLoadingSessionHistoryInfo(info, true); |
10258 | } |
10259 | |
10260 | // open a channel for the url |
10261 | |
10262 | // If we have a pending channel, use the channel we've already created here. |
10263 | // We don't need to set up load flags for our channel, as it has already been |
10264 | // created. |
10265 | |
10266 | if (nsCOMPtr<nsIChannel> channel = |
10267 | aLoadState->GetPendingRedirectedChannel()) { |
10268 | // If we have a request outparameter, shove our channel into it. |
10269 | if (aRequest) { |
10270 | nsCOMPtr<nsIRequest> outRequest = channel; |
10271 | outRequest.forget(aRequest); |
10272 | } |
10273 | |
10274 | return OpenRedirectedChannel(aLoadState); |
10275 | } |
10276 | |
10277 | // There are two cases we care about: |
10278 | // * Top-level load: In this case, loadingNode is null, but loadingWindow |
10279 | // is our mScriptGlobal. We pass null for loadingPrincipal in this case. |
10280 | // * Subframe load: loadingWindow is null, but loadingNode is the frame |
10281 | // element for the load. loadingPrincipal is the NodePrincipal of the |
10282 | // frame element. |
10283 | nsCOMPtr<nsINode> loadingNode; |
10284 | nsCOMPtr<nsPIDOMWindowOuter> loadingWindow; |
10285 | nsCOMPtr<nsIPrincipal> loadingPrincipal; |
10286 | nsCOMPtr<nsISupports> topLevelLoadingContext; |
10287 | |
10288 | if (contentPolicyType == nsIContentPolicy::TYPE_DOCUMENT) { |
10289 | loadingNode = nullptr; |
10290 | loadingPrincipal = nullptr; |
10291 | loadingWindow = mScriptGlobal; |
10292 | if (XRE_IsContentProcess()) { |
10293 | // In e10s the child process doesn't have access to the element that |
10294 | // contains the browsing context (because that element is in the chrome |
10295 | // process). |
10296 | nsCOMPtr<nsIBrowserChild> browserChild = GetBrowserChild(); |
10297 | topLevelLoadingContext = ToSupports(browserChild); |
10298 | } else { |
10299 | // This is for loading non-e10s tabs and toplevel windows of various |
10300 | // sorts. |
10301 | // For the toplevel window cases, requestingElement will be null. |
10302 | nsCOMPtr<Element> requestingElement = |
10303 | loadingWindow->GetFrameElementInternal(); |
10304 | topLevelLoadingContext = requestingElement; |
10305 | } |
10306 | } else { |
10307 | loadingWindow = nullptr; |
10308 | loadingNode = mScriptGlobal->GetFrameElementInternal(); |
10309 | if (loadingNode) { |
10310 | // If we have a loading node, then use that as our loadingPrincipal. |
10311 | loadingPrincipal = loadingNode->NodePrincipal(); |
10312 | #ifdef DEBUG1 |
10313 | // Get the docshell type for requestingElement. |
10314 | RefPtr<Document> requestingDoc = loadingNode->OwnerDoc(); |
10315 | nsCOMPtr<nsIDocShell> elementDocShell = requestingDoc->GetDocShell(); |
10316 | // requestingElement docshell type = current docshell type. |
10317 | 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" , 10319); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mItemType == elementDocShell->ItemType()" ") (" "subframes should have the same docshell type as their parent" ")"); do { *((volatile int*)__null) = 10319; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false) |
10318 | 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" , 10319); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mItemType == elementDocShell->ItemType()" ") (" "subframes should have the same docshell type as their parent" ")"); do { *((volatile int*)__null) = 10319; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false) |
10319 | "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" , 10319); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mItemType == elementDocShell->ItemType()" ") (" "subframes should have the same docshell type as their parent" ")"); do { *((volatile int*)__null) = 10319; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
10320 | #endif |
10321 | } else { |
10322 | if (mIsBeingDestroyed) { |
10323 | // If this isn't a top-level load and mScriptGlobal's frame element is |
10324 | // null, then the element got removed from the DOM while we were trying |
10325 | // to load this resource. This docshell is scheduled for destruction |
10326 | // already, so bail out here. |
10327 | return NS_OK; |
10328 | } |
10329 | // If we are not being destroyed and we do not have access to the loading |
10330 | // node, then we are a remote subframe. Set the loading principal |
10331 | // to be a null principal and then set it correctly in the parent. |
10332 | loadingPrincipal = NullPrincipal::Create(GetOriginAttributes(), nullptr); |
10333 | } |
10334 | } |
10335 | |
10336 | if (!aLoadState->TriggeringPrincipal()) { |
10337 | 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" , 10337); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "DoURILoad needs a valid triggeringPrincipal" ")"); do { *(( volatile int*)__null) = 10337; __attribute__((nomerge)) ::abort (); } while (false); } } while (false); |
10338 | return NS_ERROR_FAILURE; |
10339 | } |
10340 | |
10341 | uint32_t sandboxFlags = mBrowsingContext->GetSandboxFlags(); |
10342 | nsSecurityFlags securityFlags = |
10343 | nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL; |
10344 | |
10345 | if (mLoadType == LOAD_ERROR_PAGE) { |
10346 | securityFlags |= nsILoadInfo::SEC_LOAD_ERROR_PAGE; |
10347 | } |
10348 | |
10349 | if (inheritPrincipal) { |
10350 | securityFlags |= nsILoadInfo::SEC_FORCE_INHERIT_PRINCIPAL; |
10351 | } |
10352 | |
10353 | // Must never have a parent for TYPE_DOCUMENT loads |
10354 | 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" , 10355); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mBrowsingContext->GetParent()" ")"); do { *((volatile int*)__null) = 10355; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); } } while (false) |
10355 | !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" , 10355); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mBrowsingContext->GetParent()" ")"); do { *((volatile int*)__null) = 10355; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); } } while (false); |
10356 | // Subdocuments must have a parent |
10357 | 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" , 10358); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mBrowsingContext->GetParent()" ")"); do { *((volatile int*)__null) = 10358; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); } } while (false) |
10358 | 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" , 10358); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mBrowsingContext->GetParent()" ")"); do { *((volatile int*)__null) = 10358; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); } } while (false); |
10359 | mBrowsingContext->SetTriggeringAndInheritPrincipals( |
10360 | aLoadState->TriggeringPrincipal(), aLoadState->PrincipalToInherit(), |
10361 | aLoadState->GetLoadIdentifier()); |
10362 | RefPtr<LoadInfo> loadInfo = |
10363 | (contentPolicyType == nsIContentPolicy::TYPE_DOCUMENT) |
10364 | ? new LoadInfo(loadingWindow, aLoadState->URI(), |
10365 | aLoadState->TriggeringPrincipal(), |
10366 | topLevelLoadingContext, securityFlags, sandboxFlags) |
10367 | : new LoadInfo(loadingPrincipal, aLoadState->TriggeringPrincipal(), |
10368 | loadingNode, securityFlags, contentPolicyType, |
10369 | Maybe<mozilla::dom::ClientInfo>(), |
10370 | Maybe<mozilla::dom::ServiceWorkerDescriptor>(), |
10371 | sandboxFlags); |
10372 | RefPtr<WindowContext> context = mBrowsingContext->GetCurrentWindowContext(); |
10373 | |
10374 | if (isAboutBlankLoadOntoInitialAboutBlank) { |
10375 | // Match the DocumentChannel case where the default for third-partiness |
10376 | // differs from the default in LoadInfo construction here. |
10377 | // toolkit/components/antitracking/test/browser/browser_aboutblank.js |
10378 | // fails without this. |
10379 | BrowsingContext* top = mBrowsingContext->Top(); |
10380 | if (top == mBrowsingContext) { |
10381 | // If we're at the top, this must be a window.open()ed |
10382 | // window, and we can't be third-party relative to ourselves. |
10383 | loadInfo->SetIsThirdPartyContextToTopWindow(false); |
10384 | } else { |
10385 | if (Document* topDoc = top->GetDocument()) { |
10386 | bool thirdParty = false; |
10387 | mozilla::Unused << topDoc->GetPrincipal()->IsThirdPartyPrincipal( |
10388 | aLoadState->PrincipalToInherit(), &thirdParty); |
10389 | loadInfo->SetIsThirdPartyContextToTopWindow(thirdParty); |
10390 | } else { |
10391 | // If top is in a different process, we have to be third-party relative |
10392 | // to it. |
10393 | loadInfo->SetIsThirdPartyContextToTopWindow(true); |
10394 | } |
10395 | } |
10396 | } |
10397 | |
10398 | if (mLoadType != LOAD_ERROR_PAGE && context && context->IsInProcess()) { |
10399 | if (context->HasValidTransientUserGestureActivation()) { |
10400 | aLoadState->SetHasValidUserGestureActivation(true); |
10401 | aLoadState->SetTextDirectiveUserActivation(true); |
10402 | } |
10403 | if (!aLoadState->TriggeringWindowId()) { |
10404 | aLoadState->SetTriggeringWindowId(context->Id()); |
10405 | } |
10406 | if (!aLoadState->TriggeringStorageAccess()) { |
10407 | Document* contextDoc = context->GetExtantDoc(); |
10408 | if (contextDoc) { |
10409 | aLoadState->SetTriggeringStorageAccess( |
10410 | contextDoc->UsingStorageAccess()); |
10411 | } |
10412 | } |
10413 | } |
10414 | |
10415 | // in case this docshell load was triggered by a valid transient user gesture, |
10416 | // or also the load originates from external, then we pass that information on |
10417 | // to the loadinfo, which allows e.g. setting Sec-Fetch-User request headers. |
10418 | if (aLoadState->HasValidUserGestureActivation() || |
10419 | aLoadState->HasLoadFlags(LOAD_FLAGS_FROM_EXTERNAL)) { |
10420 | loadInfo->SetHasValidUserGestureActivation(true); |
10421 | aLoadState->SetTextDirectiveUserActivation(true); |
10422 | } |
10423 | |
10424 | loadInfo->SetTextDirectiveUserActivation( |
10425 | aLoadState->GetTextDirectiveUserActivation()); |
10426 | |
10427 | loadInfo->SetTriggeringWindowId(aLoadState->TriggeringWindowId()); |
10428 | loadInfo->SetTriggeringStorageAccess(aLoadState->TriggeringStorageAccess()); |
10429 | loadInfo->SetTriggeringSandboxFlags(aLoadState->TriggeringSandboxFlags()); |
10430 | loadInfo->SetIsMetaRefresh(aLoadState->IsMetaRefresh()); |
10431 | |
10432 | uint32_t cacheKey = 0; |
10433 | if (aCacheKey) { |
10434 | cacheKey = *aCacheKey; |
10435 | } else if (mozilla::SessionHistoryInParent()) { |
10436 | if (mLoadingEntry) { |
10437 | cacheKey = mLoadingEntry->mInfo.GetCacheKey(); |
10438 | } else if (mActiveEntry) { // for reload cases |
10439 | cacheKey = mActiveEntry->GetCacheKey(); |
10440 | } |
10441 | } else { |
10442 | if (mLSHE) { |
10443 | cacheKey = mLSHE->GetCacheKey(); |
10444 | } else if (mOSHE) { // for reload cases |
10445 | cacheKey = mOSHE->GetCacheKey(); |
10446 | } |
10447 | } |
10448 | |
10449 | bool uriModified; |
10450 | if (mLSHE || mLoadingEntry) { |
10451 | if (mLoadingEntry) { |
10452 | uriModified = mLoadingEntry->mInfo.GetURIWasModified(); |
10453 | } else { |
10454 | uriModified = mLSHE->GetURIWasModified(); |
10455 | } |
10456 | } else { |
10457 | uriModified = false; |
10458 | } |
10459 | |
10460 | bool isEmbeddingBlockedError = false; |
10461 | if (mFailedChannel) { |
10462 | nsresult status; |
10463 | mFailedChannel->GetStatus(&status); |
10464 | isEmbeddingBlockedError = status == NS_ERROR_XFO_VIOLATION || |
10465 | status == NS_ERROR_CSP_FRAME_ANCESTOR_VIOLATION; |
10466 | } |
10467 | |
10468 | nsLoadFlags loadFlags = aLoadState->CalculateChannelLoadFlags( |
10469 | mBrowsingContext, Some(uriModified), Some(isEmbeddingBlockedError)); |
10470 | |
10471 | nsCOMPtr<nsIChannel> channel; |
10472 | if (DocumentChannel::CanUseDocumentChannel(aLoadState->URI()) && |
10473 | !isAboutBlankLoadOntoInitialAboutBlank) { |
10474 | channel = DocumentChannel::CreateForDocument( |
10475 | aLoadState, loadInfo, loadFlags, this, cacheKey, uriModified, |
10476 | isEmbeddingBlockedError); |
10477 | 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" , 10477); AnnotateMozCrashReason("MOZ_ASSERT" "(" "channel" ")" ); do { *((volatile int*)__null) = 10477; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
10478 | |
10479 | // Disable keyword fixup when using DocumentChannel, since |
10480 | // DocumentLoadListener will handle this for us (in the parent process). |
10481 | mAllowKeywordFixup = false; |
10482 | } else if (!CreateAndConfigureRealChannelForLoadState( |
10483 | mBrowsingContext, aLoadState, loadInfo, this, this, |
10484 | GetOriginAttributes(), loadFlags, cacheKey, rv, |
10485 | getter_AddRefs(channel))) { |
10486 | return rv; |
10487 | } |
10488 | |
10489 | // Make sure to give the caller a channel if we managed to create one |
10490 | // This is important for correct error page/session history interaction |
10491 | if (aRequest) { |
10492 | NS_ADDREF(*aRequest = channel)(*aRequest = channel)->AddRef(); |
10493 | } |
10494 | |
10495 | const nsACString& typeHint = aLoadState->TypeHint(); |
10496 | if (!typeHint.IsVoid()) { |
10497 | mContentTypeHint = typeHint; |
10498 | } else { |
10499 | mContentTypeHint.Truncate(); |
10500 | } |
10501 | |
10502 | // Load attributes depend on load type... |
10503 | if (mLoadType == LOAD_RELOAD_CHARSET_CHANGE) { |
10504 | // Use SetAllowStaleCacheContent (not LOAD_FROM_CACHE flag) since we |
10505 | // only want to force cache load for this channel, not the whole |
10506 | // loadGroup. |
10507 | nsCOMPtr<nsICacheInfoChannel> cachingChannel = do_QueryInterface(channel); |
10508 | if (cachingChannel) { |
10509 | cachingChannel->SetAllowStaleCacheContent(true); |
10510 | } |
10511 | } |
10512 | |
10513 | uint32_t openFlags = |
10514 | nsDocShell::ComputeURILoaderFlags(mBrowsingContext, mLoadType); |
10515 | return OpenInitializedChannel(channel, uriLoader, openFlags); |
10516 | } |
10517 | |
10518 | static nsresult AppendSegmentToString(nsIInputStream* aIn, void* aClosure, |
10519 | const char* aFromRawSegment, |
10520 | uint32_t aToOffset, uint32_t aCount, |
10521 | uint32_t* aWriteCount) { |
10522 | // aFromSegment now contains aCount bytes of data. |
10523 | |
10524 | nsAutoCString* buf = static_cast<nsAutoCString*>(aClosure); |
10525 | buf->Append(aFromRawSegment, aCount); |
10526 | |
10527 | // Indicate that we have consumed all of aFromSegment |
10528 | *aWriteCount = aCount; |
10529 | return NS_OK; |
10530 | } |
10531 | |
10532 | /* static */ nsresult nsDocShell::AddHeadersToChannel( |
10533 | nsIInputStream* aHeadersData, nsIChannel* aGenericChannel) { |
10534 | nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aGenericChannel); |
10535 | 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" , 10535); return NS_ERROR_UNEXPECTED; } } while (false); |
10536 | |
10537 | uint32_t numRead; |
10538 | nsAutoCString headersString; |
10539 | nsresult rv = aHeadersData->ReadSegments( |
10540 | AppendSegmentToString, &headersString, UINT32_MAX(4294967295U), &numRead); |
10541 | 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" , 10541); return rv; } } while (false); |
10542 | |
10543 | // used during the manipulation of the String from the InputStream |
10544 | nsAutoCString headerName; |
10545 | nsAutoCString headerValue; |
10546 | int32_t crlf; |
10547 | int32_t colon; |
10548 | |
10549 | // |
10550 | // Iterate over the headersString: for each "\r\n" delimited chunk, |
10551 | // add the value as a header to the nsIHttpChannel |
10552 | // |
10553 | |
10554 | static const char kWhitespace[] = "\b\t\r\n "; |
10555 | while (true) { |
10556 | crlf = headersString.Find("\r\n"); |
10557 | if (crlf == kNotFound) { |
10558 | return NS_OK; |
10559 | } |
10560 | |
10561 | const nsACString& oneHeader = StringHead(headersString, crlf); |
10562 | |
10563 | colon = oneHeader.FindChar(':'); |
10564 | if (colon == kNotFound) { |
10565 | return NS_ERROR_UNEXPECTED; |
10566 | } |
10567 | |
10568 | headerName = StringHead(oneHeader, colon); |
10569 | headerValue = Substring(oneHeader, colon + 1); |
10570 | |
10571 | headerName.Trim(kWhitespace); |
10572 | headerValue.Trim(kWhitespace); |
10573 | |
10574 | headersString.Cut(0, crlf + 2); |
10575 | |
10576 | // |
10577 | // FINALLY: we can set the header! |
10578 | // |
10579 | |
10580 | rv = httpChannel->SetRequestHeader(headerName, headerValue, true); |
10581 | 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" , 10581); return rv; } } while (false); |
10582 | } |
10583 | |
10584 | 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" , 10584); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: " "oops" ")"); do { *((volatile int *)__null) = 10584; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
10585 | return NS_ERROR_UNEXPECTED; |
10586 | } |
10587 | |
10588 | /* static */ uint32_t nsDocShell::ComputeURILoaderFlags( |
10589 | BrowsingContext* aBrowsingContext, uint32_t aLoadType, |
10590 | bool aIsDocumentLoad) { |
10591 | 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" , 10591); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aBrowsingContext" ")"); do { *((volatile int*)__null) = 10591; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
10592 | |
10593 | uint32_t openFlags = 0; |
10594 | if (aLoadType == LOAD_LINK) { |
10595 | openFlags |= nsIURILoader::IS_CONTENT_PREFERRED; |
10596 | } |
10597 | if (!aBrowsingContext->GetAllowContentRetargeting()) { |
10598 | openFlags |= nsIURILoader::DONT_RETARGET; |
10599 | } |
10600 | |
10601 | // Unless the pref is set, object/embed loads always specify DONT_RETARGET. |
10602 | // See bug 1868001 for details. |
10603 | if (!aIsDocumentLoad && |
10604 | !StaticPrefs::dom_navigation_object_embed_allow_retargeting()) { |
10605 | openFlags |= nsIURILoader::DONT_RETARGET; |
10606 | } |
10607 | |
10608 | return openFlags; |
10609 | } |
10610 | |
10611 | nsresult nsDocShell::OpenInitializedChannel(nsIChannel* aChannel, |
10612 | nsIURILoader* aURILoader, |
10613 | uint32_t aOpenFlags) { |
10614 | nsresult rv = NS_OK; |
10615 | |
10616 | // If anything fails here, make sure to clear our initial ClientSource. |
10617 | auto cleanupInitialClient = |
10618 | MakeScopeExit([&] { mInitialClientSource.reset(); }); |
10619 | |
10620 | nsCOMPtr<nsPIDOMWindowOuter> win = GetWindow(); |
10621 | 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" , 10621); return NS_ERROR_FAILURE; } } while (false); |
10622 | |
10623 | MaybeCreateInitialClientSource(); |
10624 | |
10625 | // Let the client channel helper know if we are using DocumentChannel, |
10626 | // since redirects get handled in the parent process in that case. |
10627 | RefPtr<net::DocumentChannel> docChannel = do_QueryObject(aChannel); |
10628 | if (docChannel && XRE_IsContentProcess()) { |
10629 | // Tell the content process nsDocumentOpenInfo to not try to do |
10630 | // any sort of targeting. |
10631 | aOpenFlags |= nsIURILoader::DONT_RETARGET; |
10632 | } |
10633 | |
10634 | // Since we are loading a document we need to make sure the proper reserved |
10635 | // and initial client data is stored on the nsILoadInfo. The |
10636 | // ClientChannelHelper does this and ensures that it is propagated properly |
10637 | // on redirects. We pass no reserved client here so that the helper will |
10638 | // create the reserved ClientSource if necessary. |
10639 | Maybe<ClientInfo> noReservedClient; |
10640 | if (docChannel) { |
10641 | // When using DocumentChannel, all redirect handling is done in the parent, |
10642 | // so we just need the child variant to watch for the internal redirect |
10643 | // to the final channel. |
10644 | rv = AddClientChannelHelperInChild(aChannel, |
10645 | GetMainThreadSerialEventTarget()); |
10646 | docChannel->SetInitialClientInfo(GetInitialClientInfo()); |
10647 | } else { |
10648 | rv = AddClientChannelHelper(aChannel, std::move(noReservedClient), |
10649 | GetInitialClientInfo(), |
10650 | GetMainThreadSerialEventTarget()); |
10651 | } |
10652 | 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" , 10652); return rv; } } while (false); |
10653 | |
10654 | rv = aURILoader->OpenURI(aChannel, aOpenFlags, this); |
10655 | 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" , 10655); return rv; } } while (false); |
10656 | |
10657 | // We're about to load a new page and it may take time before necko |
10658 | // gives back any data, so main thread might have a chance to process a |
10659 | // collector slice |
10660 | nsJSContext::MaybeRunNextCollectorSlice(this, JS::GCReason::DOCSHELL); |
10661 | |
10662 | // Success. Keep the initial ClientSource if it exists. |
10663 | cleanupInitialClient.release(); |
10664 | |
10665 | return NS_OK; |
10666 | } |
10667 | |
10668 | nsresult nsDocShell::OpenRedirectedChannel(nsDocShellLoadState* aLoadState) { |
10669 | nsCOMPtr<nsIChannel> channel = aLoadState->GetPendingRedirectedChannel(); |
10670 | 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" , 10670); AnnotateMozCrashReason("MOZ_ASSERT" "(" "channel" ")" ); do { *((volatile int*)__null) = 10670; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
10671 | |
10672 | // If anything fails here, make sure to clear our initial ClientSource. |
10673 | auto cleanupInitialClient = |
10674 | MakeScopeExit([&] { mInitialClientSource.reset(); }); |
10675 | |
10676 | nsCOMPtr<nsPIDOMWindowOuter> win = GetWindow(); |
10677 | 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" , 10677); return NS_ERROR_FAILURE; } } while (false); |
10678 | |
10679 | MaybeCreateInitialClientSource(); |
10680 | |
10681 | nsCOMPtr<nsILoadInfo> loadInfo = channel->LoadInfo(); |
10682 | |
10683 | LoadInfo* li = static_cast<LoadInfo*>(loadInfo.get()); |
10684 | if (loadInfo->GetExternalContentPolicyType() == |
10685 | ExtContentPolicy::TYPE_DOCUMENT) { |
10686 | li->UpdateBrowsingContextID(mBrowsingContext->Id()); |
10687 | } else if (loadInfo->GetExternalContentPolicyType() == |
10688 | ExtContentPolicy::TYPE_SUBDOCUMENT) { |
10689 | li->UpdateFrameBrowsingContextID(mBrowsingContext->Id()); |
10690 | } |
10691 | |
10692 | // If we did a process switch, then we should have an existing allocated |
10693 | // ClientInfo, so we just need to allocate a corresponding ClientSource. |
10694 | CreateReservedSourceIfNeeded(channel, GetMainThreadSerialEventTarget()); |
10695 | |
10696 | RefPtr<nsDocumentOpenInfo> loader = |
10697 | new nsDocumentOpenInfo(this, nsIURILoader::DONT_RETARGET, nullptr); |
10698 | channel->SetLoadGroup(mLoadGroup); |
10699 | |
10700 | 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" , 10700); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false" ") (" "NS_SUCCEEDED(loader->Prepare())" ")"); do { *((volatile int*)__null) = 10700; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); } } while (false); |
10701 | |
10702 | nsresult rv = NS_OK; |
10703 | if (XRE_IsParentProcess()) { |
10704 | // If we're in the parent, the we don't have an nsIChildChannel, just |
10705 | // the original channel, which is already open in this process. |
10706 | |
10707 | // DocumentLoadListener expects to get an nsIParentChannel, so |
10708 | // we create a wrapper around the channel and nsIStreamListener |
10709 | // that forwards functionality as needed, and then we register |
10710 | // it under the provided identifier. |
10711 | RefPtr<ParentChannelWrapper> wrapper = |
10712 | new ParentChannelWrapper(channel, loader); |
10713 | wrapper->Register(aLoadState->GetPendingRedirectChannelRegistrarId()); |
10714 | |
10715 | mLoadGroup->AddRequest(channel, nullptr); |
10716 | } else if (nsCOMPtr<nsIChildChannel> childChannel = |
10717 | do_QueryInterface(channel)) { |
10718 | // Our channel was redirected from another process, so doesn't need to |
10719 | // be opened again. However, it does need its listener hooked up |
10720 | // correctly. |
10721 | rv = childChannel->CompleteRedirectSetup(loader); |
10722 | } else { |
10723 | // It's possible for the redirected channel to not implement |
10724 | // nsIChildChannel and be entirely local (like srcdoc). In that case we |
10725 | // can just open the local instance and it will work. |
10726 | rv = channel->AsyncOpen(loader); |
10727 | } |
10728 | if (rv == NS_ERROR_NO_CONTENT) { |
10729 | return NS_OK; |
10730 | } |
10731 | 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" , 10731); return rv; } } while (false); |
10732 | |
10733 | // Success. Keep the initial ClientSource if it exists. |
10734 | cleanupInitialClient.release(); |
10735 | return NS_OK; |
10736 | } |
10737 | |
10738 | // https://html.spec.whatwg.org/#scrolling-to-a-fragment |
10739 | nsresult nsDocShell::ScrollToAnchor(bool aCurHasRef, bool aNewHasRef, |
10740 | nsACString& aNewHash, uint32_t aLoadType) { |
10741 | if (!mCurrentURI) { |
10742 | return NS_OK; |
10743 | } |
10744 | |
10745 | RefPtr<PresShell> presShell = GetPresShell(); |
10746 | if (!presShell) { |
10747 | // If we failed to get the shell, or if there is no shell, |
10748 | // nothing left to do here. |
10749 | return NS_OK; |
10750 | } |
10751 | |
10752 | ScrollContainerFrame* rootScroll = presShell->GetRootScrollContainerFrame(); |
10753 | if (rootScroll) { |
10754 | rootScroll->ClearDidHistoryRestore(); |
10755 | } |
10756 | |
10757 | // If it's a load from history, we don't have any anchor jumping to do. |
10758 | // Scrollbar position will be restored by the caller based on positions stored |
10759 | // in session history. |
10760 | bool scroll = aLoadType != LOAD_HISTORY && aLoadType != LOAD_RELOAD_NORMAL; |
10761 | // If the load contains text directives, try to apply them. This may fail if |
10762 | // the load is a same-document load that was initiated before the document was |
10763 | // fully loaded and the target is not yet included in the DOM tree. |
10764 | // For this case, the `uninvokedTextDirectives` are not cleared, so that |
10765 | // `Document::ScrollToRef()` can re-apply the text directive. |
10766 | // `Document::ScrollToRef()` is (presumably) the second "async" call mentioned |
10767 | // in sec. 7.4.2.3.3 in the HTML spec, "Fragment navigations": |
10768 | // https://html.spec.whatwg.org/#scroll-to-fragid:~:text=This%20algorithm%20will%20be%20called%20twice |
10769 | |
10770 | const RefPtr fragmentDirective = GetDocument()->FragmentDirective(); |
10771 | const nsTArray<RefPtr<nsRange>> textDirectiveRanges = |
10772 | fragmentDirective->FindTextFragmentsInDocument(); |
10773 | fragmentDirective->HighlightTextDirectives(textDirectiveRanges); |
10774 | const bool scrollToTextDirective = |
10775 | !textDirectiveRanges.IsEmpty() && |
10776 | fragmentDirective->IsTextDirectiveAllowedToBeScrolledTo(); |
10777 | const RefPtr<nsRange> textDirectiveToScroll = |
10778 | scrollToTextDirective ? textDirectiveRanges[0] : nullptr; |
10779 | |
10780 | // If we have no new anchor, we do not want to scroll, unless there is a |
10781 | // current anchor and we are doing a history load. So return if we have no |
10782 | // new anchor, and there is no current anchor or the load is not a history |
10783 | // load. |
10784 | if ((!aCurHasRef || aLoadType != LOAD_HISTORY) && !aNewHasRef && |
10785 | !scrollToTextDirective) { |
10786 | return NS_OK; |
10787 | } |
10788 | |
10789 | // Both the new and current URIs refer to the same page. We can now |
10790 | // browse to the hash stored in the new URI. |
10791 | |
10792 | if (aNewHash.IsEmpty() && !scrollToTextDirective) { |
10793 | // 2. If fragment is the empty string, then return the special value top of |
10794 | // the document. |
10795 | // |
10796 | // Tell the shell it's at an anchor without scrolling. |
10797 | presShell->GoToAnchor(u""_ns, nullptr, false); |
10798 | |
10799 | if (scroll) { |
10800 | // Scroll to the top of the page. Ignore the return value; failure to |
10801 | // scroll here (e.g. if there is no root scrollframe) is not grounds for |
10802 | // canceling the load! |
10803 | SetCurScrollPosEx(0, 0); |
10804 | } |
10805 | |
10806 | return NS_OK; |
10807 | } |
10808 | |
10809 | // 3. Let potentialIndicatedElement be the result of finding a potential |
10810 | // indicated element given document and fragment. |
10811 | NS_ConvertUTF8toUTF16 uStr(aNewHash); |
10812 | |
10813 | 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" , 10813); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!uStr.IsEmpty() || scrollToTextDirective" ")"); do { *((volatile int*)__null) = 10813; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
10814 | |
10815 | auto rv = presShell->GoToAnchor(uStr, textDirectiveToScroll, scroll, |
10816 | ScrollFlags::ScrollSmoothAuto); |
10817 | |
10818 | // 4. If potentialIndicatedElement is not null, then return |
10819 | // potentialIndicatedElement. |
10820 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) { |
10821 | return NS_OK; |
10822 | } |
10823 | |
10824 | // 5. Let fragmentBytes be the result of percent-decoding fragment. |
10825 | nsAutoCString fragmentBytes; |
10826 | const bool unescaped = NS_UnescapeURL(aNewHash.Data(), aNewHash.Length(), |
10827 | /* aFlags = */ 0, fragmentBytes); |
10828 | |
10829 | if (!unescaped) { |
10830 | // Another attempt is only necessary if characters were unescaped. |
10831 | return NS_OK; |
10832 | } |
10833 | |
10834 | if (fragmentBytes.IsEmpty()) { |
10835 | // When aNewHash contains "%00", the unescaped string may be empty, and |
10836 | // GoToAnchor asserts if we ask it to scroll to an empty ref. |
10837 | presShell->GoToAnchor(u""_ns, nullptr, false); |
10838 | return NS_OK; |
10839 | } |
10840 | |
10841 | // 6. Let decodedFragment be the result of running UTF-8 decode without BOM on |
10842 | // fragmentBytes. |
10843 | nsAutoString decodedFragment; |
10844 | rv = UTF_8_ENCODING->DecodeWithoutBOMHandling(fragmentBytes, decodedFragment); |
10845 | 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" , 10845); return rv; } } while (false); |
10846 | |
10847 | // 7. Set potentialIndicatedElement to the result of finding a potential |
10848 | // indicated element given document and decodedFragment. |
10849 | // |
10850 | // Ignore the return value of GoToAnchor, since it will return an error if |
10851 | // there is no such anchor in the document, which is actually a success |
10852 | // condition for us (we want to update the session history with the new URI no |
10853 | // matter whether we actually scrolled somewhere). |
10854 | presShell->GoToAnchor(decodedFragment, nullptr, scroll, |
10855 | ScrollFlags::ScrollSmoothAuto); |
10856 | |
10857 | return NS_OK; |
10858 | } |
10859 | |
10860 | bool nsDocShell::OnNewURI(nsIURI* aURI, nsIChannel* aChannel, |
10861 | nsIPrincipal* aTriggeringPrincipal, |
10862 | nsIPrincipal* aPrincipalToInherit, |
10863 | nsIPrincipal* aPartitionedPrincipalToInherit, |
10864 | nsIContentSecurityPolicy* aCsp, |
10865 | bool aAddToGlobalHistory, bool aCloneSHChildren) { |
10866 | 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" , 10866); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aURI" ") (" "uri is null" ")"); do { *((volatile int*)__null) = 10866; __attribute__ ((nomerge)) ::abort(); } while (false); } } while (false); |
10867 | 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" , 10867); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aChannel || !aTriggeringPrincipal" ") (" "Shouldn't have both set" ")"); do { *((volatile int*) __null) = 10867; __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); |
10868 | |
10869 | 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" , 10870); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aPrincipalToInherit || (aPrincipalToInherit && aTriggeringPrincipal)" ")"); do { *((volatile int*)__null) = 10870; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false) |
10870 | (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" , 10870); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aPrincipalToInherit || (aPrincipalToInherit && aTriggeringPrincipal)" ")"); do { *((volatile int*)__null) = 10870; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
10871 | |
10872 | #if defined(DEBUG1) |
10873 | if (MOZ_LOG_TEST(gDocShellLog, LogLevel::Debug)(__builtin_expect(!!(mozilla::detail::log_test(gDocShellLog, LogLevel ::Debug)), 0))) { |
10874 | nsAutoCString chanName; |
10875 | if (aChannel) { |
10876 | aChannel->GetName(chanName); |
10877 | } else { |
10878 | chanName.AssignLiteral("<no channel>"); |
10879 | } |
10880 | |
10881 | 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) |
10882 | ("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) |
10883 | 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); |
10884 | } |
10885 | #endif |
10886 | |
10887 | bool equalUri = false; |
10888 | |
10889 | // Get the post data and the HTTP response code from the channel. |
10890 | uint32_t responseStatus = 0; |
10891 | nsCOMPtr<nsIInputStream> inputStream; |
10892 | if (aChannel) { |
10893 | nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(aChannel)); |
10894 | |
10895 | // Check if the HTTPChannel is hiding under a multiPartChannel |
10896 | if (!httpChannel) { |
10897 | GetHttpChannel(aChannel, getter_AddRefs(httpChannel)); |
10898 | } |
10899 | |
10900 | if (httpChannel) { |
10901 | nsCOMPtr<nsIUploadChannel> uploadChannel(do_QueryInterface(httpChannel)); |
10902 | if (uploadChannel) { |
10903 | uploadChannel->GetUploadStream(getter_AddRefs(inputStream)); |
10904 | } |
10905 | |
10906 | // If the response status indicates an error, unlink this session |
10907 | // history entry from any entries sharing its document. |
10908 | nsresult rv = httpChannel->GetResponseStatus(&responseStatus); |
10909 | if (mLSHE && NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && responseStatus >= 400) { |
10910 | mLSHE->AbandonBFCacheEntry(); |
10911 | // FIXME Do the same for mLoadingEntry |
10912 | } |
10913 | } |
10914 | } |
10915 | |
10916 | // Determine if this type of load should update history. |
10917 | bool updateGHistory = ShouldUpdateGlobalHistory(mLoadType); |
10918 | |
10919 | // We don't update session history on reload unless we're loading |
10920 | // an iframe in shift-reload case. |
10921 | bool updateSHistory = mBrowsingContext->ShouldUpdateSessionHistory(mLoadType); |
10922 | |
10923 | // Create SH Entry (mLSHE) only if there is a SessionHistory object in the |
10924 | // root browsing context. |
10925 | // FIXME If session history in the parent is enabled then we only do this if |
10926 | // the session history object is in process, otherwise we can't really |
10927 | // use the mLSHE anyway. Once session history is only stored in the |
10928 | // parent then this code will probably be removed anyway. |
10929 | RefPtr<ChildSHistory> rootSH = GetRootSessionHistory(); |
10930 | if (!rootSH) { |
10931 | updateSHistory = false; |
10932 | updateGHistory = false; // XXX Why global history too? |
10933 | } |
10934 | |
10935 | // Check if the url to be loaded is the same as the one already loaded. |
10936 | if (mCurrentURI) { |
10937 | aURI->Equals(mCurrentURI, &equalUri); |
10938 | } |
10939 | |
10940 | #ifdef DEBUG1 |
10941 | bool shAvailable = (rootSH != nullptr); |
10942 | |
10943 | // XXX This log message is almost useless because |updateSHistory| |
10944 | // and |updateGHistory| are not correct at this point. |
10945 | |
10946 | 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) |
10947 | (" 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) |
10948 | " 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) |
10949 | 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); |
10950 | #endif |
10951 | |
10952 | /* If the url to be loaded is the same as the one already there, |
10953 | * and the original loadType is LOAD_NORMAL, LOAD_LINK, or |
10954 | * LOAD_STOP_CONTENT, set loadType to LOAD_NORMAL_REPLACE so that |
10955 | * AddToSessionHistory() won't mess with the current SHEntry and |
10956 | * if this page has any frame children, it also will be handled |
10957 | * properly. see bug 83684 |
10958 | * |
10959 | * NB: If mOSHE is null but we have a current URI, then it probably |
10960 | * means that we must be at the transient about:blank content viewer; |
10961 | * we should let the normal load continue, since there's nothing to |
10962 | * replace. Sometimes this happens after a session restore (eg process |
10963 | * switch) and mCurrentURI is not about:blank; we assume we can let the load |
10964 | * continue (Bug 1301399). |
10965 | * |
10966 | * XXX Hopefully changing the loadType at this time will not hurt |
10967 | * anywhere. The other way to take care of sequentially repeating |
10968 | * frameset pages is to add new methods to nsIDocShellTreeItem. |
10969 | * Hopefully I don't have to do that. |
10970 | */ |
10971 | if (equalUri && |
10972 | (mozilla::SessionHistoryInParent() ? !!mActiveEntry : !!mOSHE) && |
10973 | (mLoadType == LOAD_NORMAL || mLoadType == LOAD_LINK || |
10974 | mLoadType == LOAD_STOP_CONTENT) && |
10975 | !inputStream) { |
10976 | mLoadType = LOAD_NORMAL_REPLACE; |
10977 | } |
10978 | |
10979 | // If this is a refresh to the currently loaded url, we don't |
10980 | // have to update session or global history. |
10981 | if (mLoadType == LOAD_REFRESH && !inputStream && equalUri) { |
10982 | SetHistoryEntryAndUpdateBC(Some<nsISHEntry*>(mOSHE), Nothing()); |
10983 | } |
10984 | |
10985 | /* If the user pressed shift-reload, cache will create a new cache key |
10986 | * for the page. Save the new cacheKey in Session History. |
10987 | * see bug 90098 |
10988 | */ |
10989 | if (aChannel && IsForceReloadType(mLoadType)) { |
10990 | 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" , 10992); 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) = 10992; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false) |
10991 | "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" , 10992); 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) = 10992; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false) |
10992 | " 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" , 10992); 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) = 10992; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
10993 | |
10994 | nsCOMPtr<nsICacheInfoChannel> cacheChannel(do_QueryInterface(aChannel)); |
10995 | uint32_t cacheKey = 0; |
10996 | // Get the Cache Key and store it in SH. |
10997 | if (cacheChannel) { |
10998 | cacheChannel->GetCacheKey(&cacheKey); |
10999 | } |
11000 | // If we already have a loading history entry, store the new cache key |
11001 | // in it. Otherwise, since we're doing a reload and won't be updating |
11002 | // our history entry, store the cache key in our current history entry. |
11003 | SetCacheKeyOnHistoryEntry(mLSHE ? mLSHE : mOSHE, cacheKey); |
11004 | |
11005 | if (!mozilla::SessionHistoryInParent()) { |
11006 | // Since we're force-reloading, clear all the sub frame history. |
11007 | ClearFrameHistory(mLSHE); |
11008 | ClearFrameHistory(mOSHE); |
11009 | } |
11010 | } |
11011 | |
11012 | if (!mozilla::SessionHistoryInParent()) { |
11013 | // Clear subframe history on refresh. |
11014 | // XXX: history.go(0) won't go this path as mLoadType is LOAD_HISTORY in |
11015 | // this case. One should re-validate after bug 1331865 fixed. |
11016 | if (mLoadType == LOAD_REFRESH) { |
11017 | ClearFrameHistory(mLSHE); |
11018 | ClearFrameHistory(mOSHE); |
11019 | } |
11020 | |
11021 | if (updateSHistory) { |
11022 | // Update session history if necessary... |
11023 | if (!mLSHE && (mItemType == typeContent) && mURIResultedInDocument) { |
11024 | /* This is a fresh page getting loaded for the first time |
11025 | *.Create a Entry for it and add it to SH, if this is the |
11026 | * rootDocShell |
11027 | */ |
11028 | (void)AddToSessionHistory(aURI, aChannel, aTriggeringPrincipal, |
11029 | aPrincipalToInherit, |
11030 | aPartitionedPrincipalToInherit, aCsp, |
11031 | aCloneSHChildren, getter_AddRefs(mLSHE)); |
11032 | } |
11033 | } else if (GetSessionHistory() && mLSHE && mURIResultedInDocument) { |
11034 | // Even if we don't add anything to SHistory, ensure the current index |
11035 | // points to the same SHEntry as our mLSHE. |
11036 | |
11037 | GetSessionHistory()->LegacySHistory()->EnsureCorrectEntryAtCurrIndex( |
11038 | mLSHE); |
11039 | } |
11040 | } |
11041 | |
11042 | // If this is a POST request, we do not want to include this in global |
11043 | // history. |
11044 | if (ShouldAddURIVisit(aChannel) && updateGHistory && aAddToGlobalHistory && |
11045 | !net::ChannelIsPost(aChannel)) { |
11046 | nsCOMPtr<nsIURI> previousURI; |
11047 | uint32_t previousFlags = 0; |
11048 | |
11049 | if (mLoadType & LOAD_CMD_RELOAD) { |
11050 | // On a reload request, we don't set redirecting flags. |
11051 | previousURI = aURI; |
11052 | } else { |
11053 | ExtractLastVisit(aChannel, getter_AddRefs(previousURI), &previousFlags); |
11054 | } |
11055 | |
11056 | AddURIVisit(aURI, previousURI, previousFlags, responseStatus); |
11057 | } |
11058 | |
11059 | // If this was a history load or a refresh, or it was a history load but |
11060 | // later changed to LOAD_NORMAL_REPLACE due to redirection, update the index |
11061 | // in session history. |
11062 | if (!mozilla::SessionHistoryInParent() && rootSH && |
11063 | ((mLoadType & (LOAD_CMD_HISTORY | LOAD_CMD_RELOAD)) || |
11064 | mLoadType == LOAD_NORMAL_REPLACE || mLoadType == LOAD_REFRESH_REPLACE)) { |
11065 | mPreviousEntryIndex = rootSH->Index(); |
11066 | if (!mozilla::SessionHistoryInParent()) { |
11067 | rootSH->LegacySHistory()->UpdateIndex(); |
11068 | } |
11069 | mLoadedEntryIndex = rootSH->Index(); |
11070 | 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) |
11071 | ("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) |
11072 | 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); |
11073 | } |
11074 | |
11075 | // aCloneSHChildren exactly means "we are not loading a new document". |
11076 | uint32_t locationFlags = |
11077 | aCloneSHChildren ? uint32_t(LOCATION_CHANGE_SAME_DOCUMENT) : 0; |
11078 | |
11079 | bool onLocationChangeNeeded = |
11080 | SetCurrentURI(aURI, aChannel, false, |
11081 | /* aIsInitialAboutBlank */ false, locationFlags); |
11082 | // Make sure to store the referrer from the channel, if any |
11083 | nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(aChannel)); |
11084 | if (httpChannel) { |
11085 | mReferrerInfo = httpChannel->GetReferrerInfo(); |
11086 | } |
11087 | return onLocationChangeNeeded; |
11088 | } |
11089 | |
11090 | Maybe<Wireframe> nsDocShell::GetWireframe() { |
11091 | const bool collectWireFrame = |
11092 | mozilla::SessionHistoryInParent() && |
11093 | StaticPrefs::browser_history_collectWireframes() && |
11094 | mBrowsingContext->IsTopContent() && mActiveEntry; |
11095 | |
11096 | if (!collectWireFrame) { |
11097 | return Nothing(); |
11098 | } |
11099 | |
11100 | RefPtr<Document> doc = mDocumentViewer->GetDocument(); |
11101 | Nullable<Wireframe> wireframe; |
11102 | doc->GetWireframeWithoutFlushing(false, wireframe); |
11103 | if (wireframe.IsNull()) { |
11104 | return Nothing(); |
11105 | } |
11106 | return Some(wireframe.Value()); |
11107 | } |
11108 | |
11109 | bool nsDocShell::CollectWireframe() { |
11110 | Maybe<Wireframe> wireframe = GetWireframe(); |
11111 | if (wireframe.isNothing()) { |
11112 | return false; |
11113 | } |
11114 | |
11115 | if (XRE_IsParentProcess()) { |
11116 | SessionHistoryEntry* entry = |
11117 | mBrowsingContext->Canonical()->GetActiveSessionHistoryEntry(); |
11118 | if (entry) { |
11119 | entry->SetWireframe(wireframe); |
11120 | } |
11121 | } else { |
11122 | mozilla::Unused |
11123 | << ContentChild::GetSingleton()->SendSessionHistoryEntryWireframe( |
11124 | mBrowsingContext, wireframe.ref()); |
11125 | } |
11126 | |
11127 | return true; |
11128 | } |
11129 | |
11130 | //***************************************************************************** |
11131 | // nsDocShell: Session History |
11132 | //***************************************************************************** |
11133 | |
11134 | NS_IMETHODIMPnsresult |
11135 | nsDocShell::AddState(JS::Handle<JS::Value> aData, const nsAString& aTitle, |
11136 | const nsAString& aURL, bool aReplace, JSContext* aCx) { |
11137 | 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) |
11138 | ("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) |
11139 | 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) |
11140 | 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); |
11141 | // Implements History.pushState and History.replaceState |
11142 | |
11143 | // Here's what we do, roughly in the order specified by HTML5. The specific |
11144 | // steps we are executing are at |
11145 | // <https://html.spec.whatwg.org/multipage/history.html#dom-history-pushstate> |
11146 | // and |
11147 | // <https://html.spec.whatwg.org/multipage/history.html#url-and-history-update-steps>. |
11148 | // This function basically implements #dom-history-pushstate and |
11149 | // UpdateURLAndHistory implements #url-and-history-update-steps. |
11150 | // |
11151 | // A. Serialize aData using structured clone. This is #dom-history-pushstate |
11152 | // step 5. |
11153 | // B. If the third argument is present, #dom-history-pushstate step 7. |
11154 | // 7.1. Resolve the url, relative to our document. |
11155 | // 7.2. If (a) fails, raise a SECURITY_ERR |
11156 | // 7.4. Compare the resulting absolute URL to the document's address. If |
11157 | // any part of the URLs difer other than the <path>, <query>, and |
11158 | // <fragment> components, raise a SECURITY_ERR and abort. |
11159 | // C. If !aReplace, #url-and-history-update-steps steps 2.1-2.3: |
11160 | // Remove from the session history all entries after the current entry, |
11161 | // as we would after a regular navigation, and save the current |
11162 | // entry's scroll position (bug 590573). |
11163 | // D. #url-and-history-update-steps step 2.4 or step 3. As apropriate, |
11164 | // either add a state object entry to the session history after the |
11165 | // current entry with the following properties, or modify the current |
11166 | // session history entry to set |
11167 | // a. cloned data as the state object, |
11168 | // b. if the third argument was present, the absolute URL found in |
11169 | // step 2 |
11170 | // Also clear the new history entry's POST data (see bug 580069). |
11171 | // E. If aReplace is false (i.e. we're doing a pushState instead of a |
11172 | // replaceState), notify bfcache that we've navigated to a new page. |
11173 | // F. If the third argument is present, set the document's current address |
11174 | // to the absolute URL found in step B. This is |
11175 | // #url-and-history-update-steps step 4. |
11176 | // |
11177 | // It's important that this function not run arbitrary scripts after step A |
11178 | // and before completing step E. For example, if a script called |
11179 | // history.back() before we completed step E, bfcache might destroy an |
11180 | // active content viewer. Since EvictOutOfRangeDocumentViewers at the end of |
11181 | // step E might run script, we can't just put a script blocker around the |
11182 | // critical section. |
11183 | // |
11184 | // Note that we completely ignore the aTitle parameter. |
11185 | |
11186 | nsresult rv; |
11187 | |
11188 | // Don't clobber the load type of an existing network load. |
11189 | AutoRestore<uint32_t> loadTypeResetter(mLoadType); |
11190 | |
11191 | // pushState effectively becomes replaceState when we've started a network |
11192 | // load but haven't adopted its document yet. This mirrors what we do with |
11193 | // changes to the hash at this stage of the game. |
11194 | if (JustStartedNetworkLoad()) { |
11195 | aReplace = true; |
11196 | } |
11197 | |
11198 | RefPtr<Document> document = GetDocument(); |
11199 | 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" , 11199); return NS_ERROR_FAILURE; } } while (false); |
11200 | |
11201 | // Step A: Serialize aData using structured clone. |
11202 | // https://html.spec.whatwg.org/multipage/history.html#dom-history-pushstate |
11203 | // step 5. |
11204 | nsCOMPtr<nsIStructuredCloneContainer> scContainer; |
11205 | |
11206 | // scContainer->Init might cause arbitrary JS to run, and this code might |
11207 | // navigate the page we're on, potentially to a different origin! (bug |
11208 | // 634834) To protect against this, we abort if our principal changes due |
11209 | // to the InitFromJSVal() call. |
11210 | { |
11211 | RefPtr<Document> origDocument = GetDocument(); |
11212 | if (!origDocument) { |
11213 | return NS_ERROR_DOM_SECURITY_ERR; |
11214 | } |
11215 | nsCOMPtr<nsIPrincipal> origPrincipal = origDocument->NodePrincipal(); |
11216 | |
11217 | scContainer = new nsStructuredCloneContainer(); |
11218 | rv = scContainer->InitFromJSVal(aData, aCx); |
11219 | 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" , 11219); return rv; } } while (false); |
11220 | |
11221 | RefPtr<Document> newDocument = GetDocument(); |
11222 | if (!newDocument) { |
11223 | return NS_ERROR_DOM_SECURITY_ERR; |
11224 | } |
11225 | nsCOMPtr<nsIPrincipal> newPrincipal = newDocument->NodePrincipal(); |
11226 | |
11227 | bool principalsEqual = false; |
11228 | origPrincipal->Equals(newPrincipal, &principalsEqual); |
11229 | 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" , 11229); return NS_ERROR_DOM_SECURITY_ERR; } } while (false); |
11230 | } |
11231 | |
11232 | // Check that the state object isn't too long. |
11233 | int32_t maxStateObjSize = StaticPrefs::browser_history_maxStateObjectSize(); |
11234 | if (maxStateObjSize < 0) { |
11235 | maxStateObjSize = 0; |
11236 | } |
11237 | |
11238 | uint64_t scSize; |
11239 | rv = scContainer->GetSerializedNBytes(&scSize); |
11240 | 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" , 11240); return rv; } } while (false); |
11241 | |
11242 | 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" , 11242); return NS_ERROR_ILLEGAL_VALUE; } } while (false); |
11243 | |
11244 | // Step B: Resolve aURL. |
11245 | // https://html.spec.whatwg.org/multipage/history.html#dom-history-pushstate |
11246 | // step 7. |
11247 | bool equalURIs = true; |
11248 | nsCOMPtr<nsIURI> currentURI; |
11249 | if (mCurrentURI) { |
11250 | currentURI = nsIOService::CreateExposableURI(mCurrentURI); |
11251 | } else { |
11252 | currentURI = mCurrentURI; |
11253 | } |
11254 | nsCOMPtr<nsIURI> newURI; |
11255 | if (aURL.Length() == 0) { |
11256 | newURI = currentURI; |
11257 | } else { |
11258 | // 7.1: Resolve aURL relative to mURI |
11259 | |
11260 | nsIURI* docBaseURI = document->GetDocBaseURI(); |
11261 | if (!docBaseURI) { |
11262 | return NS_ERROR_FAILURE; |
11263 | } |
11264 | |
11265 | nsAutoCString spec; |
11266 | docBaseURI->GetSpec(spec); |
11267 | |
11268 | rv = NS_NewURI(getter_AddRefs(newURI), aURL, |
11269 | document->GetDocumentCharacterSet(), docBaseURI); |
11270 | |
11271 | // 7.2: If 2a fails, raise a SECURITY_ERR |
11272 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
11273 | return NS_ERROR_DOM_SECURITY_ERR; |
11274 | } |
11275 | |
11276 | // 7.4 and 7.5: Same-origin check. |
11277 | if (!nsContentUtils::URIIsLocalFile(newURI)) { |
11278 | // In addition to checking that the security manager says that |
11279 | // the new URI has the same origin as our current URI, we also |
11280 | // check that the two URIs have the same userpass. (The |
11281 | // security manager says that |http://foo.com| and |
11282 | // |http://me@foo.com| have the same origin.) currentURI |
11283 | // won't contain the password part of the userpass, so this |
11284 | // means that it's never valid to specify a password in a |
11285 | // pushState or replaceState URI. |
11286 | |
11287 | nsCOMPtr<nsIScriptSecurityManager> secMan = |
11288 | do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID"@mozilla.org/scriptsecuritymanager;1"); |
11289 | 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" , 11289); return NS_ERROR_FAILURE; } } while (false); |
11290 | |
11291 | // It's very important that we check that newURI is of the same |
11292 | // origin as currentURI, not docBaseURI, because a page can |
11293 | // set docBaseURI arbitrarily to any domain. |
11294 | nsAutoCString currentUserPass, newUserPass; |
11295 | 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" , 11296); return NS_ERROR_FAILURE; } } while (false) |
11296 | 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" , 11296); return NS_ERROR_FAILURE; } } while (false); |
11297 | 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" , 11297); return NS_ERROR_FAILURE; } } while (false); |
11298 | bool isPrivateWin = |
11299 | document->NodePrincipal()->OriginAttributesRef().IsPrivateBrowsing(); |
11300 | if (NS_FAILED(secMan->CheckSameOriginURI(currentURI, newURI, true,((bool)(__builtin_expect(!!(NS_FAILED_impl(secMan->CheckSameOriginURI (currentURI, newURI, true, isPrivateWin))), 0))) |
11301 | isPrivateWin))((bool)(__builtin_expect(!!(NS_FAILED_impl(secMan->CheckSameOriginURI (currentURI, newURI, true, isPrivateWin))), 0))) || |
11302 | !currentUserPass.Equals(newUserPass)) { |
11303 | return NS_ERROR_DOM_SECURITY_ERR; |
11304 | } |
11305 | } else { |
11306 | // It's a file:// URI |
11307 | nsCOMPtr<nsIPrincipal> principal = document->GetPrincipal(); |
11308 | |
11309 | if (!principal || NS_FAILED(principal->CheckMayLoadWithReporting(((bool)(__builtin_expect(!!(NS_FAILED_impl(principal->CheckMayLoadWithReporting ( newURI, false, document->InnerWindowID()))), 0))) |
11310 | newURI, false, document->InnerWindowID()))((bool)(__builtin_expect(!!(NS_FAILED_impl(principal->CheckMayLoadWithReporting ( newURI, false, document->InnerWindowID()))), 0)))) { |
11311 | return NS_ERROR_DOM_SECURITY_ERR; |
11312 | } |
11313 | } |
11314 | |
11315 | if (currentURI) { |
11316 | currentURI->Equals(newURI, &equalURIs); |
11317 | } else { |
11318 | equalURIs = false; |
11319 | } |
11320 | |
11321 | } // end of same-origin check |
11322 | |
11323 | // Step 8: call "URL and history update steps" |
11324 | rv = UpdateURLAndHistory(document, newURI, scContainer, aTitle, aReplace, |
11325 | currentURI, equalURIs); |
11326 | 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" , 11326); return rv; } } while (false); |
11327 | |
11328 | return NS_OK; |
11329 | } |
11330 | |
11331 | nsresult nsDocShell::UpdateURLAndHistory(Document* aDocument, nsIURI* aNewURI, |
11332 | nsIStructuredCloneContainer* aData, |
11333 | const nsAString& aTitle, bool aReplace, |
11334 | nsIURI* aCurrentURI, bool aEqualURIs) { |
11335 | // Implements |
11336 | // https://html.spec.whatwg.org/multipage/history.html#url-and-history-update-steps |
11337 | |
11338 | // If we have a pending title change, handle it before creating a new entry. |
11339 | aDocument->DoNotifyPossibleTitleChange(); |
11340 | |
11341 | // Step 2, if aReplace is false: Create a new entry in the session |
11342 | // history. This will erase all SHEntries after the new entry and make this |
11343 | // entry the current one. This operation may modify mOSHE, which we need |
11344 | // later, so we keep a reference here. |
11345 | 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" , 11345); return NS_ERROR_FAILURE; } } while (false); |
11346 | nsCOMPtr<nsISHEntry> oldOSHE = mOSHE; |
11347 | |
11348 | // If this push/replaceState changed the document's current URI and the new |
11349 | // URI differs from the old URI in more than the hash, or if the old |
11350 | // SHEntry's URI was modified in this way by a push/replaceState call |
11351 | // set URIWasModified to true for the current SHEntry (bug 669671). |
11352 | bool sameExceptHashes = true; |
11353 | aNewURI->EqualsExceptRef(aCurrentURI, &sameExceptHashes); |
11354 | bool uriWasModified; |
11355 | if (sameExceptHashes) { |
11356 | if (mozilla::SessionHistoryInParent()) { |
11357 | uriWasModified = mActiveEntry && mActiveEntry->GetURIWasModified(); |
11358 | } else { |
11359 | uriWasModified = oldOSHE && oldOSHE->GetURIWasModified(); |
11360 | } |
11361 | } else { |
11362 | uriWasModified = true; |
11363 | } |
11364 | |
11365 | mLoadType = LOAD_PUSHSTATE; |
11366 | |
11367 | nsCOMPtr<nsISHEntry> newSHEntry; |
11368 | if (!aReplace) { |
11369 | // Step 2. |
11370 | |
11371 | // Step 2.2, "Remove any tasks queued by the history traversal task |
11372 | // source that are associated with any Document objects in the |
11373 | // top-level browsing context's document family." This is very hard in |
11374 | // SessionHistoryInParent since we can't synchronously access the |
11375 | // pending navigations that are already sent to the parent. We can |
11376 | // abort any AsyncGo navigations that are waiting to be sent. If we |
11377 | // send a message to the parent, it would be processed after any |
11378 | // navigations previously sent. So long as we consider the "history |
11379 | // traversal task source" to be the list in this process we match the |
11380 | // spec. If we move the entire list to the parent, we can handle the |
11381 | // aborting of loads there, but we don't have a way to synchronously |
11382 | // remove entries as we do here for non-SHIP. |
11383 | RefPtr<ChildSHistory> shistory = GetRootSessionHistory(); |
11384 | if (shistory) { |
11385 | shistory->RemovePendingHistoryNavigations(); |
11386 | } |
11387 | |
11388 | nsPoint scrollPos = GetCurScrollPos(); |
11389 | |
11390 | bool scrollRestorationIsManual; |
11391 | if (mozilla::SessionHistoryInParent()) { |
11392 | // FIXME Need to save the current scroll position on mActiveEntry. |
11393 | scrollRestorationIsManual = mActiveEntry->GetScrollRestorationIsManual(); |
11394 | } else { |
11395 | // Save the current scroll position (bug 590573). Step 2.3. |
11396 | mOSHE->SetScrollPosition(scrollPos.x, scrollPos.y); |
11397 | |
11398 | scrollRestorationIsManual = mOSHE->GetScrollRestorationIsManual(); |
11399 | } |
11400 | |
11401 | nsCOMPtr<nsIContentSecurityPolicy> csp = aDocument->GetCsp(); |
11402 | |
11403 | if (mozilla::SessionHistoryInParent()) { |
11404 | 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) |
11405 | ("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); |
11406 | |
11407 | nsString title(mActiveEntry->GetTitle()); |
11408 | nsCOMPtr<nsIReferrerInfo> referrerInfo = mActiveEntry->GetReferrerInfo(); |
11409 | |
11410 | UpdateActiveEntry(false, |
11411 | /* aPreviousScrollPos = */ Some(scrollPos), aNewURI, |
11412 | /* aOriginalURI = */ nullptr, |
11413 | /* aReferrerInfo = */ referrerInfo, |
11414 | /* aTriggeringPrincipal = */ aDocument->NodePrincipal(), |
11415 | csp, title, scrollRestorationIsManual, aData, |
11416 | uriWasModified); |
11417 | } else { |
11418 | // Since we're not changing which page we have loaded, pass |
11419 | // true for aCloneChildren. |
11420 | nsresult rv = AddToSessionHistory( |
11421 | aNewURI, nullptr, |
11422 | aDocument->NodePrincipal(), // triggeringPrincipal |
11423 | nullptr, nullptr, csp, true, getter_AddRefs(newSHEntry)); |
11424 | 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" , 11424); return rv; } } while (false); |
11425 | |
11426 | 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" , 11426); return NS_ERROR_FAILURE; } } while (false); |
11427 | |
11428 | // Session history entries created by pushState inherit scroll restoration |
11429 | // mode from the current entry. |
11430 | newSHEntry->SetScrollRestorationIsManual(scrollRestorationIsManual); |
11431 | |
11432 | // Set the new SHEntry's title (bug 655273). |
11433 | nsString title; |
11434 | mOSHE->GetTitle(title); |
11435 | newSHEntry->SetTitle(title); |
11436 | |
11437 | nsCOMPtr<nsIReferrerInfo> referrerInfo = mOSHE->GetReferrerInfo(); |
11438 | newSHEntry->SetReferrerInfo(referrerInfo); |
11439 | |
11440 | // Link the new SHEntry to the old SHEntry's BFCache entry, since the |
11441 | // two entries correspond to the same document. |
11442 | 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" , 11443); return NS_ERROR_FAILURE; } } while (false) |
11443 | 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" , 11443); return NS_ERROR_FAILURE; } } while (false); |
11444 | |
11445 | // AddToSessionHistory may not modify mOSHE. In case it doesn't, |
11446 | // we'll just set mOSHE here. |
11447 | mOSHE = newSHEntry; |
11448 | } |
11449 | } else if (mozilla::SessionHistoryInParent()) { |
11450 | 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) |
11451 | ("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) |
11452 | 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); |
11453 | // Setting the resultPrincipalURI to nullptr is fine here: it will cause |
11454 | // NS_GetFinalChannelURI to use the originalURI as the URI, which is aNewURI |
11455 | // in our case. We could also set it to aNewURI, with the same result. |
11456 | // We don't use aTitle here, see bug 544535. |
11457 | nsString title; |
11458 | nsCOMPtr<nsIReferrerInfo> referrerInfo; |
11459 | if (mActiveEntry) { |
11460 | title = mActiveEntry->GetTitle(); |
11461 | referrerInfo = mActiveEntry->GetReferrerInfo(); |
11462 | } else { |
11463 | referrerInfo = nullptr; |
11464 | } |
11465 | UpdateActiveEntry( |
11466 | true, /* aPreviousScrollPos = */ Nothing(), aNewURI, aNewURI, |
11467 | /* aReferrerInfo = */ referrerInfo, aDocument->NodePrincipal(), |
11468 | aDocument->GetCsp(), title, |
11469 | mActiveEntry && mActiveEntry->GetScrollRestorationIsManual(), aData, |
11470 | uriWasModified); |
11471 | } else { |
11472 | // Step 3. |
11473 | newSHEntry = mOSHE; |
11474 | |
11475 | 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); |
11476 | // Since we're not changing which page we have loaded, pass |
11477 | // true for aCloneChildren. |
11478 | if (!newSHEntry) { |
11479 | nsresult rv = AddToSessionHistory( |
11480 | aNewURI, nullptr, |
11481 | aDocument->NodePrincipal(), // triggeringPrincipal |
11482 | nullptr, nullptr, aDocument->GetCsp(), true, |
11483 | getter_AddRefs(newSHEntry)); |
11484 | 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" , 11484); return rv; } } while (false); |
11485 | mOSHE = newSHEntry; |
11486 | } |
11487 | |
11488 | nsCOMPtr<nsIReferrerInfo> referrerInfo = mOSHE->GetReferrerInfo(); |
11489 | |
11490 | newSHEntry->SetURI(aNewURI); |
11491 | newSHEntry->SetOriginalURI(aNewURI); |
11492 | // We replaced the URI of the entry, clear the unstripped URI as it |
11493 | // shouldn't be used for reloads anymore. |
11494 | newSHEntry->SetUnstrippedURI(nullptr); |
11495 | // Setting the resultPrincipalURI to nullptr is fine here: it will cause |
11496 | // NS_GetFinalChannelURI to use the originalURI as the URI, which is aNewURI |
11497 | // in our case. We could also set it to aNewURI, with the same result. |
11498 | newSHEntry->SetResultPrincipalURI(nullptr); |
11499 | newSHEntry->SetLoadReplace(false); |
11500 | newSHEntry->SetReferrerInfo(referrerInfo); |
11501 | } |
11502 | |
11503 | if (!mozilla::SessionHistoryInParent()) { |
11504 | // Step 2.4 and 3: Modify new/original session history entry and clear its |
11505 | // POST data, if there is any. |
11506 | newSHEntry->SetStateData(aData); |
11507 | newSHEntry->SetPostData(nullptr); |
11508 | |
11509 | newSHEntry->SetURIWasModified(uriWasModified); |
11510 | |
11511 | // Step E as described at the top of AddState: If aReplace is false, |
11512 | // indicating that we're doing a pushState rather than a replaceState, |
11513 | // notify bfcache that we've added a page to the history so it can evict |
11514 | // content viewers if appropriate. Otherwise call ReplaceEntry so that we |
11515 | // notify nsIHistoryListeners that an entry was replaced. We may not have a |
11516 | // root session history if this call is coming from a document.open() in a |
11517 | // docshell subtree that disables session history. |
11518 | RefPtr<ChildSHistory> rootSH = GetRootSessionHistory(); |
11519 | if (rootSH) { |
11520 | rootSH->LegacySHistory()->EvictDocumentViewersOrReplaceEntry(newSHEntry, |
11521 | aReplace); |
11522 | } |
11523 | } |
11524 | |
11525 | // Step 4: If the document's URI changed, update document's URI and update |
11526 | // global history. |
11527 | // |
11528 | // We need to call FireOnLocationChange so that the browser's address bar |
11529 | // gets updated and the back button is enabled, but we only need to |
11530 | // explicitly call FireOnLocationChange if we're not calling SetCurrentURI, |
11531 | // since SetCurrentURI will call FireOnLocationChange for us. |
11532 | // |
11533 | // Both SetCurrentURI(...) and FireDummyOnLocationChange() pass |
11534 | // nullptr for aRequest param to FireOnLocationChange(...). Such an update |
11535 | // notification is allowed only when we know docshell is not loading a new |
11536 | // document and it requires LOCATION_CHANGE_SAME_DOCUMENT flag. Otherwise, |
11537 | // FireOnLocationChange(...) breaks security UI. |
11538 | // |
11539 | // If the docshell is shutting down, don't update the document URI, as we |
11540 | // can't load into a docshell that is being destroyed. |
11541 | if (!aEqualURIs && !mIsBeingDestroyed) { |
11542 | aDocument->SetDocumentURI(aNewURI); |
11543 | SetCurrentURI(aNewURI, nullptr, /* aFireLocationChange */ true, |
11544 | /* aIsInitialAboutBlank */ false, |
11545 | GetSameDocumentNavigationFlags(aNewURI)); |
11546 | |
11547 | AddURIVisit(aNewURI, aCurrentURI, 0); |
11548 | |
11549 | // AddURIVisit doesn't set the title for the new URI in global history, |
11550 | // so do that here. |
11551 | UpdateGlobalHistoryTitle(aNewURI); |
11552 | |
11553 | // Inform the favicon service that our old favicon applies to this new |
11554 | // URI. |
11555 | CopyFavicon(aCurrentURI, aNewURI, UsePrivateBrowsing()); |
11556 | } else { |
11557 | FireDummyOnLocationChange(); |
11558 | } |
11559 | aDocument->SetStateObject(aData); |
11560 | |
11561 | return NS_OK; |
11562 | } |
11563 | |
11564 | NS_IMETHODIMPnsresult |
11565 | nsDocShell::GetCurrentScrollRestorationIsManual(bool* aIsManual) { |
11566 | if (mozilla::SessionHistoryInParent()) { |
11567 | *aIsManual = mActiveEntry && mActiveEntry->GetScrollRestorationIsManual(); |
11568 | return NS_OK; |
11569 | } |
11570 | |
11571 | *aIsManual = false; |
11572 | if (mOSHE) { |
11573 | return mOSHE->GetScrollRestorationIsManual(aIsManual); |
11574 | } |
11575 | |
11576 | return NS_OK; |
11577 | } |
11578 | |
11579 | NS_IMETHODIMPnsresult |
11580 | nsDocShell::SetCurrentScrollRestorationIsManual(bool aIsManual) { |
11581 | SetScrollRestorationIsManualOnHistoryEntry(mOSHE, aIsManual); |
11582 | |
11583 | return NS_OK; |
11584 | } |
11585 | |
11586 | void nsDocShell::SetScrollRestorationIsManualOnHistoryEntry( |
11587 | nsISHEntry* aSHEntry, bool aIsManual) { |
11588 | if (aSHEntry) { |
11589 | aSHEntry->SetScrollRestorationIsManual(aIsManual); |
11590 | } |
11591 | |
11592 | if (mActiveEntry && mBrowsingContext) { |
11593 | mActiveEntry->SetScrollRestorationIsManual(aIsManual); |
11594 | if (XRE_IsParentProcess()) { |
11595 | SessionHistoryEntry* entry = |
11596 | mBrowsingContext->Canonical()->GetActiveSessionHistoryEntry(); |
11597 | if (entry) { |
11598 | entry->SetScrollRestorationIsManual(aIsManual); |
11599 | } |
11600 | } else { |
11601 | mozilla::Unused << ContentChild::GetSingleton() |
11602 | ->SendSessionHistoryEntryScrollRestorationIsManual( |
11603 | mBrowsingContext, aIsManual); |
11604 | } |
11605 | } |
11606 | } |
11607 | |
11608 | void nsDocShell::SetCacheKeyOnHistoryEntry(nsISHEntry* aSHEntry, |
11609 | uint32_t aCacheKey) { |
11610 | if (aSHEntry) { |
11611 | aSHEntry->SetCacheKey(aCacheKey); |
11612 | } |
11613 | |
11614 | if (mActiveEntry && mBrowsingContext) { |
11615 | mActiveEntry->SetCacheKey(aCacheKey); |
11616 | if (XRE_IsParentProcess()) { |
11617 | SessionHistoryEntry* entry = |
11618 | mBrowsingContext->Canonical()->GetActiveSessionHistoryEntry(); |
11619 | if (entry) { |
11620 | entry->SetCacheKey(aCacheKey); |
11621 | } |
11622 | } else { |
11623 | mozilla::Unused |
11624 | << ContentChild::GetSingleton()->SendSessionHistoryEntryCacheKey( |
11625 | mBrowsingContext, aCacheKey); |
11626 | } |
11627 | } |
11628 | } |
11629 | |
11630 | /* static */ |
11631 | bool nsDocShell::ShouldAddToSessionHistory(nsIURI* aURI, nsIChannel* aChannel) { |
11632 | // I believe none of the about: urls should go in the history. But then |
11633 | // that could just be me... If the intent is only deny about:blank then we |
11634 | // should just do a spec compare, rather than two gets of the scheme and |
11635 | // then the path. -Gagan |
11636 | nsresult rv; |
11637 | nsAutoCString buf; |
11638 | |
11639 | rv = aURI->GetScheme(buf); |
11640 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
11641 | return false; |
11642 | } |
11643 | |
11644 | if (buf.EqualsLiteral("about")) { |
11645 | rv = aURI->GetPathQueryRef(buf); |
11646 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
11647 | return false; |
11648 | } |
11649 | |
11650 | if (buf.EqualsLiteral("blank")) { |
11651 | return false; |
11652 | } |
11653 | // We only want to add about:newtab if it's not privileged, and |
11654 | // if it is not configured to show the blank page. |
11655 | if (buf.EqualsLiteral("newtab")) { |
11656 | if (!StaticPrefs::browser_newtabpage_enabled()) { |
11657 | return false; |
11658 | } |
11659 | |
11660 | 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" , 11660); return false; } } while (false); |
11661 | nsCOMPtr<nsIPrincipal> resultPrincipal; |
11662 | rv = nsContentUtils::GetSecurityManager()->GetChannelResultPrincipal( |
11663 | aChannel, getter_AddRefs(resultPrincipal)); |
11664 | 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" , 11664); return false; } } while (false); |
11665 | return !resultPrincipal->IsSystemPrincipal(); |
11666 | } |
11667 | } |
11668 | |
11669 | return true; |
11670 | } |
11671 | |
11672 | nsresult nsDocShell::AddToSessionHistory( |
11673 | nsIURI* aURI, nsIChannel* aChannel, nsIPrincipal* aTriggeringPrincipal, |
11674 | nsIPrincipal* aPrincipalToInherit, |
11675 | nsIPrincipal* aPartitionedPrincipalToInherit, |
11676 | nsIContentSecurityPolicy* aCsp, bool aCloneChildren, |
11677 | nsISHEntry** aNewEntry) { |
11678 | 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" , 11678); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aURI" ") (" "uri is null" ")"); do { *((volatile int*)__null) = 11678; __attribute__ ((nomerge)) ::abort(); } while (false); } } while (false); |
11679 | 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" , 11679); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aChannel || !aTriggeringPrincipal" ") (" "Shouldn't have both set" ")"); do { *((volatile int*) __null) = 11679; __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); |
11680 | 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" , 11680); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "!mozilla::SessionHistoryInParent()" ")"); do { *((volatile int*)__null) = 11680; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
11681 | |
11682 | #if defined(DEBUG1) |
11683 | if (MOZ_LOG_TEST(gDocShellLog, LogLevel::Debug)(__builtin_expect(!!(mozilla::detail::log_test(gDocShellLog, LogLevel ::Debug)), 0))) { |
11684 | nsAutoCString chanName; |
11685 | if (aChannel) { |
11686 | aChannel->GetName(chanName); |
11687 | } else { |
11688 | chanName.AssignLiteral("<no channel>"); |
11689 | } |
11690 | |
11691 | 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) |
11692 | ("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) |
11693 | 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); |
11694 | } |
11695 | #endif |
11696 | |
11697 | nsresult rv = NS_OK; |
11698 | nsCOMPtr<nsISHEntry> entry; |
11699 | |
11700 | /* |
11701 | * If this is a LOAD_FLAGS_REPLACE_HISTORY in a subframe, we use |
11702 | * the existing SH entry in the page and replace the url and |
11703 | * other vitalities. |
11704 | */ |
11705 | if (LOAD_TYPE_HAS_FLAGS(mLoadType, LOAD_FLAGS_REPLACE_HISTORY)((mLoadType) & ((LOAD_FLAGS_REPLACE_HISTORY) << 16) ) && |
11706 | !mBrowsingContext->IsTop()) { |
11707 | // This is a subframe |
11708 | entry = mOSHE; |
11709 | if (entry) { |
11710 | entry->ClearEntry(); |
11711 | } |
11712 | } |
11713 | |
11714 | // Create a new entry if necessary. |
11715 | if (!entry) { |
11716 | entry = new nsSHEntry(); |
11717 | } |
11718 | |
11719 | // Get the post data & referrer |
11720 | nsCOMPtr<nsIInputStream> inputStream; |
11721 | nsCOMPtr<nsIURI> originalURI; |
11722 | nsCOMPtr<nsIURI> resultPrincipalURI; |
11723 | nsCOMPtr<nsIURI> unstrippedURI; |
11724 | bool loadReplace = false; |
11725 | nsCOMPtr<nsIReferrerInfo> referrerInfo; |
11726 | uint32_t cacheKey = 0; |
11727 | nsCOMPtr<nsIPrincipal> triggeringPrincipal = aTriggeringPrincipal; |
11728 | nsCOMPtr<nsIPrincipal> principalToInherit = aPrincipalToInherit; |
11729 | nsCOMPtr<nsIPrincipal> partitionedPrincipalToInherit = |
11730 | aPartitionedPrincipalToInherit; |
11731 | nsCOMPtr<nsIContentSecurityPolicy> csp = aCsp; |
11732 | bool expired = false; // by default the page is not expired |
11733 | bool discardLayoutState = false; |
11734 | nsCOMPtr<nsICacheInfoChannel> cacheChannel; |
11735 | bool userActivation = false; |
11736 | |
11737 | if (aChannel) { |
11738 | cacheChannel = do_QueryInterface(aChannel); |
11739 | |
11740 | /* If there is a caching channel, get the Cache Key and store it |
11741 | * in SH. |
11742 | */ |
11743 | if (cacheChannel) { |
11744 | cacheChannel->GetCacheKey(&cacheKey); |
11745 | } |
11746 | nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(aChannel)); |
11747 | |
11748 | // Check if the httpChannel is hiding under a multipartChannel |
11749 | if (!httpChannel) { |
11750 | GetHttpChannel(aChannel, getter_AddRefs(httpChannel)); |
11751 | } |
11752 | if (httpChannel) { |
11753 | nsCOMPtr<nsIUploadChannel> uploadChannel(do_QueryInterface(httpChannel)); |
11754 | if (uploadChannel) { |
11755 | uploadChannel->GetUploadStream(getter_AddRefs(inputStream)); |
11756 | } |
11757 | httpChannel->GetOriginalURI(getter_AddRefs(originalURI)); |
11758 | uint32_t loadFlags; |
11759 | aChannel->GetLoadFlags(&loadFlags); |
11760 | loadReplace = loadFlags & nsIChannel::LOAD_REPLACE; |
11761 | rv = httpChannel->GetReferrerInfo(getter_AddRefs(referrerInfo)); |
11762 | 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" , 11762); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))" ")"); do { *((volatile int*)__null) = 11762; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
11763 | |
11764 | discardLayoutState = ShouldDiscardLayoutState(httpChannel); |
11765 | } |
11766 | |
11767 | nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo(); |
11768 | if (!triggeringPrincipal) { |
11769 | triggeringPrincipal = loadInfo->TriggeringPrincipal(); |
11770 | } |
11771 | if (!csp) { |
11772 | csp = loadInfo->GetCspToInherit(); |
11773 | } |
11774 | |
11775 | loadInfo->GetResultPrincipalURI(getter_AddRefs(resultPrincipalURI)); |
11776 | |
11777 | loadInfo->GetUnstrippedURI(getter_AddRefs(unstrippedURI)); |
11778 | |
11779 | userActivation = loadInfo->GetHasValidUserGestureActivation(); |
11780 | |
11781 | // For now keep storing just the principal in the SHEntry. |
11782 | if (!principalToInherit) { |
11783 | if (loadInfo->GetLoadingSandboxed()) { |
11784 | if (loadInfo->GetLoadingPrincipal()) { |
11785 | principalToInherit = NullPrincipal::CreateWithInheritedAttributes( |
11786 | loadInfo->GetLoadingPrincipal()); |
11787 | } else { |
11788 | // get the OriginAttributes |
11789 | OriginAttributes attrs; |
11790 | loadInfo->GetOriginAttributes(&attrs); |
11791 | principalToInherit = NullPrincipal::Create(attrs); |
11792 | } |
11793 | } else { |
11794 | principalToInherit = loadInfo->PrincipalToInherit(); |
11795 | } |
11796 | } |
11797 | |
11798 | if (!partitionedPrincipalToInherit) { |
11799 | // XXXehsan is it correct to fall back to the principal to inherit in all |
11800 | // cases? For example, what about the cases where we are using the load |
11801 | // info's principal to inherit? Do we need to add a similar concept to |
11802 | // load info for partitioned principal? |
11803 | partitionedPrincipalToInherit = principalToInherit; |
11804 | } |
11805 | } |
11806 | |
11807 | nsAutoString srcdoc; |
11808 | bool srcdocEntry = false; |
11809 | nsCOMPtr<nsIURI> baseURI; |
11810 | |
11811 | nsCOMPtr<nsIInputStreamChannel> inStrmChan = do_QueryInterface(aChannel); |
11812 | if (inStrmChan) { |
11813 | bool isSrcdocChannel; |
11814 | inStrmChan->GetIsSrcdocChannel(&isSrcdocChannel); |
11815 | if (isSrcdocChannel) { |
11816 | inStrmChan->GetSrcdocData(srcdoc); |
11817 | srcdocEntry = true; |
11818 | inStrmChan->GetBaseURI(getter_AddRefs(baseURI)); |
11819 | } else { |
11820 | srcdoc.SetIsVoid(true); |
11821 | } |
11822 | } |
11823 | /* If cache got a 'no-store', ask SH not to store |
11824 | * HistoryLayoutState. By default, SH will set this |
11825 | * flag to true and save HistoryLayoutState. |
11826 | */ |
11827 | bool saveLayoutState = !discardLayoutState; |
11828 | |
11829 | if (cacheChannel) { |
11830 | // Check if the page has expired from cache |
11831 | uint32_t expTime = 0; |
11832 | cacheChannel->GetCacheTokenExpirationTime(&expTime); |
11833 | uint32_t now = PRTimeToSeconds(PR_Now()); |
11834 | if (expTime <= now) { |
11835 | expired = true; |
11836 | } |
11837 | } |
11838 | |
11839 | // Title is set in nsDocShell::SetTitle() |
11840 | entry->Create(aURI, // uri |
11841 | u""_ns, // Title |
11842 | inputStream, // Post data stream |
11843 | cacheKey, // CacheKey |
11844 | mContentTypeHint, // Content-type |
11845 | triggeringPrincipal, // Channel or provided principal |
11846 | principalToInherit, partitionedPrincipalToInherit, csp, |
11847 | HistoryID(), GetCreatedDynamically(), originalURI, |
11848 | resultPrincipalURI, unstrippedURI, loadReplace, referrerInfo, |
11849 | srcdoc, srcdocEntry, baseURI, saveLayoutState, expired, |
11850 | userActivation); |
11851 | |
11852 | if (mBrowsingContext->IsTop() && GetSessionHistory()) { |
11853 | bool shouldPersist = ShouldAddToSessionHistory(aURI, aChannel); |
11854 | Maybe<int32_t> previousEntryIndex; |
11855 | Maybe<int32_t> loadedEntryIndex; |
11856 | rv = GetSessionHistory()->LegacySHistory()->AddToRootSessionHistory( |
11857 | aCloneChildren, mOSHE, mBrowsingContext, entry, mLoadType, |
11858 | shouldPersist, &previousEntryIndex, &loadedEntryIndex); |
11859 | |
11860 | 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" , 11860); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))" ") (" "Could not add entry to root session history" ")"); do { *((volatile int*)__null) = 11860; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
11861 | if (previousEntryIndex.isSome()) { |
11862 | mPreviousEntryIndex = previousEntryIndex.value(); |
11863 | } |
11864 | if (loadedEntryIndex.isSome()) { |
11865 | mLoadedEntryIndex = loadedEntryIndex.value(); |
11866 | } |
11867 | |
11868 | // aCloneChildren implies that we are retaining the same document, thus we |
11869 | // need to signal to the top WC that the new SHEntry may receive a fresh |
11870 | // user interaction flag. |
11871 | if (aCloneChildren) { |
11872 | WindowContext* topWc = mBrowsingContext->GetTopWindowContext(); |
11873 | if (topWc && !topWc->IsDiscarded()) { |
11874 | 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" , 11874); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false" ") (" "NS_SUCCEEDED(topWc->SetSHEntryHasUserInteraction(false))" ")"); do { *((volatile int*)__null) = 11874; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); } } while (false); |
11875 | } |
11876 | } |
11877 | } else { |
11878 | // This is a subframe, make sure that this new SHEntry will be |
11879 | // marked with user interaction. |
11880 | WindowContext* topWc = mBrowsingContext->GetTopWindowContext(); |
11881 | if (topWc && !topWc->IsDiscarded()) { |
11882 | 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" , 11882); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false" ") (" "NS_SUCCEEDED(topWc->SetSHEntryHasUserInteraction(false))" ")"); do { *((volatile int*)__null) = 11882; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); } } while (false); |
11883 | } |
11884 | if (!mOSHE || !LOAD_TYPE_HAS_FLAGS(mLoadType, LOAD_FLAGS_REPLACE_HISTORY)((mLoadType) & ((LOAD_FLAGS_REPLACE_HISTORY) << 16) )) { |
11885 | rv = AddChildSHEntryToParent(entry, mBrowsingContext->ChildOffset(), |
11886 | aCloneChildren); |
11887 | } |
11888 | } |
11889 | |
11890 | // Return the new SH entry... |
11891 | if (aNewEntry) { |
11892 | *aNewEntry = nullptr; |
11893 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) { |
11894 | entry.forget(aNewEntry); |
11895 | } |
11896 | } |
11897 | |
11898 | return rv; |
11899 | } |
11900 | |
11901 | void nsDocShell::UpdateActiveEntry( |
11902 | bool aReplace, const Maybe<nsPoint>& aPreviousScrollPos, nsIURI* aURI, |
11903 | nsIURI* aOriginalURI, nsIReferrerInfo* aReferrerInfo, |
11904 | nsIPrincipal* aTriggeringPrincipal, nsIContentSecurityPolicy* aCsp, |
11905 | const nsAString& aTitle, bool aScrollRestorationIsManual, |
11906 | nsIStructuredCloneContainer* aData, bool aURIWasModified) { |
11907 | 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" , 11907); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mozilla::SessionHistoryInParent()" ")"); do { *((volatile int*)__null) = 11907; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
11908 | 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" , 11908); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aURI" ") (" "uri is null" ")"); do { *((volatile int*)__null) = 11908; __attribute__ ((nomerge)) ::abort(); } while (false); } } while (false); |
11909 | 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" , 11910); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLoadType == LOAD_PUSHSTATE" ") (" "This code only deals with pushState" ")"); do { *((volatile int*)__null) = 11910; __attribute__((nomerge)) ::abort(); } while (false); } } while (false) |
11910 | "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" , 11910); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLoadType == LOAD_PUSHSTATE" ") (" "This code only deals with pushState" ")"); do { *((volatile int*)__null) = 11910; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
11911 | 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" , 11911); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aReplace" ")"); do { *((volatile int*)__null) = 11911; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); } } while (false); |
11912 | |
11913 | 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) |
11914 | ("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) |
11915 | 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); |
11916 | |
11917 | // Even if we're replacing an existing entry we create new a |
11918 | // SessionHistoryInfo. In the parent process we'll keep the existing |
11919 | // SessionHistoryEntry, but just replace its SessionHistoryInfo, that way the |
11920 | // entry keeps identity but its data is replaced. |
11921 | bool replace = aReplace && mActiveEntry; |
11922 | |
11923 | if (!replace) { |
11924 | CollectWireframe(); |
11925 | } |
11926 | |
11927 | if (mActiveEntry) { |
11928 | // Link this entry to the previous active entry. |
11929 | mActiveEntry = MakeUnique<SessionHistoryInfo>(*mActiveEntry, aURI); |
11930 | } else { |
11931 | mActiveEntry = MakeUnique<SessionHistoryInfo>( |
11932 | aURI, aTriggeringPrincipal, nullptr, nullptr, aCsp, mContentTypeHint); |
11933 | } |
11934 | mActiveEntry->SetOriginalURI(aOriginalURI); |
11935 | mActiveEntry->SetUnstrippedURI(nullptr); |
11936 | mActiveEntry->SetReferrerInfo(aReferrerInfo); |
11937 | mActiveEntry->SetTitle(aTitle); |
11938 | mActiveEntry->SetStateData(static_cast<nsStructuredCloneContainer*>(aData)); |
11939 | mActiveEntry->SetURIWasModified(aURIWasModified); |
11940 | mActiveEntry->SetScrollRestorationIsManual(aScrollRestorationIsManual); |
11941 | |
11942 | if (replace) { |
11943 | mBrowsingContext->ReplaceActiveSessionHistoryEntry(mActiveEntry.get()); |
11944 | } else { |
11945 | mBrowsingContext->IncrementHistoryEntryCountForBrowsingContext(); |
11946 | // FIXME We should probably just compute mChildOffset in the parent |
11947 | // instead of passing it over IPC here. |
11948 | mBrowsingContext->SetActiveSessionHistoryEntry( |
11949 | aPreviousScrollPos, mActiveEntry.get(), mLoadType, |
11950 | /* aCacheKey = */ 0); |
11951 | // FIXME Do we need to update mPreviousEntryIndex and mLoadedEntryIndex? |
11952 | } |
11953 | } |
11954 | |
11955 | nsresult nsDocShell::LoadHistoryEntry(nsISHEntry* aEntry, uint32_t aLoadType, |
11956 | bool aUserActivation) { |
11957 | 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" , 11957); return NS_ERROR_FAILURE; } } while (false); |
11958 | |
11959 | nsresult rv; |
11960 | RefPtr<nsDocShellLoadState> loadState; |
11961 | rv = aEntry->CreateLoadInfo(getter_AddRefs(loadState)); |
11962 | 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" , 11962); return rv; } } while (false); |
11963 | |
11964 | // Calling CreateAboutBlankDocumentViewer can set mOSHE to null, and if |
11965 | // that's the only thing holding a ref to aEntry that will cause aEntry to |
11966 | // die while we're loading it. So hold a strong ref to aEntry here, just |
11967 | // in case. |
11968 | nsCOMPtr<nsISHEntry> kungFuDeathGrip(aEntry); |
11969 | |
11970 | loadState->SetHasValidUserGestureActivation( |
11971 | loadState->HasValidUserGestureActivation() || aUserActivation); |
11972 | |
11973 | loadState->SetTextDirectiveUserActivation( |
11974 | loadState->GetTextDirectiveUserActivation() || aUserActivation); |
11975 | |
11976 | return LoadHistoryEntry(loadState, aLoadType, aEntry == mOSHE); |
11977 | } |
11978 | |
11979 | nsresult nsDocShell::LoadHistoryEntry(const LoadingSessionHistoryInfo& aEntry, |
11980 | uint32_t aLoadType, |
11981 | bool aUserActivation) { |
11982 | RefPtr<nsDocShellLoadState> loadState = aEntry.CreateLoadInfo(); |
11983 | loadState->SetHasValidUserGestureActivation( |
11984 | loadState->HasValidUserGestureActivation() || aUserActivation); |
11985 | |
11986 | loadState->SetTextDirectiveUserActivation( |
11987 | loadState->GetTextDirectiveUserActivation() || aUserActivation); |
11988 | |
11989 | return LoadHistoryEntry(loadState, aLoadType, aEntry.mLoadingCurrentEntry); |
11990 | } |
11991 | |
11992 | nsresult nsDocShell::LoadHistoryEntry(nsDocShellLoadState* aLoadState, |
11993 | uint32_t aLoadType, |
11994 | bool aLoadingCurrentEntry) { |
11995 | if (!IsNavigationAllowed()) { |
11996 | return NS_OK; |
11997 | } |
11998 | |
11999 | // We are setting load type afterwards so we don't have to |
12000 | // send it in an IPC message |
12001 | aLoadState->SetLoadType(aLoadType); |
12002 | |
12003 | nsresult rv; |
12004 | if (SchemeIsJavascript(aLoadState->URI())) { |
12005 | // We're loading a URL that will execute script from inside asyncOpen. |
12006 | // Replace the current document with about:blank now to prevent |
12007 | // anything from the current document from leaking into any JavaScript |
12008 | // code in the URL. |
12009 | // Don't cache the presentation if we're going to just reload the |
12010 | // current entry. Caching would lead to trying to save the different |
12011 | // content viewers in the same nsISHEntry object. |
12012 | rv = CreateAboutBlankDocumentViewer( |
12013 | aLoadState->PrincipalToInherit(), |
12014 | aLoadState->PartitionedPrincipalToInherit(), nullptr, nullptr, |
12015 | /* aIsInitialDocument */ false, Nothing(), !aLoadingCurrentEntry); |
12016 | |
12017 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
12018 | // The creation of the intermittent about:blank content |
12019 | // viewer failed for some reason (potentially because the |
12020 | // user prevented it). Interrupt the history load. |
12021 | return NS_OK; |
12022 | } |
12023 | |
12024 | if (!aLoadState->TriggeringPrincipal()) { |
12025 | // Ensure that we have a triggeringPrincipal. Otherwise javascript: |
12026 | // URIs will pick it up from the about:blank page we just loaded, |
12027 | // and we don't really want even that in this case. |
12028 | nsCOMPtr<nsIPrincipal> principal = |
12029 | NullPrincipal::Create(GetOriginAttributes()); |
12030 | aLoadState->SetTriggeringPrincipal(principal); |
12031 | } |
12032 | } |
12033 | |
12034 | /* If there is a valid postdata *and* the user pressed |
12035 | * reload or shift-reload, take user's permission before we |
12036 | * repost the data to the server. |
12037 | */ |
12038 | if ((aLoadType & LOAD_CMD_RELOAD) && aLoadState->PostDataStream()) { |
12039 | bool repost; |
12040 | rv = ConfirmRepost(&repost); |
12041 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
12042 | return rv; |
12043 | } |
12044 | |
12045 | // If the user pressed cancel in the dialog, return. We're done here. |
12046 | if (!repost) { |
12047 | return NS_BINDING_ABORTED; |
12048 | } |
12049 | } |
12050 | |
12051 | // If there is no valid triggeringPrincipal, we deny the load |
12052 | 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" , 12053); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->TriggeringPrincipal()" ") (" "need a valid triggeringPrincipal to load from history" ")"); do { *((volatile int*)__null) = 12053; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false) |
12053 | "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" , 12053); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->TriggeringPrincipal()" ") (" "need a valid triggeringPrincipal to load from history" ")"); do { *((volatile int*)__null) = 12053; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
12054 | if (!aLoadState->TriggeringPrincipal()) { |
12055 | return NS_ERROR_FAILURE; |
12056 | } |
12057 | |
12058 | return InternalLoad(aLoadState); // No nsIRequest |
12059 | } |
12060 | |
12061 | NS_IMETHODIMPnsresult |
12062 | nsDocShell::PersistLayoutHistoryState() { |
12063 | nsresult rv = NS_OK; |
12064 | |
12065 | if (mozilla::SessionHistoryInParent() ? !!mActiveEntry : !!mOSHE) { |
12066 | bool scrollRestorationIsManual; |
12067 | if (mozilla::SessionHistoryInParent()) { |
12068 | scrollRestorationIsManual = mActiveEntry->GetScrollRestorationIsManual(); |
12069 | } else { |
12070 | scrollRestorationIsManual = mOSHE->GetScrollRestorationIsManual(); |
12071 | } |
12072 | nsCOMPtr<nsILayoutHistoryState> layoutState; |
12073 | if (RefPtr<PresShell> presShell = GetPresShell()) { |
12074 | rv = presShell->CaptureHistoryState(getter_AddRefs(layoutState)); |
12075 | } else if (scrollRestorationIsManual) { |
12076 | // Even if we don't have layout anymore, we may want to reset the |
12077 | // current scroll state in layout history. |
12078 | GetLayoutHistoryState(getter_AddRefs(layoutState)); |
12079 | } |
12080 | |
12081 | if (scrollRestorationIsManual && layoutState) { |
12082 | layoutState->ResetScrollState(); |
12083 | } |
12084 | } |
12085 | |
12086 | return rv; |
12087 | } |
12088 | |
12089 | void nsDocShell::SwapHistoryEntries(nsISHEntry* aOldEntry, |
12090 | nsISHEntry* aNewEntry) { |
12091 | if (aOldEntry == mOSHE) { |
12092 | mOSHE = aNewEntry; |
12093 | } |
12094 | |
12095 | if (aOldEntry == mLSHE) { |
12096 | mLSHE = aNewEntry; |
12097 | } |
12098 | } |
12099 | |
12100 | void nsDocShell::SetHistoryEntryAndUpdateBC(const Maybe<nsISHEntry*>& aLSHE, |
12101 | const Maybe<nsISHEntry*>& aOSHE) { |
12102 | // We want to hold on to the reference in mLSHE before we update it. |
12103 | // Otherwise, SetHistoryEntry could release the last reference to |
12104 | // the entry while aOSHE is pointing to it. |
12105 | nsCOMPtr<nsISHEntry> deathGripOldLSHE; |
12106 | if (aLSHE.isSome()) { |
12107 | deathGripOldLSHE = SetHistoryEntry(&mLSHE, aLSHE.value()); |
12108 | 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" , 12108); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLSHE.get() == aLSHE.value()" ")"); do { *((volatile int*)__null) = 12108; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
12109 | } |
12110 | nsCOMPtr<nsISHEntry> deathGripOldOSHE; |
12111 | if (aOSHE.isSome()) { |
12112 | deathGripOldOSHE = SetHistoryEntry(&mOSHE, aOSHE.value()); |
12113 | 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" , 12113); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mOSHE.get() == aOSHE.value()" ")"); do { *((volatile int*)__null) = 12113; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
12114 | } |
12115 | } |
12116 | |
12117 | already_AddRefed<nsISHEntry> nsDocShell::SetHistoryEntry( |
12118 | nsCOMPtr<nsISHEntry>* aPtr, nsISHEntry* aEntry) { |
12119 | // We need to sync up the docshell and session history trees for |
12120 | // subframe navigation. If the load was in a subframe, we forward up to |
12121 | // the root docshell, which will then recursively sync up all docshells |
12122 | // to their corresponding entries in the new session history tree. |
12123 | // If we don't do this, then we can cache a content viewer on the wrong |
12124 | // cloned entry, and subsequently restore it at the wrong time. |
12125 | RefPtr<BrowsingContext> topBC = mBrowsingContext->Top(); |
12126 | if (topBC->IsDiscarded()) { |
12127 | topBC = nullptr; |
12128 | } |
12129 | RefPtr<BrowsingContext> currBC = |
12130 | mBrowsingContext->IsDiscarded() ? nullptr : mBrowsingContext; |
12131 | if (topBC && *aPtr) { |
12132 | (*aPtr)->SyncTreesForSubframeNavigation(aEntry, topBC, currBC); |
12133 | } |
12134 | nsCOMPtr<nsISHEntry> entry(aEntry); |
12135 | entry.swap(*aPtr); |
12136 | return entry.forget(); |
12137 | } |
12138 | |
12139 | already_AddRefed<ChildSHistory> nsDocShell::GetRootSessionHistory() { |
12140 | RefPtr<ChildSHistory> childSHistory = |
12141 | mBrowsingContext->Top()->GetChildSessionHistory(); |
12142 | return childSHistory.forget(); |
12143 | } |
12144 | |
12145 | nsresult nsDocShell::GetHttpChannel(nsIChannel* aChannel, |
12146 | nsIHttpChannel** aReturn) { |
12147 | 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" , 12147); return NS_ERROR_INVALID_POINTER; } } while (false); |
12148 | if (!aChannel) { |
12149 | return NS_ERROR_FAILURE; |
12150 | } |
12151 | |
12152 | nsCOMPtr<nsIMultiPartChannel> multiPartChannel(do_QueryInterface(aChannel)); |
12153 | if (multiPartChannel) { |
12154 | nsCOMPtr<nsIChannel> baseChannel; |
12155 | multiPartChannel->GetBaseChannel(getter_AddRefs(baseChannel)); |
12156 | nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(baseChannel)); |
12157 | *aReturn = httpChannel; |
12158 | NS_IF_ADDREF(*aReturn)ns_if_addref(*aReturn); |
12159 | } |
12160 | return NS_OK; |
12161 | } |
12162 | |
12163 | bool nsDocShell::ShouldDiscardLayoutState(nsIHttpChannel* aChannel) { |
12164 | // By default layout State will be saved. |
12165 | if (!aChannel) { |
12166 | return false; |
12167 | } |
12168 | |
12169 | // figure out if SH should be saving layout state |
12170 | bool noStore = false; |
12171 | Unused << aChannel->IsNoStoreResponse(&noStore); |
12172 | return noStore; |
12173 | } |
12174 | |
12175 | NS_IMETHODIMPnsresult |
12176 | nsDocShell::GetEditor(nsIEditor** aEditor) { |
12177 | 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" , 12177); return NS_ERROR_INVALID_POINTER; } } while (false); |
12178 | RefPtr<HTMLEditor> htmlEditor = GetHTMLEditorInternal(); |
12179 | htmlEditor.forget(aEditor); |
12180 | return NS_OK; |
12181 | } |
12182 | |
12183 | NS_IMETHODIMPnsresult |
12184 | nsDocShell::SetEditor(nsIEditor* aEditor) { |
12185 | HTMLEditor* htmlEditor = aEditor ? aEditor->GetAsHTMLEditor() : nullptr; |
12186 | // If TextEditor comes, throw an error. |
12187 | if (aEditor && !htmlEditor) { |
12188 | return NS_ERROR_INVALID_ARG; |
12189 | } |
12190 | return SetHTMLEditorInternal(htmlEditor); |
12191 | } |
12192 | |
12193 | HTMLEditor* nsDocShell::GetHTMLEditorInternal() { |
12194 | return mEditorData ? mEditorData->GetHTMLEditor() : nullptr; |
12195 | } |
12196 | |
12197 | nsresult nsDocShell::SetHTMLEditorInternal(HTMLEditor* aHTMLEditor) { |
12198 | if (!aHTMLEditor && !mEditorData) { |
12199 | return NS_OK; |
12200 | } |
12201 | |
12202 | nsresult rv = EnsureEditorData(); |
12203 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
12204 | return rv; |
12205 | } |
12206 | |
12207 | return mEditorData->SetHTMLEditor(aHTMLEditor); |
12208 | } |
12209 | |
12210 | NS_IMETHODIMPnsresult |
12211 | nsDocShell::GetEditable(bool* aEditable) { |
12212 | 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" , 12212); return NS_ERROR_INVALID_POINTER; } } while (false); |
12213 | *aEditable = mEditorData && mEditorData->GetEditable(); |
12214 | return NS_OK; |
12215 | } |
12216 | |
12217 | NS_IMETHODIMPnsresult |
12218 | nsDocShell::GetHasEditingSession(bool* aHasEditingSession) { |
12219 | 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" , 12219); return NS_ERROR_INVALID_POINTER; } } while (false); |
12220 | |
12221 | if (mEditorData) { |
12222 | *aHasEditingSession = !!mEditorData->GetEditingSession(); |
12223 | } else { |
12224 | *aHasEditingSession = false; |
12225 | } |
12226 | |
12227 | return NS_OK; |
12228 | } |
12229 | |
12230 | NS_IMETHODIMPnsresult |
12231 | nsDocShell::MakeEditable(bool aInWaitForUriLoad) { |
12232 | nsresult rv = EnsureEditorData(); |
12233 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
12234 | return rv; |
12235 | } |
12236 | |
12237 | return mEditorData->MakeEditable(aInWaitForUriLoad); |
12238 | } |
12239 | |
12240 | /* static */ bool nsDocShell::ShouldAddURIVisit(nsIChannel* aChannel) { |
12241 | bool needToAddURIVisit = true; |
12242 | nsCOMPtr<nsIPropertyBag2> props(do_QueryInterface(aChannel)); |
12243 | if (props) { |
12244 | mozilla::Unused << props->GetPropertyAsBool( |
12245 | u"docshell.needToAddURIVisit"_ns, &needToAddURIVisit); |
12246 | } |
12247 | |
12248 | return needToAddURIVisit; |
12249 | } |
12250 | |
12251 | /* static */ void nsDocShell::ExtractLastVisit( |
12252 | nsIChannel* aChannel, nsIURI** aURI, uint32_t* aChannelRedirectFlags) { |
12253 | nsCOMPtr<nsIPropertyBag2> props(do_QueryInterface(aChannel)); |
12254 | if (!props) { |
12255 | return; |
12256 | } |
12257 | |
12258 | nsresult rv; |
12259 | nsCOMPtr<nsIURI> uri(do_GetProperty(props, u"docshell.previousURI"_ns, &rv)); |
12260 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) { |
12261 | uri.forget(aURI); |
12262 | |
12263 | rv = props->GetPropertyAsUint32(u"docshell.previousFlags"_ns, |
12264 | aChannelRedirectFlags); |
12265 | |
12266 | 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" , 12268); } } while (false) |
12267 | 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" , 12268); } } while (false) |
12268 | "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" , 12268); } } while (false); |
12269 | |
12270 | } else { |
12271 | // There is no last visit for this channel, so this must be the first |
12272 | // link. Link the visit to the referrer of this request, if any. |
12273 | // Treat referrer as null if there is an error getting it. |
12274 | NS_GetReferrerFromChannel(aChannel, aURI); |
12275 | } |
12276 | } |
12277 | |
12278 | void nsDocShell::SaveLastVisit(nsIChannel* aChannel, nsIURI* aURI, |
12279 | uint32_t aChannelRedirectFlags) { |
12280 | nsCOMPtr<nsIWritablePropertyBag2> props(do_QueryInterface(aChannel)); |
12281 | if (!props || !aURI) { |
12282 | return; |
12283 | } |
12284 | |
12285 | props->SetPropertyAsInterface(u"docshell.previousURI"_ns, aURI); |
12286 | props->SetPropertyAsUint32(u"docshell.previousFlags"_ns, |
12287 | aChannelRedirectFlags); |
12288 | } |
12289 | |
12290 | /* static */ void nsDocShell::InternalAddURIVisit( |
12291 | nsIURI* aURI, nsIURI* aPreviousURI, uint32_t aChannelRedirectFlags, |
12292 | uint32_t aResponseStatus, BrowsingContext* aBrowsingContext, |
12293 | nsIWidget* aWidget, uint32_t aLoadType, bool aWasUpgraded) { |
12294 | 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" , 12294); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aURI" ") (" "Visited URI is null!" ")"); do { *((volatile int*)__null) = 12294; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
12295 | 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" , 12296); 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) = 12296; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
12296 | "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" , 12296); 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) = 12296; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
12297 | |
12298 | bool usePrivateBrowsing = false; |
12299 | aBrowsingContext->GetUsePrivateBrowsing(&usePrivateBrowsing); |
12300 | |
12301 | // Only content-type docshells save URI visits. Also don't do |
12302 | // anything here if we're not supposed to use global history. |
12303 | if (!aBrowsingContext->IsContent() || |
12304 | !aBrowsingContext->GetUseGlobalHistory() || usePrivateBrowsing) { |
12305 | return; |
12306 | } |
12307 | |
12308 | nsCOMPtr<IHistory> history = components::History::Service(); |
12309 | |
12310 | if (history) { |
12311 | uint32_t visitURIFlags = 0; |
12312 | |
12313 | if (aBrowsingContext->IsTop()) { |
12314 | visitURIFlags |= IHistory::TOP_LEVEL; |
12315 | } |
12316 | |
12317 | if (aChannelRedirectFlags & nsIChannelEventSink::REDIRECT_TEMPORARY) { |
12318 | visitURIFlags |= IHistory::REDIRECT_TEMPORARY; |
12319 | } else if (aChannelRedirectFlags & |
12320 | nsIChannelEventSink::REDIRECT_PERMANENT) { |
12321 | visitURIFlags |= IHistory::REDIRECT_PERMANENT; |
12322 | } else { |
12323 | 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" , 12325); 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) = 12325; __attribute__((nomerge)) ::abort (); } while (false); } } while (false) |
12324 | "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" , 12325); 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) = 12325; __attribute__((nomerge)) ::abort (); } while (false); } } while (false) |
12325 | "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" , 12325); 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) = 12325; __attribute__((nomerge)) ::abort (); } while (false); } } while (false); |
12326 | } |
12327 | |
12328 | if (aResponseStatus >= 300 && aResponseStatus < 400) { |
12329 | visitURIFlags |= IHistory::REDIRECT_SOURCE; |
12330 | if (aResponseStatus == 301 || aResponseStatus == 308) { |
12331 | visitURIFlags |= IHistory::REDIRECT_SOURCE_PERMANENT; |
12332 | } |
12333 | } |
12334 | // Errors 400-501 and 505 are considered unrecoverable, in the sense a |
12335 | // simple retry attempt by the user is unlikely to solve them. |
12336 | // 408 is special cased, since may actually indicate a temporary |
12337 | // connection problem. |
12338 | else if (aResponseStatus != 408 && |
12339 | ((aResponseStatus >= 400 && aResponseStatus <= 501) || |
12340 | aResponseStatus == 505)) { |
12341 | visitURIFlags |= IHistory::UNRECOVERABLE_ERROR; |
12342 | } |
12343 | |
12344 | if (aWasUpgraded) { |
12345 | visitURIFlags |= |
12346 | IHistory::REDIRECT_SOURCE | IHistory::REDIRECT_SOURCE_UPGRADED; |
12347 | } |
12348 | |
12349 | mozilla::Unused << history->VisitURI(aWidget, aURI, aPreviousURI, |
12350 | visitURIFlags, |
12351 | aBrowsingContext->BrowserId()); |
12352 | } |
12353 | } |
12354 | |
12355 | void nsDocShell::AddURIVisit(nsIURI* aURI, nsIURI* aPreviousURI, |
12356 | uint32_t aChannelRedirectFlags, |
12357 | uint32_t aResponseStatus) { |
12358 | nsPIDOMWindowOuter* outer = GetWindow(); |
12359 | nsCOMPtr<nsIWidget> widget = widget::WidgetUtils::DOMWindowToWidget(outer); |
12360 | |
12361 | InternalAddURIVisit(aURI, aPreviousURI, aChannelRedirectFlags, |
12362 | aResponseStatus, mBrowsingContext, widget, mLoadType, |
12363 | false); |
12364 | } |
12365 | |
12366 | //***************************************************************************** |
12367 | // nsDocShell: Helper Routines |
12368 | //***************************************************************************** |
12369 | |
12370 | NS_IMETHODIMPnsresult |
12371 | nsDocShell::SetLoadType(uint32_t aLoadType) { |
12372 | mLoadType = aLoadType; |
12373 | return NS_OK; |
12374 | } |
12375 | |
12376 | NS_IMETHODIMPnsresult |
12377 | nsDocShell::GetLoadType(uint32_t* aLoadType) { |
12378 | *aLoadType = mLoadType; |
12379 | return NS_OK; |
12380 | } |
12381 | |
12382 | nsresult nsDocShell::ConfirmRepost(bool* aRepost) { |
12383 | if (StaticPrefs::dom_confirm_repost_testing_always_accept()) { |
12384 | *aRepost = true; |
12385 | return NS_OK; |
12386 | } |
12387 | |
12388 | nsCOMPtr<nsIPromptCollection> prompter = |
12389 | do_GetService("@mozilla.org/embedcomp/prompt-collection;1"); |
12390 | if (!prompter) { |
12391 | return NS_ERROR_NOT_AVAILABLE; |
12392 | } |
12393 | |
12394 | return prompter->ConfirmRepost(mBrowsingContext, aRepost); |
12395 | } |
12396 | |
12397 | nsresult nsDocShell::GetPromptAndStringBundle(nsIPrompt** aPrompt, |
12398 | nsIStringBundle** aStringBundle) { |
12399 | 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" , 12400); return NS_ERROR_FAILURE; } } while (false) |
12400 | 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" , 12400); return NS_ERROR_FAILURE; } } while (false); |
12401 | |
12402 | nsCOMPtr<nsIStringBundleService> stringBundleService = |
12403 | mozilla::components::StringBundle::Service(); |
12404 | 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" , 12404); return NS_ERROR_FAILURE; } } while (false); |
12405 | |
12406 | 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" , 12408); return NS_ERROR_FAILURE; } } while (false) |
12407 | 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" , 12408); return NS_ERROR_FAILURE; } } while (false) |
12408 | 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" , 12408); return NS_ERROR_FAILURE; } } while (false); |
12409 | |
12410 | return NS_OK; |
12411 | } |
12412 | |
12413 | ScrollContainerFrame* nsDocShell::GetRootScrollContainerFrame() { |
12414 | PresShell* presShell = GetPresShell(); |
12415 | 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" , 12415); return nullptr; } } while (false); |
12416 | |
12417 | return presShell->GetRootScrollContainerFrame(); |
12418 | } |
12419 | |
12420 | nsresult nsDocShell::EnsureScriptEnvironment() { |
12421 | if (mScriptGlobal) { |
12422 | return NS_OK; |
12423 | } |
12424 | |
12425 | if (mIsBeingDestroyed) { |
12426 | return NS_ERROR_NOT_AVAILABLE; |
12427 | } |
12428 | |
12429 | #ifdef DEBUG1 |
12430 | 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" , 12432); MOZ_PretendNoReturn(); } } while (0) |
12431 | "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" , 12432); MOZ_PretendNoReturn(); } } while (0) |
12432 | "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" , 12432); MOZ_PretendNoReturn(); } } while (0); |
12433 | |
12434 | // Yeah, this isn't re-entrant safe, but that's ok since if we |
12435 | // re-enter this method, we'll infinitely loop... |
12436 | AutoRestore<bool> boolSetter(mInEnsureScriptEnv); |
12437 | mInEnsureScriptEnv = true; |
12438 | #endif |
12439 | |
12440 | nsCOMPtr<nsIWebBrowserChrome> browserChrome(do_GetInterface(mTreeOwner)); |
12441 | 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" , 12441); return NS_ERROR_NOT_AVAILABLE; } } while (false); |
12442 | |
12443 | uint32_t chromeFlags; |
12444 | browserChrome->GetChromeFlags(&chromeFlags); |
12445 | |
12446 | // If our window is modal and we're not opened as chrome, make |
12447 | // this window a modal content window. |
12448 | mScriptGlobal = nsGlobalWindowOuter::Create(this, mItemType == typeChrome); |
12449 | 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" , 12449); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mScriptGlobal" ")"); do { *((volatile int*)__null) = 12449; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
12450 | |
12451 | // Ensure the script object is set up to run script. |
12452 | return mScriptGlobal->EnsureScriptEnvironment(); |
12453 | } |
12454 | |
12455 | nsresult nsDocShell::EnsureEditorData() { |
12456 | 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" , 12456); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mIsBeingDestroyed" ")"); do { *((volatile int*)__null) = 12456; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
12457 | |
12458 | bool openDocHasDetachedEditor = mOSHE && mOSHE->HasDetachedEditor(); |
12459 | if (!mEditorData && !mIsBeingDestroyed && !openDocHasDetachedEditor) { |
12460 | // We shouldn't recreate the editor data if it already exists, or |
12461 | // we're shutting down, or we already have a detached editor data |
12462 | // stored in the session history. We should only have one editordata |
12463 | // per docshell. |
12464 | mEditorData = MakeUnique<nsDocShellEditorData>(this); |
12465 | } |
12466 | |
12467 | return mEditorData ? NS_OK : NS_ERROR_NOT_AVAILABLE; |
12468 | } |
12469 | |
12470 | nsresult nsDocShell::EnsureFind() { |
12471 | if (!mFind) { |
12472 | mFind = new nsWebBrowserFind(); |
12473 | } |
12474 | |
12475 | // we promise that the nsIWebBrowserFind that we return has been set |
12476 | // up to point to the focused, or content window, so we have to |
12477 | // set that up each time. |
12478 | |
12479 | nsIScriptGlobalObject* scriptGO = GetScriptGlobalObject(); |
12480 | 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" , 12480); return NS_ERROR_UNEXPECTED; } } while (false); |
12481 | |
12482 | // default to our window |
12483 | nsCOMPtr<nsPIDOMWindowOuter> ourWindow = do_QueryInterface(scriptGO); |
12484 | nsCOMPtr<nsPIDOMWindowOuter> windowToSearch; |
12485 | nsFocusManager::GetFocusedDescendant(ourWindow, |
12486 | nsFocusManager::eIncludeAllDescendants, |
12487 | getter_AddRefs(windowToSearch)); |
12488 | |
12489 | nsCOMPtr<nsIWebBrowserFindInFrames> findInFrames = do_QueryInterface(mFind); |
12490 | if (!findInFrames) { |
12491 | return NS_ERROR_NO_INTERFACE; |
12492 | } |
12493 | |
12494 | nsresult rv = findInFrames->SetRootSearchFrame(ourWindow); |
12495 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
12496 | return rv; |
12497 | } |
12498 | rv = findInFrames->SetCurrentSearchFrame(windowToSearch); |
12499 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
12500 | return rv; |
12501 | } |
12502 | |
12503 | return NS_OK; |
12504 | } |
12505 | |
12506 | NS_IMETHODIMPnsresult |
12507 | nsDocShell::IsBeingDestroyed(bool* aDoomed) { |
12508 | 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" , 12508); return NS_ERROR_INVALID_ARG; } } while (false); |
12509 | *aDoomed = mIsBeingDestroyed; |
12510 | return NS_OK; |
12511 | } |
12512 | |
12513 | NS_IMETHODIMPnsresult |
12514 | nsDocShell::GetIsExecutingOnLoadHandler(bool* aResult) { |
12515 | 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" , 12515); return NS_ERROR_INVALID_ARG; } } while (false); |
12516 | *aResult = mIsExecutingOnLoadHandler; |
12517 | return NS_OK; |
12518 | } |
12519 | |
12520 | NS_IMETHODIMPnsresult |
12521 | nsDocShell::GetLayoutHistoryState(nsILayoutHistoryState** aLayoutHistoryState) { |
12522 | nsCOMPtr<nsILayoutHistoryState> state; |
12523 | if (mozilla::SessionHistoryInParent()) { |
12524 | if (mActiveEntry) { |
12525 | state = mActiveEntry->GetLayoutHistoryState(); |
12526 | } |
12527 | } else { |
12528 | if (mOSHE) { |
12529 | state = mOSHE->GetLayoutHistoryState(); |
12530 | } |
12531 | } |
12532 | state.forget(aLayoutHistoryState); |
12533 | return NS_OK; |
12534 | } |
12535 | |
12536 | NS_IMETHODIMPnsresult |
12537 | nsDocShell::SetLayoutHistoryState(nsILayoutHistoryState* aLayoutHistoryState) { |
12538 | if (mOSHE) { |
12539 | mOSHE->SetLayoutHistoryState(aLayoutHistoryState); |
12540 | } |
12541 | if (mActiveEntry) { |
12542 | mActiveEntry->SetLayoutHistoryState(aLayoutHistoryState); |
12543 | } |
12544 | return NS_OK; |
12545 | } |
12546 | |
12547 | nsDocShell::InterfaceRequestorProxy::InterfaceRequestorProxy( |
12548 | nsIInterfaceRequestor* aRequestor) { |
12549 | if (aRequestor) { |
12550 | mWeakPtr = do_GetWeakReference(aRequestor); |
12551 | } |
12552 | } |
12553 | |
12554 | nsDocShell::InterfaceRequestorProxy::~InterfaceRequestorProxy() { |
12555 | mWeakPtr = nullptr; |
12556 | } |
12557 | |
12558 | 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" , 12558); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0" ") (" "illegal refcnt" ")"); do { *((volatile int*)__null) = 12558; __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" , 12558); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsDocShell::InterfaceRequestorProxy\" != nullptr" ") (" "Must specify a name" ")"); do { *((volatile int*)__null ) = 12558; __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" , 12558); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0" ") (" "dup release" ")"); do { *((volatile int*)__null) = 12558 ; __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" , 12558); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsDocShell::InterfaceRequestorProxy\" != nullptr" ") (" "Must specify a name" ")"); do { *((volatile int*)__null ) = 12558; __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" , 12558); 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; } |
12559 | |
12560 | NS_IMETHODIMPnsresult |
12561 | nsDocShell::InterfaceRequestorProxy::GetInterface(const nsIID& aIID, |
12562 | void** aSink) { |
12563 | 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" , 12563); return NS_ERROR_INVALID_POINTER; } } while (false); |
12564 | nsCOMPtr<nsIInterfaceRequestor> ifReq = do_QueryReferent(mWeakPtr); |
12565 | if (ifReq) { |
12566 | return ifReq->GetInterface(aIID, aSink); |
12567 | } |
12568 | *aSink = nullptr; |
12569 | return NS_NOINTERFACE; |
12570 | } |
12571 | |
12572 | //***************************************************************************** |
12573 | // nsDocShell::nsIAuthPromptProvider |
12574 | //***************************************************************************** |
12575 | |
12576 | NS_IMETHODIMPnsresult |
12577 | nsDocShell::GetAuthPrompt(uint32_t aPromptReason, const nsIID& aIID, |
12578 | void** aResult) { |
12579 | // a priority prompt request will override a false mAllowAuth setting |
12580 | bool priorityPrompt = (aPromptReason == PROMPT_PROXY); |
12581 | |
12582 | if (!mAllowAuth && !priorityPrompt) { |
12583 | return NS_ERROR_NOT_AVAILABLE; |
12584 | } |
12585 | |
12586 | // we're either allowing auth, or it's a proxy request |
12587 | nsresult rv; |
12588 | nsCOMPtr<nsIPromptFactory> wwatch = |
12589 | do_GetService(NS_WINDOWWATCHER_CONTRACTID"@mozilla.org/embedcomp/window-watcher;1", &rv); |
12590 | 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" , 12590); return rv; } } while (false); |
12591 | |
12592 | rv = EnsureScriptEnvironment(); |
12593 | 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" , 12593); return rv; } } while (false); |
12594 | |
12595 | // Get the an auth prompter for our window so that the parenting |
12596 | // of the dialogs works as it should when using tabs. |
12597 | |
12598 | return wwatch->GetPrompt(mScriptGlobal, aIID, |
12599 | reinterpret_cast<void**>(aResult)); |
12600 | } |
12601 | |
12602 | //***************************************************************************** |
12603 | // nsDocShell::nsILoadContext |
12604 | //***************************************************************************** |
12605 | |
12606 | NS_IMETHODIMPnsresult |
12607 | nsDocShell::GetAssociatedWindow(mozIDOMWindowProxy** aWindow) { |
12608 | CallGetInterface(this, aWindow); |
12609 | return NS_OK; |
12610 | } |
12611 | |
12612 | NS_IMETHODIMPnsresult |
12613 | nsDocShell::GetTopWindow(mozIDOMWindowProxy** aWindow) { |
12614 | return mBrowsingContext->GetTopWindow(aWindow); |
12615 | } |
12616 | |
12617 | NS_IMETHODIMPnsresult |
12618 | nsDocShell::GetTopFrameElement(Element** aElement) { |
12619 | return mBrowsingContext->GetTopFrameElement(aElement); |
12620 | } |
12621 | |
12622 | NS_IMETHODIMPnsresult |
12623 | nsDocShell::GetUseTrackingProtection(bool* aUseTrackingProtection) { |
12624 | return mBrowsingContext->GetUseTrackingProtection(aUseTrackingProtection); |
12625 | } |
12626 | |
12627 | NS_IMETHODIMPnsresult |
12628 | nsDocShell::SetUseTrackingProtection(bool aUseTrackingProtection) { |
12629 | return mBrowsingContext->SetUseTrackingProtection(aUseTrackingProtection); |
12630 | } |
12631 | |
12632 | NS_IMETHODIMPnsresult |
12633 | nsDocShell::GetIsContent(bool* aIsContent) { |
12634 | *aIsContent = (mItemType == typeContent); |
12635 | return NS_OK; |
12636 | } |
12637 | |
12638 | bool nsDocShell::IsOKToLoadURI(nsIURI* aURI) { |
12639 | 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" , 12639); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aURI" ") (" "Must have a URI!" ")"); do { *((volatile int*)__null) = 12639 ; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
12640 | |
12641 | if (!mFiredUnloadEvent) { |
12642 | return true; |
12643 | } |
12644 | |
12645 | if (!mLoadingURI) { |
12646 | return false; |
12647 | } |
12648 | |
12649 | bool isPrivateWin = false; |
12650 | Document* doc = GetDocument(); |
12651 | if (doc) { |
12652 | isPrivateWin = |
12653 | doc->NodePrincipal()->OriginAttributesRef().IsPrivateBrowsing(); |
12654 | } |
12655 | |
12656 | nsCOMPtr<nsIScriptSecurityManager> secMan = |
12657 | do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID"@mozilla.org/scriptsecuritymanager;1"); |
12658 | return secMan && NS_SUCCEEDED(secMan->CheckSameOriginURI(((bool)(__builtin_expect(!!(!NS_FAILED_impl(secMan->CheckSameOriginURI ( aURI, mLoadingURI, false, isPrivateWin))), 1))) |
12659 | aURI, mLoadingURI, false, isPrivateWin))((bool)(__builtin_expect(!!(!NS_FAILED_impl(secMan->CheckSameOriginURI ( aURI, mLoadingURI, false, isPrivateWin))), 1))); |
12660 | } |
12661 | |
12662 | // |
12663 | // Routines for selection and clipboard |
12664 | // |
12665 | nsresult nsDocShell::GetControllerForCommand(const char* aCommand, |
12666 | nsIController** aResult) { |
12667 | 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" , 12667); return NS_ERROR_INVALID_POINTER; } } while (false); |
12668 | *aResult = nullptr; |
12669 | |
12670 | 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" , 12670); return NS_ERROR_FAILURE; } } while (false); |
12671 | |
12672 | nsCOMPtr<nsPIWindowRoot> root = mScriptGlobal->GetTopWindowRoot(); |
12673 | 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" , 12673); return NS_ERROR_FAILURE; } } while (false); |
12674 | |
12675 | return root->GetControllerForCommand(aCommand, false /* for any window */, |
12676 | aResult); |
12677 | } |
12678 | |
12679 | NS_IMETHODIMPnsresult |
12680 | nsDocShell::IsCommandEnabled(const char* aCommand, bool* aResult) { |
12681 | 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" , 12681); return NS_ERROR_INVALID_POINTER; } } while (false); |
12682 | *aResult = false; |
12683 | |
12684 | nsresult rv = NS_ERROR_FAILURE; |
12685 | |
12686 | nsCOMPtr<nsIController> controller; |
12687 | rv = GetControllerForCommand(aCommand, getter_AddRefs(controller)); |
12688 | if (controller) { |
12689 | rv = controller->IsCommandEnabled(aCommand, aResult); |
12690 | } |
12691 | |
12692 | return rv; |
12693 | } |
12694 | |
12695 | NS_IMETHODIMPnsresult |
12696 | nsDocShell::DoCommand(const char* aCommand) { |
12697 | nsresult rv = NS_ERROR_FAILURE; |
12698 | |
12699 | nsCOMPtr<nsIController> controller; |
12700 | rv = GetControllerForCommand(aCommand, getter_AddRefs(controller)); |
12701 | if (controller) { |
12702 | rv = controller->DoCommand(aCommand); |
12703 | } |
12704 | |
12705 | return rv; |
12706 | } |
12707 | |
12708 | NS_IMETHODIMPnsresult |
12709 | nsDocShell::DoCommandWithParams(const char* aCommand, |
12710 | nsICommandParams* aParams) { |
12711 | nsCOMPtr<nsIController> controller; |
12712 | nsresult rv = GetControllerForCommand(aCommand, getter_AddRefs(controller)); |
12713 | 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" , 12713)) { |
12714 | return rv; |
12715 | } |
12716 | |
12717 | nsCOMPtr<nsICommandController> commandController = |
12718 | do_QueryInterface(controller, &rv); |
12719 | 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" , 12719)) { |
12720 | return rv; |
12721 | } |
12722 | |
12723 | return commandController->DoCommandWithParams(aCommand, aParams); |
12724 | } |
12725 | |
12726 | nsresult nsDocShell::EnsureCommandHandler() { |
12727 | if (!mCommandManager) { |
12728 | if (nsCOMPtr<nsPIDOMWindowOuter> domWindow = GetWindow()) { |
12729 | mCommandManager = new nsCommandManager(domWindow); |
12730 | } |
12731 | } |
12732 | return mCommandManager ? NS_OK : NS_ERROR_FAILURE; |
12733 | } |
12734 | |
12735 | // link handling |
12736 | |
12737 | class OnLinkClickEvent : public Runnable { |
12738 | public: |
12739 | OnLinkClickEvent(nsDocShell* aHandler, nsIContent* aContent, |
12740 | nsDocShellLoadState* aLoadState, bool aNoOpenerImplied, |
12741 | bool aIsTrusted, nsIPrincipal* aTriggeringPrincipal); |
12742 | |
12743 | NS_IMETHODvirtual nsresult Run() override { |
12744 | // We need to set up an AutoJSAPI here for the following reason: When we |
12745 | // do OnLinkClickSync we'll eventually end up in |
12746 | // nsGlobalWindow::OpenInternal which only does popup blocking if |
12747 | // !LegacyIsCallerChromeOrNativeCode(). So we need to fake things so that |
12748 | // we don't look like native code as far as LegacyIsCallerNativeCode() is |
12749 | // concerned. |
12750 | AutoJSAPI jsapi; |
12751 | if (mIsTrusted || jsapi.Init(mContent->OwnerDoc()->GetScopeObject())) { |
12752 | mHandler->OnLinkClickSync(mContent, mLoadState, mNoOpenerImplied, |
12753 | mTriggeringPrincipal); |
12754 | } |
12755 | return NS_OK; |
12756 | } |
12757 | |
12758 | private: |
12759 | RefPtr<nsDocShell> mHandler; |
12760 | nsCOMPtr<nsIContent> mContent; |
12761 | RefPtr<nsDocShellLoadState> mLoadState; |
12762 | nsCOMPtr<nsIPrincipal> mTriggeringPrincipal; |
12763 | bool mNoOpenerImplied; |
12764 | bool mIsTrusted; |
12765 | }; |
12766 | |
12767 | OnLinkClickEvent::OnLinkClickEvent(nsDocShell* aHandler, nsIContent* aContent, |
12768 | nsDocShellLoadState* aLoadState, |
12769 | bool aNoOpenerImplied, bool aIsTrusted, |
12770 | nsIPrincipal* aTriggeringPrincipal) |
12771 | : mozilla::Runnable("OnLinkClickEvent"), |
12772 | mHandler(aHandler), |
12773 | mContent(aContent), |
12774 | mLoadState(aLoadState), |
12775 | mTriggeringPrincipal(aTriggeringPrincipal), |
12776 | mNoOpenerImplied(aNoOpenerImplied), |
12777 | mIsTrusted(aIsTrusted) {} |
12778 | |
12779 | nsresult nsDocShell::OnLinkClick( |
12780 | nsIContent* aContent, nsIURI* aURI, const nsAString& aTargetSpec, |
12781 | const nsAString& aFileName, nsIInputStream* aPostDataStream, |
12782 | nsIInputStream* aHeadersDataStream, bool aIsUserTriggered, bool aIsTrusted, |
12783 | nsIPrincipal* aTriggeringPrincipal, nsIContentSecurityPolicy* aCsp) { |
12784 | #ifndef ANDROID |
12785 | 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" , 12785); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aTriggeringPrincipal" ") (" "Need a valid triggeringPrincipal" ")"); do { *((volatile int*)__null) = 12785; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
12786 | #endif |
12787 | 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" , 12787); MOZ_PretendNoReturn(); } } while (0); |
12788 | |
12789 | if (!IsNavigationAllowed() || !IsOKToLoadURI(aURI)) { |
12790 | return NS_OK; |
12791 | } |
12792 | |
12793 | // On history navigation through Back/Forward buttons, don't execute |
12794 | // automatic JavaScript redirection such as |anchorElement.click()| or |
12795 | // |formElement.submit()|. |
12796 | // |
12797 | // XXX |formElement.submit()| bypasses this checkpoint because it calls |
12798 | // nsDocShell::OnLinkClickSync(...) instead. |
12799 | if (ShouldBlockLoadingForBackButton()) { |
12800 | return NS_OK; |
12801 | } |
12802 | |
12803 | if (aContent->IsEditable()) { |
12804 | return NS_OK; |
12805 | } |
12806 | |
12807 | Document* ownerDoc = aContent->OwnerDoc(); |
12808 | if (nsContentUtils::IsExternalProtocol(aURI)) { |
12809 | ownerDoc->EnsureNotEnteringAndExitFullscreen(); |
12810 | } |
12811 | |
12812 | bool noOpenerImplied = false; |
12813 | nsAutoString target(aTargetSpec); |
12814 | if (aFileName.IsVoid() && |
12815 | ShouldOpenInBlankTarget(aTargetSpec, aURI, aContent, aIsUserTriggered)) { |
12816 | target = u"_blank"; |
12817 | if (!aTargetSpec.Equals(target)) { |
12818 | noOpenerImplied = true; |
12819 | } |
12820 | } |
12821 | |
12822 | RefPtr<nsDocShellLoadState> loadState = new nsDocShellLoadState(aURI); |
12823 | loadState->SetTarget(target); |
12824 | loadState->SetFileName(aFileName); |
12825 | loadState->SetPostDataStream(aPostDataStream); |
12826 | loadState->SetHeadersStream(aHeadersDataStream); |
12827 | loadState->SetFirstParty(true); |
12828 | loadState->SetTriggeringPrincipal( |
12829 | aTriggeringPrincipal ? aTriggeringPrincipal : aContent->NodePrincipal()); |
12830 | loadState->SetPrincipalToInherit(aContent->NodePrincipal()); |
12831 | loadState->SetCsp(aCsp ? aCsp : aContent->GetCsp()); |
12832 | loadState->SetAllowFocusMove(UserActivation::IsHandlingUserInput()); |
12833 | |
12834 | const bool hasValidUserGestureActivation = |
12835 | ownerDoc->HasValidTransientUserGestureActivation(); |
12836 | loadState->SetHasValidUserGestureActivation(hasValidUserGestureActivation); |
12837 | loadState->SetTextDirectiveUserActivation( |
12838 | ownerDoc->ConsumeTextDirectiveUserActivation() || |
12839 | hasValidUserGestureActivation); |
12840 | |
12841 | nsCOMPtr<nsIRunnable> ev = |
12842 | new OnLinkClickEvent(this, aContent, loadState, noOpenerImplied, |
12843 | aIsTrusted, aTriggeringPrincipal); |
12844 | return Dispatch(ev.forget()); |
12845 | } |
12846 | |
12847 | bool nsDocShell::ShouldOpenInBlankTarget(const nsAString& aOriginalTarget, |
12848 | nsIURI* aLinkURI, nsIContent* aContent, |
12849 | bool aIsUserTriggered) { |
12850 | if (net::SchemeIsJavascript(aLinkURI)) { |
12851 | return false; |
12852 | } |
12853 | |
12854 | // External links from within app tabs should always open in new tabs |
12855 | // instead of replacing the app tab's page (Bug 575561) |
12856 | // nsIURI.host can throw for non-nsStandardURL nsIURIs. If we fail to |
12857 | // get either host, just return false to use the original target. |
12858 | nsAutoCString linkHost; |
12859 | if (NS_FAILED(aLinkURI->GetHost(linkHost))((bool)(__builtin_expect(!!(NS_FAILED_impl(aLinkURI->GetHost (linkHost))), 0)))) { |
12860 | return false; |
12861 | } |
12862 | |
12863 | // The targetTopLevelLinkClicksToBlank property on BrowsingContext allows |
12864 | // privileged code to change the default targeting behaviour. In particular, |
12865 | // if a user-initiated link click for the (or targetting the) top-level frame |
12866 | // is detected, we default the target to "_blank" to give it a new |
12867 | // top-level BrowsingContext. |
12868 | if (mBrowsingContext->TargetTopLevelLinkClicksToBlank() && aIsUserTriggered && |
12869 | ((aOriginalTarget.IsEmpty() && mBrowsingContext->IsTop()) || |
12870 | aOriginalTarget == u"_top"_ns)) { |
12871 | return true; |
12872 | } |
12873 | |
12874 | // Don't modify non-default targets. |
12875 | if (!aOriginalTarget.IsEmpty()) { |
12876 | return false; |
12877 | } |
12878 | |
12879 | // Only check targets that are in extension panels or app tabs. |
12880 | // (isAppTab will be false for app tab subframes). |
12881 | nsString mmGroup = mBrowsingContext->Top()->GetMessageManagerGroup(); |
12882 | if (!mmGroup.EqualsLiteral("webext-browsers") && |
12883 | !mBrowsingContext->IsAppTab()) { |
12884 | return false; |
12885 | } |
12886 | |
12887 | nsCOMPtr<nsIURI> docURI = aContent->OwnerDoc()->GetDocumentURIObject(); |
12888 | if (!docURI) { |
12889 | return false; |
12890 | } |
12891 | |
12892 | nsAutoCString docHost; |
12893 | if (NS_FAILED(docURI->GetHost(docHost))((bool)(__builtin_expect(!!(NS_FAILED_impl(docURI->GetHost (docHost))), 0)))) { |
12894 | return false; |
12895 | } |
12896 | |
12897 | if (linkHost.Equals(docHost)) { |
12898 | return false; |
12899 | } |
12900 | |
12901 | // Special case: ignore "www" prefix if it is part of host string |
12902 | return linkHost.Length() < docHost.Length() |
12903 | ? !docHost.Equals("www."_ns + linkHost) |
12904 | : !linkHost.Equals("www."_ns + docHost); |
12905 | } |
12906 | |
12907 | static bool ElementCanHaveNoopener(nsIContent* aContent) { |
12908 | // Make sure we are dealing with either an <A>, <AREA>, or <FORM> element in |
12909 | // the HTML, XHTML, or SVG namespace. |
12910 | return aContent->IsAnyOfHTMLElements(nsGkAtoms::a, nsGkAtoms::area, |
12911 | nsGkAtoms::form) || |
12912 | aContent->IsSVGElement(nsGkAtoms::a); |
12913 | } |
12914 | |
12915 | nsresult nsDocShell::OnLinkClickSync(nsIContent* aContent, |
12916 | nsDocShellLoadState* aLoadState, |
12917 | bool aNoOpenerImplied, |
12918 | nsIPrincipal* aTriggeringPrincipal) { |
12919 | if (!IsNavigationAllowed() || !IsOKToLoadURI(aLoadState->URI())) { |
12920 | return NS_OK; |
12921 | } |
12922 | |
12923 | // XXX When the linking node was HTMLFormElement, it is synchronous event. |
12924 | // That is, the caller of this method is not |OnLinkClickEvent::Run()| |
12925 | // but |HTMLFormElement::SubmitSubmission(...)|. |
12926 | if (aContent->IsHTMLElement(nsGkAtoms::form) && |
12927 | ShouldBlockLoadingForBackButton()) { |
12928 | return NS_OK; |
12929 | } |
12930 | |
12931 | if (aContent->IsEditable()) { |
12932 | return NS_OK; |
12933 | } |
12934 | |
12935 | // if the triggeringPrincipal is not passed explicitly, then we |
12936 | // fall back to using doc->NodePrincipal() as the triggeringPrincipal. |
12937 | nsCOMPtr<nsIPrincipal> triggeringPrincipal = |
12938 | aTriggeringPrincipal ? aTriggeringPrincipal : aContent->NodePrincipal(); |
12939 | |
12940 | { |
12941 | // defer to an external protocol handler if necessary... |
12942 | nsCOMPtr<nsIExternalProtocolService> extProtService = |
12943 | do_GetService(NS_EXTERNALPROTOCOLSERVICE_CONTRACTID"@mozilla.org/uriloader/external-protocol-service;1"); |
12944 | if (extProtService) { |
12945 | nsAutoCString scheme; |
12946 | aLoadState->URI()->GetScheme(scheme); |
12947 | if (!scheme.IsEmpty()) { |
12948 | // if the URL scheme does not correspond to an exposed protocol, then |
12949 | // we need to hand this link click over to the external protocol |
12950 | // handler. |
12951 | bool isExposed; |
12952 | nsresult rv = |
12953 | extProtService->IsExposedProtocol(scheme.get(), &isExposed); |
12954 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && !isExposed) { |
12955 | return extProtService->LoadURI( |
12956 | aLoadState->URI(), triggeringPrincipal, nullptr, mBrowsingContext, |
12957 | /* aTriggeredExternally */ |
12958 | false, |
12959 | /* aHasValidUserGestureActivation */ |
12960 | aContent->OwnerDoc()->HasValidTransientUserGestureActivation()); |
12961 | } |
12962 | } |
12963 | } |
12964 | } |
12965 | uint32_t triggeringSandboxFlags = 0; |
12966 | uint64_t triggeringWindowId = 0; |
12967 | bool triggeringStorageAccess = false; |
12968 | if (mBrowsingContext) { |
12969 | triggeringSandboxFlags = aContent->OwnerDoc()->GetSandboxFlags(); |
12970 | triggeringWindowId = aContent->OwnerDoc()->InnerWindowID(); |
12971 | triggeringStorageAccess = aContent->OwnerDoc()->UsingStorageAccess(); |
12972 | } |
12973 | |
12974 | uint32_t flags = INTERNAL_LOAD_FLAGS_NONE; |
12975 | bool elementCanHaveNoopener = ElementCanHaveNoopener(aContent); |
12976 | bool triggeringPrincipalIsSystemPrincipal = |
12977 | aLoadState->TriggeringPrincipal()->IsSystemPrincipal(); |
12978 | if (elementCanHaveNoopener) { |
12979 | 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" , 12979); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aContent->IsHTMLElement() || aContent->IsSVGElement()" ")"); do { *((volatile int*)__null) = 12979; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
12980 | nsAutoString relString; |
12981 | aContent->AsElement()->GetAttr(nsGkAtoms::rel, relString); |
12982 | nsWhitespaceTokenizerTemplate<nsContentUtils::IsHTMLWhitespace> tok( |
12983 | relString); |
12984 | |
12985 | bool targetBlank = aLoadState->Target().LowerCaseEqualsLiteral("_blank"); |
12986 | bool explicitOpenerSet = false; |
12987 | |
12988 | // The opener behaviour follows a hierarchy, such that if a higher |
12989 | // priority behaviour is specified, it always takes priority. That |
12990 | // priority is currently: norefrerer > noopener > opener > default |
12991 | |
12992 | while (tok.hasMoreTokens()) { |
12993 | const nsAString& token = tok.nextToken(); |
12994 | if (token.LowerCaseEqualsLiteral("noreferrer")) { |
12995 | flags |= INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER | |
12996 | INTERNAL_LOAD_FLAGS_NO_OPENER; |
12997 | // noreferrer cannot be overwritten by a 'rel=opener'. |
12998 | explicitOpenerSet = true; |
12999 | break; |
13000 | } |
13001 | |
13002 | if (token.LowerCaseEqualsLiteral("noopener")) { |
13003 | flags |= INTERNAL_LOAD_FLAGS_NO_OPENER; |
13004 | explicitOpenerSet = true; |
13005 | } |
13006 | |
13007 | if (targetBlank && StaticPrefs::dom_targetBlankNoOpener_enabled() && |
13008 | token.LowerCaseEqualsLiteral("opener") && !explicitOpenerSet) { |
13009 | explicitOpenerSet = true; |
13010 | } |
13011 | } |
13012 | |
13013 | if (targetBlank && StaticPrefs::dom_targetBlankNoOpener_enabled() && |
13014 | !explicitOpenerSet && !triggeringPrincipalIsSystemPrincipal) { |
13015 | flags |= INTERNAL_LOAD_FLAGS_NO_OPENER; |
13016 | } |
13017 | |
13018 | if (aNoOpenerImplied) { |
13019 | flags |= INTERNAL_LOAD_FLAGS_NO_OPENER; |
13020 | } |
13021 | } |
13022 | |
13023 | // Get the owner document of the link that was clicked, this will be |
13024 | // the document that the link is in, or the last document that the |
13025 | // link was in. From that document, we'll get the URI to use as the |
13026 | // referrer, since the current URI in this docshell may be a |
13027 | // new document that we're in the process of loading. |
13028 | RefPtr<Document> referrerDoc = aContent->OwnerDoc(); |
13029 | |
13030 | // Now check that the referrerDoc's inner window is the current inner |
13031 | // window for mScriptGlobal. If it's not, then we don't want to |
13032 | // follow this link. |
13033 | nsPIDOMWindowInner* referrerInner = referrerDoc->GetInnerWindow(); |
13034 | if (!mScriptGlobal || !referrerInner || |
13035 | mScriptGlobal->GetCurrentInnerWindow() != referrerInner) { |
13036 | // We're no longer the current inner window |
13037 | return NS_OK; |
13038 | } |
13039 | |
13040 | // referrer could be null here in some odd cases, but that's ok, |
13041 | // we'll just load the link w/o sending a referrer in those cases. |
13042 | |
13043 | // If this is an anchor element, grab its type property to use as a hint |
13044 | nsAutoString typeHint; |
13045 | RefPtr<HTMLAnchorElement> anchor = HTMLAnchorElement::FromNode(aContent); |
13046 | if (anchor) { |
13047 | anchor->GetType(typeHint); |
13048 | NS_ConvertUTF16toUTF8 utf8Hint(typeHint); |
13049 | nsAutoCString type, dummy; |
13050 | NS_ParseRequestContentType(utf8Hint, type, dummy); |
13051 | CopyUTF8toUTF16(type, typeHint); |
13052 | } |
13053 | |
13054 | uint32_t loadType = LOAD_LINK; |
13055 | if (aLoadState->IsFormSubmission()) { |
13056 | if (aLoadState->Target().IsEmpty()) { |
13057 | // We set the right load type here for form submissions with an empty |
13058 | // target. Form submission with a non-empty target are handled in |
13059 | // nsDocShell::PerformRetargeting after we've selected the correct target |
13060 | // BC. |
13061 | loadType = GetLoadTypeForFormSubmission(GetBrowsingContext(), aLoadState); |
13062 | } |
13063 | } else { |
13064 | // Link click can be triggered inside an onload handler, and we don't want |
13065 | // to add history entry in this case. |
13066 | bool inOnLoadHandler = false; |
13067 | GetIsExecutingOnLoadHandler(&inOnLoadHandler); |
13068 | if (inOnLoadHandler) { |
13069 | loadType = LOAD_NORMAL_REPLACE; |
13070 | } |
13071 | } |
13072 | |
13073 | nsCOMPtr<nsIReferrerInfo> referrerInfo = |
13074 | elementCanHaveNoopener ? new ReferrerInfo(*aContent->AsElement()) |
13075 | : new ReferrerInfo(*referrerDoc); |
13076 | |
13077 | aLoadState->SetTriggeringSandboxFlags(triggeringSandboxFlags); |
13078 | aLoadState->SetTriggeringWindowId(triggeringWindowId); |
13079 | aLoadState->SetTriggeringStorageAccess(triggeringStorageAccess); |
13080 | aLoadState->SetReferrerInfo(referrerInfo); |
13081 | aLoadState->SetInternalLoadFlags(flags); |
13082 | aLoadState->SetTypeHint(NS_ConvertUTF16toUTF8(typeHint)); |
13083 | aLoadState->SetLoadType(loadType); |
13084 | aLoadState->SetSourceBrowsingContext(mBrowsingContext); |
13085 | |
13086 | nsresult rv = InternalLoad(aLoadState); |
13087 | |
13088 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) { |
13089 | nsPingListener::DispatchPings(this, aContent, aLoadState->URI(), |
13090 | referrerInfo); |
13091 | } |
13092 | |
13093 | return rv; |
13094 | } |
13095 | |
13096 | nsresult nsDocShell::OnOverLink(nsIContent* aContent, nsIURI* aURI, |
13097 | const nsAString& aTargetSpec) { |
13098 | if (aContent->IsEditable()) { |
13099 | return NS_OK; |
13100 | } |
13101 | |
13102 | nsresult rv = NS_ERROR_FAILURE; |
13103 | |
13104 | nsCOMPtr<nsIWebBrowserChrome> browserChrome = do_GetInterface(mTreeOwner); |
13105 | if (!browserChrome) { |
13106 | return rv; |
13107 | } |
13108 | |
13109 | nsCOMPtr<nsIURI> exposableURI = nsIOService::CreateExposableURI(aURI); |
13110 | nsAutoCString spec; |
13111 | rv = exposableURI->GetDisplaySpec(spec); |
13112 | 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" , 13112); return rv; } } while (false); |
13113 | |
13114 | NS_ConvertUTF8toUTF16 uStr(spec); |
13115 | |
13116 | PredictorPredict(aURI, mCurrentURI, nsINetworkPredictor::PREDICT_LINK, |
13117 | aContent->NodePrincipal()->OriginAttributesRef(), nullptr); |
13118 | |
13119 | rv = browserChrome->SetLinkStatus(uStr); |
13120 | return rv; |
13121 | } |
13122 | |
13123 | nsresult nsDocShell::OnLeaveLink() { |
13124 | nsCOMPtr<nsIWebBrowserChrome> browserChrome(do_GetInterface(mTreeOwner)); |
13125 | nsresult rv = NS_ERROR_FAILURE; |
13126 | |
13127 | if (browserChrome) { |
13128 | rv = browserChrome->SetLinkStatus(u""_ns); |
13129 | } |
13130 | return rv; |
13131 | } |
13132 | |
13133 | bool nsDocShell::ShouldBlockLoadingForBackButton() { |
13134 | if (!(mLoadType & LOAD_CMD_HISTORY) || |
13135 | UserActivation::IsHandlingUserInput() || |
13136 | !Preferences::GetBool("accessibility.blockjsredirection")) { |
13137 | return false; |
13138 | } |
13139 | |
13140 | bool canGoForward = false; |
13141 | GetCanGoForward(&canGoForward); |
13142 | return canGoForward; |
13143 | } |
13144 | |
13145 | //---------------------------------------------------------------------- |
13146 | // Web Shell Services API |
13147 | |
13148 | // This functions is only called when a new charset is detected in loading a |
13149 | // document. |
13150 | nsresult nsDocShell::CharsetChangeReloadDocument( |
13151 | mozilla::NotNull<const mozilla::Encoding*> aEncoding, int32_t aSource) { |
13152 | // XXX hack. keep the aCharset and aSource wait to pick it up |
13153 | nsCOMPtr<nsIDocumentViewer> viewer; |
13154 | 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" , 13154); return NS_ERROR_FAILURE; } } while (false); |
13155 | if (viewer) { |
13156 | int32_t source; |
13157 | Unused << viewer->GetReloadEncodingAndSource(&source); |
13158 | if (aSource > source) { |
13159 | viewer->SetReloadEncodingAndSource(aEncoding, aSource); |
13160 | if (eCharsetReloadRequested != mCharsetReloadState) { |
13161 | mCharsetReloadState = eCharsetReloadRequested; |
13162 | switch (mLoadType) { |
13163 | case LOAD_RELOAD_BYPASS_PROXY_AND_CACHE: |
13164 | return Reload(LOAD_FLAGS_CHARSET_CHANGE | LOAD_FLAGS_BYPASS_CACHE | |
13165 | LOAD_FLAGS_BYPASS_PROXY); |
13166 | case LOAD_RELOAD_BYPASS_CACHE: |
13167 | return Reload(LOAD_FLAGS_CHARSET_CHANGE | LOAD_FLAGS_BYPASS_CACHE); |
13168 | default: |
13169 | return Reload(LOAD_FLAGS_CHARSET_CHANGE); |
13170 | } |
13171 | } |
13172 | } |
13173 | } |
13174 | // return failure if this request is not accepted due to mCharsetReloadState |
13175 | return NS_ERROR_DOCSHELL_REQUEST_REJECTED; |
13176 | } |
13177 | |
13178 | nsresult nsDocShell::CharsetChangeStopDocumentLoad() { |
13179 | if (eCharsetReloadRequested != mCharsetReloadState) { |
13180 | Stop(nsIWebNavigation::STOP_ALL); |
13181 | return NS_OK; |
13182 | } |
13183 | // return failer if this request is not accepted due to mCharsetReloadState |
13184 | return NS_ERROR_DOCSHELL_REQUEST_REJECTED; |
13185 | } |
13186 | |
13187 | NS_IMETHODIMPnsresult nsDocShell::ExitPrintPreview() { |
13188 | #if NS_PRINT_PREVIEW1 |
13189 | nsCOMPtr<nsIWebBrowserPrint> viewer = do_QueryInterface(mDocumentViewer); |
13190 | return viewer->ExitPrintPreview(); |
13191 | #else |
13192 | return NS_OK; |
13193 | #endif |
13194 | } |
13195 | |
13196 | /* [infallible] */ |
13197 | NS_IMETHODIMPnsresult nsDocShell::GetIsTopLevelContentDocShell( |
13198 | bool* aIsTopLevelContentDocShell) { |
13199 | *aIsTopLevelContentDocShell = false; |
13200 | |
13201 | if (mItemType == typeContent) { |
13202 | *aIsTopLevelContentDocShell = mBrowsingContext->IsTopContent(); |
13203 | } |
13204 | |
13205 | return NS_OK; |
13206 | } |
13207 | |
13208 | // Implements nsILoadContext.originAttributes |
13209 | NS_IMETHODIMPnsresult |
13210 | nsDocShell::GetScriptableOriginAttributes(JSContext* aCx, |
13211 | JS::MutableHandle<JS::Value> aVal) { |
13212 | return mBrowsingContext->GetScriptableOriginAttributes(aCx, aVal); |
13213 | } |
13214 | |
13215 | // Implements nsIDocShell.GetOriginAttributes() |
13216 | NS_IMETHODIMPnsresult |
13217 | nsDocShell::GetOriginAttributes(JSContext* aCx, |
13218 | JS::MutableHandle<JS::Value> aVal) { |
13219 | return mBrowsingContext->GetScriptableOriginAttributes(aCx, aVal); |
13220 | } |
13221 | |
13222 | bool nsDocShell::ServiceWorkerAllowedToControlWindow(nsIPrincipal* aPrincipal, |
13223 | nsIURI* aURI) { |
13224 | 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" , 13224); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPrincipal" ")"); do { *((volatile int*)__null) = 13224; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
13225 | 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" , 13225); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aURI" ")") ; do { *((volatile int*)__null) = 13225; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
13226 | |
13227 | if (UsePrivateBrowsing() || mBrowsingContext->GetSandboxFlags()) { |
13228 | return false; |
13229 | } |
13230 | |
13231 | nsCOMPtr<nsIDocShellTreeItem> parent; |
13232 | GetInProcessSameTypeParent(getter_AddRefs(parent)); |
13233 | nsPIDOMWindowOuter* parentOuter = parent ? parent->GetWindow() : nullptr; |
13234 | nsPIDOMWindowInner* parentInner = |
13235 | parentOuter ? parentOuter->GetCurrentInnerWindow() : nullptr; |
13236 | |
13237 | StorageAccess storage = |
13238 | StorageAllowedForNewWindow(aPrincipal, aURI, parentInner); |
13239 | |
13240 | // If the partitioned service worker is enabled, service worker is allowed to |
13241 | // control the window if partition is enabled. |
13242 | if (StaticPrefs::privacy_partition_serviceWorkers() && parentInner) { |
13243 | RefPtr<Document> doc = parentInner->GetExtantDoc(); |
13244 | |
13245 | if (doc && StoragePartitioningEnabled(storage, doc->CookieJarSettings())) { |
13246 | return true; |
13247 | } |
13248 | } |
13249 | |
13250 | return storage == StorageAccess::eAllow; |
13251 | } |
13252 | |
13253 | nsresult nsDocShell::SetOriginAttributes(const OriginAttributes& aAttrs) { |
13254 | 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" , 13254); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mIsBeingDestroyed" ")"); do { *((volatile int*)__null) = 13254; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
13255 | return mBrowsingContext->SetOriginAttributes(aAttrs); |
13256 | } |
13257 | |
13258 | NS_IMETHODIMPnsresult |
13259 | nsDocShell::ResumeRedirectedLoad(uint64_t aIdentifier, int32_t aHistoryIndex) { |
13260 | RefPtr<nsDocShell> self = this; |
13261 | RefPtr<ChildProcessChannelListener> cpcl = |
13262 | ChildProcessChannelListener::GetSingleton(); |
13263 | |
13264 | // Call into InternalLoad with the pending channel when it is received. |
13265 | cpcl->RegisterCallback( |
13266 | aIdentifier, [self, aHistoryIndex]( |
13267 | nsDocShellLoadState* aLoadState, |
13268 | nsTArray<Endpoint<extensions::PStreamFilterParent>>&& |
13269 | aStreamFilterEndpoints, |
13270 | nsDOMNavigationTiming* aTiming) { |
13271 | 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" , 13271); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->GetPendingRedirectedChannel()" ")"); do { *((volatile int*)__null) = 13271; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
13272 | 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" , 13272)) { |
13273 | aLoadState->GetPendingRedirectedChannel()->CancelWithReason( |
13274 | NS_BINDING_ABORTED, "nsDocShell::mIsBeingDestroyed"_ns); |
13275 | return NS_BINDING_ABORTED; |
13276 | } |
13277 | |
13278 | self->mLoadType = aLoadState->LoadType(); |
13279 | nsCOMPtr<nsIURI> previousURI; |
13280 | uint32_t previousFlags = 0; |
13281 | ExtractLastVisit(aLoadState->GetPendingRedirectedChannel(), |
13282 | getter_AddRefs(previousURI), &previousFlags); |
13283 | self->SaveLastVisit(aLoadState->GetPendingRedirectedChannel(), |
13284 | previousURI, previousFlags); |
13285 | |
13286 | if (aTiming) { |
13287 | self->mTiming = new nsDOMNavigationTiming(self, aTiming); |
13288 | self->mBlankTiming = false; |
13289 | } |
13290 | |
13291 | // If we're performing a history load, locate the correct history entry, |
13292 | // and set the relevant bits on our loadState. |
13293 | if (aHistoryIndex >= 0 && self->GetSessionHistory() && |
13294 | !mozilla::SessionHistoryInParent()) { |
13295 | nsCOMPtr<nsISHistory> legacySHistory = |
13296 | self->GetSessionHistory()->LegacySHistory(); |
13297 | |
13298 | nsCOMPtr<nsISHEntry> entry; |
13299 | nsresult rv = legacySHistory->GetEntryAtIndex(aHistoryIndex, |
13300 | getter_AddRefs(entry)); |
13301 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) { |
13302 | legacySHistory->InternalSetRequestedIndex(aHistoryIndex); |
13303 | aLoadState->SetLoadType(LOAD_HISTORY); |
13304 | aLoadState->SetSHEntry(entry); |
13305 | } |
13306 | } |
13307 | |
13308 | self->InternalLoad(aLoadState); |
13309 | |
13310 | if (aLoadState->GetOriginalURIString().isSome()) { |
13311 | // Save URI string in case it's needed later when |
13312 | // sending to search engine service in EndPageLoad() |
13313 | self->mOriginalUriString = *aLoadState->GetOriginalURIString(); |
13314 | } |
13315 | |
13316 | for (auto& endpoint : aStreamFilterEndpoints) { |
13317 | extensions::StreamFilterParent::Attach( |
13318 | aLoadState->GetPendingRedirectedChannel(), std::move(endpoint)); |
13319 | } |
13320 | |
13321 | // If the channel isn't pending, then it means that InternalLoad |
13322 | // never connected it, and we shouldn't try to continue. This |
13323 | // can happen even if InternalLoad returned NS_OK. |
13324 | bool pending = false; |
13325 | aLoadState->GetPendingRedirectedChannel()->IsPending(&pending); |
13326 | 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" , 13326); MOZ_PretendNoReturn(); } } while (0); |
13327 | if (!pending) { |
13328 | return NS_BINDING_ABORTED; |
13329 | } |
13330 | return NS_OK; |
13331 | }); |
13332 | return NS_OK; |
13333 | } |
13334 | |
13335 | NS_IMETHODIMPnsresult |
13336 | nsDocShell::SetOriginAttributes(JS::Handle<JS::Value> aOriginAttributes, |
13337 | JSContext* aCx) { |
13338 | OriginAttributes attrs; |
13339 | if (!aOriginAttributes.isObject() || !attrs.Init(aCx, aOriginAttributes)) { |
13340 | return NS_ERROR_INVALID_ARG; |
13341 | } |
13342 | |
13343 | return SetOriginAttributes(attrs); |
13344 | } |
13345 | |
13346 | NS_IMETHODIMPnsresult |
13347 | nsDocShell::GetAsyncPanZoomEnabled(bool* aOut) { |
13348 | if (PresShell* presShell = GetPresShell()) { |
13349 | *aOut = presShell->AsyncPanZoomEnabled(); |
13350 | return NS_OK; |
13351 | } |
13352 | |
13353 | // If we don't have a presShell, fall back to the default platform value of |
13354 | // whether or not APZ is enabled. |
13355 | *aOut = gfxPlatform::AsyncPanZoomEnabled(); |
13356 | return NS_OK; |
13357 | } |
13358 | |
13359 | bool nsDocShell::HasUnloadedParent() { |
13360 | for (WindowContext* wc = GetBrowsingContext()->GetParentWindowContext(); wc; |
13361 | wc = wc->GetParentWindowContext()) { |
13362 | if (!wc->IsCurrent() || wc->IsDiscarded() || |
13363 | wc->GetBrowsingContext()->IsDiscarded()) { |
13364 | // If a parent is OOP and the parent WindowContext is no |
13365 | // longer current, we can assume the parent was unloaded. |
13366 | return true; |
13367 | } |
13368 | |
13369 | if (wc->GetBrowsingContext()->IsInProcess() && |
13370 | (!wc->GetBrowsingContext()->GetDocShell() || |
13371 | wc->GetBrowsingContext()->GetDocShell()->GetIsInUnload())) { |
13372 | return true; |
13373 | } |
13374 | } |
13375 | return false; |
13376 | } |
13377 | |
13378 | /* static */ |
13379 | bool nsDocShell::ShouldUpdateGlobalHistory(uint32_t aLoadType) { |
13380 | return !(aLoadType == LOAD_BYPASS_HISTORY || aLoadType == LOAD_ERROR_PAGE || |
13381 | aLoadType & LOAD_CMD_HISTORY); |
13382 | } |
13383 | |
13384 | void nsDocShell::UpdateGlobalHistoryTitle(nsIURI* aURI) { |
13385 | if (!mBrowsingContext->GetUseGlobalHistory() || UsePrivateBrowsing()) { |
13386 | return; |
13387 | } |
13388 | |
13389 | // Global history is interested into sub-frame visits only for link-coloring |
13390 | // purposes, thus title updates are skipped for those. |
13391 | // |
13392 | // Moreover, some iframe documents (such as the ones created via |
13393 | // document.open()) inherit the document uri of the caller, which would cause |
13394 | // us to override a previously set page title with one from the subframe. |
13395 | if (IsSubframe()) { |
13396 | return; |
13397 | } |
13398 | |
13399 | if (nsCOMPtr<IHistory> history = components::History::Service()) { |
13400 | history->SetURITitle(aURI, mTitle); |
13401 | } |
13402 | } |
13403 | |
13404 | bool nsDocShell::IsInvisible() { return mInvisible; } |
13405 | |
13406 | void nsDocShell::SetInvisible(bool aInvisible) { mInvisible = aInvisible; } |
13407 | |
13408 | /* static */ |
13409 | void nsDocShell::MaybeNotifyKeywordSearchLoading(const nsString& aProvider, |
13410 | const nsString& aKeyword) { |
13411 | if (aProvider.IsEmpty()) { |
13412 | return; |
13413 | } |
13414 | nsresult rv; |
13415 | nsCOMPtr<nsISupportsString> isupportsString = |
13416 | do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID"@mozilla.org/supports-string;1", &rv); |
13417 | 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" , 13417); return; } } while (false); |
13418 | |
13419 | rv = isupportsString->SetData(aProvider); |
13420 | 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" , 13420); return; } } while (false); |
13421 | |
13422 | nsCOMPtr<nsIObserverService> obsSvc = services::GetObserverService(); |
13423 | if (obsSvc) { |
13424 | // Note that "keyword-search" refers to a search via the url |
13425 | // bar, not a bookmarks keyword search. |
13426 | obsSvc->NotifyObservers(isupportsString, "keyword-search", aKeyword.get()); |
13427 | } |
13428 | } |
13429 | |
13430 | NS_IMETHODIMPnsresult |
13431 | nsDocShell::ShouldPrepareForIntercept(nsIURI* aURI, nsIChannel* aChannel, |
13432 | bool* aShouldIntercept) { |
13433 | return mInterceptController->ShouldPrepareForIntercept(aURI, aChannel, |
13434 | aShouldIntercept); |
13435 | } |
13436 | |
13437 | NS_IMETHODIMPnsresult |
13438 | nsDocShell::ChannelIntercepted(nsIInterceptedChannel* aChannel) { |
13439 | return mInterceptController->ChannelIntercepted(aChannel); |
13440 | } |
13441 | |
13442 | bool nsDocShell::InFrameSwap() { |
13443 | RefPtr<nsDocShell> shell = this; |
13444 | do { |
13445 | if (shell->mInFrameSwap) { |
13446 | return true; |
13447 | } |
13448 | shell = shell->GetInProcessParentDocshell(); |
13449 | } while (shell); |
13450 | return false; |
13451 | } |
13452 | |
13453 | UniquePtr<ClientSource> nsDocShell::TakeInitialClientSource() { |
13454 | return std::move(mInitialClientSource); |
13455 | } |
13456 | |
13457 | NS_IMETHODIMPnsresult |
13458 | nsDocShell::GetEditingSession(nsIEditingSession** aEditSession) { |
13459 | if (!NS_SUCCEEDED(EnsureEditorData())((bool)(__builtin_expect(!!(!NS_FAILED_impl(EnsureEditorData( ))), 1)))) { |
13460 | return NS_ERROR_FAILURE; |
13461 | } |
13462 | |
13463 | *aEditSession = do_AddRef(mEditorData->GetEditingSession()).take(); |
13464 | return *aEditSession ? NS_OK : NS_ERROR_FAILURE; |
13465 | } |
13466 | |
13467 | NS_IMETHODIMPnsresult |
13468 | nsDocShell::GetScriptableBrowserChild(nsIBrowserChild** aBrowserChild) { |
13469 | *aBrowserChild = GetBrowserChild().take(); |
13470 | return *aBrowserChild ? NS_OK : NS_ERROR_FAILURE; |
13471 | } |
13472 | |
13473 | already_AddRefed<nsIBrowserChild> nsDocShell::GetBrowserChild() { |
13474 | nsCOMPtr<nsIBrowserChild> tc = do_QueryReferent(mBrowserChild); |
13475 | return tc.forget(); |
13476 | } |
13477 | |
13478 | nsCommandManager* nsDocShell::GetCommandManager() { |
13479 | 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" , 13479); return nullptr; } } while (false); |
13480 | return mCommandManager; |
13481 | } |
13482 | |
13483 | NS_IMETHODIMP_(void)void |
13484 | nsDocShell::GetOriginAttributes(mozilla::OriginAttributes& aAttrs) { |
13485 | mBrowsingContext->GetOriginAttributes(aAttrs); |
13486 | } |
13487 | |
13488 | HTMLEditor* nsIDocShell::GetHTMLEditor() { |
13489 | nsDocShell* docShell = static_cast<nsDocShell*>(this); |
13490 | return docShell->GetHTMLEditorInternal(); |
13491 | } |
13492 | |
13493 | nsresult nsIDocShell::SetHTMLEditor(HTMLEditor* aHTMLEditor) { |
13494 | nsDocShell* docShell = static_cast<nsDocShell*>(this); |
13495 | return docShell->SetHTMLEditorInternal(aHTMLEditor); |
13496 | } |
13497 | |
13498 | #define MATRIX_LENGTH 20 |
13499 | |
13500 | NS_IMETHODIMPnsresult |
13501 | nsDocShell::SetColorMatrix(const nsTArray<float>& aMatrix) { |
13502 | if (aMatrix.Length() == MATRIX_LENGTH) { |
13503 | mColorMatrix.reset(new gfx::Matrix5x4()); |
13504 | static_assert( |
13505 | MATRIX_LENGTH * sizeof(float) == sizeof(mColorMatrix->components), |
13506 | "Size mismatch for our memcpy"); |
13507 | memcpy(mColorMatrix->components, aMatrix.Elements(), |
13508 | sizeof(mColorMatrix->components)); |
13509 | } else if (aMatrix.Length() == 0) { |
13510 | mColorMatrix.reset(); |
13511 | } else { |
13512 | return NS_ERROR_INVALID_ARG; |
13513 | } |
13514 | |
13515 | PresShell* presShell = GetPresShell(); |
13516 | if (!presShell) { |
13517 | return NS_ERROR_FAILURE; |
13518 | } |
13519 | |
13520 | nsIFrame* frame = presShell->GetRootFrame(); |
13521 | if (!frame) { |
13522 | return NS_ERROR_FAILURE; |
13523 | } |
13524 | |
13525 | frame->SchedulePaint(); |
13526 | |
13527 | return NS_OK; |
13528 | } |
13529 | |
13530 | NS_IMETHODIMPnsresult |
13531 | nsDocShell::GetColorMatrix(nsTArray<float>& aMatrix) { |
13532 | if (mColorMatrix) { |
13533 | aMatrix.SetLength(MATRIX_LENGTH); |
13534 | static_assert( |
13535 | MATRIX_LENGTH * sizeof(float) == sizeof(mColorMatrix->components), |
13536 | "Size mismatch for our memcpy"); |
13537 | memcpy(aMatrix.Elements(), mColorMatrix->components, |
13538 | MATRIX_LENGTH * sizeof(float)); |
13539 | } |
13540 | |
13541 | return NS_OK; |
13542 | } |
13543 | |
13544 | #undef MATRIX_LENGTH |
13545 | |
13546 | NS_IMETHODIMPnsresult |
13547 | nsDocShell::GetIsForceReloading(bool* aForceReload) { |
13548 | *aForceReload = IsForceReloading(); |
13549 | return NS_OK; |
13550 | } |
13551 | |
13552 | bool nsDocShell::IsForceReloading() { return IsForceReloadType(mLoadType); } |
13553 | |
13554 | NS_IMETHODIMPnsresult |
13555 | nsDocShell::GetBrowsingContextXPCOM(BrowsingContext** aBrowsingContext) { |
13556 | *aBrowsingContext = do_AddRef(mBrowsingContext).take(); |
13557 | return NS_OK; |
13558 | } |
13559 | |
13560 | BrowsingContext* nsDocShell::GetBrowsingContext() { return mBrowsingContext; } |
13561 | |
13562 | bool nsDocShell::GetIsAttemptingToNavigate() { |
13563 | // XXXbz the document.open spec says to abort even if there's just a |
13564 | // queued navigation task, sort of. It's not clear whether browsers |
13565 | // actually do that, and we didn't use to do it, so for now let's |
13566 | // not do that. |
13567 | // https://github.com/whatwg/html/issues/3447 tracks the spec side of this. |
13568 | if (mDocumentRequest) { |
13569 | // There's definitely a navigation in progress. |
13570 | return true; |
13571 | } |
13572 | |
13573 | // javascript: channels have slightly weird behavior: they're LOAD_BACKGROUND |
13574 | // until the script runs, which means they're not sending loadgroup |
13575 | // notifications and hence not getting set as mDocumentRequest. Look through |
13576 | // our loadgroup for document-level javascript: loads. |
13577 | if (!mLoadGroup) { |
13578 | return false; |
13579 | } |
13580 | |
13581 | nsCOMPtr<nsISimpleEnumerator> requests; |
13582 | mLoadGroup->GetRequests(getter_AddRefs(requests)); |
13583 | bool hasMore = false; |
13584 | while (NS_SUCCEEDED(requests->HasMoreElements(&hasMore))((bool)(__builtin_expect(!!(!NS_FAILED_impl(requests->HasMoreElements (&hasMore))), 1))) && hasMore) { |
13585 | nsCOMPtr<nsISupports> elem; |
13586 | requests->GetNext(getter_AddRefs(elem)); |
13587 | nsCOMPtr<nsIScriptChannel> scriptChannel(do_QueryInterface(elem)); |
13588 | if (!scriptChannel) { |
13589 | continue; |
13590 | } |
13591 | |
13592 | if (scriptChannel->GetIsDocumentLoad()) { |
13593 | // This is a javascript: load that might lead to a new document, |
13594 | // hence a navigation. |
13595 | return true; |
13596 | } |
13597 | } |
13598 | |
13599 | return mCheckingSessionHistory; |
13600 | } |
13601 | |
13602 | void nsDocShell::SetLoadingSessionHistoryInfo( |
13603 | const mozilla::dom::LoadingSessionHistoryInfo& aLoadingInfo, |
13604 | bool aNeedToReportActiveAfterLoadingBecomesActive) { |
13605 | // FIXME Would like to assert this, but can't yet. |
13606 | // MOZ_ASSERT(!mLoadingEntry); |
13607 | 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) |
13608 | ("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) |
13609 | 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); |
13610 | mLoadingEntry = MakeUnique<LoadingSessionHistoryInfo>(aLoadingInfo); |
13611 | mNeedToReportActiveAfterLoadingBecomesActive = |
13612 | aNeedToReportActiveAfterLoadingBecomesActive; |
13613 | } |
13614 | |
13615 | void nsDocShell::MoveLoadingToActiveEntry(bool aPersist, bool aExpired, |
13616 | uint32_t aCacheKey, |
13617 | nsIURI* aPreviousURI) { |
13618 | 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" , 13618); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mozilla::SessionHistoryInParent()" ")"); do { *((volatile int*)__null) = 13618; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
13619 | |
13620 | 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) |
13621 | ("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); |
13622 | |
13623 | UniquePtr<SessionHistoryInfo> previousActiveEntry(mActiveEntry.release()); |
13624 | mozilla::UniquePtr<mozilla::dom::LoadingSessionHistoryInfo> loadingEntry; |
13625 | mActiveEntryIsLoadingFromSessionHistory = |
13626 | mLoadingEntry && mLoadingEntry->mLoadIsFromSessionHistory; |
13627 | if (mLoadingEntry) { |
13628 | 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) |
13629 | ("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) |
13630 | "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) |
13631 | 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); |
13632 | mActiveEntry = MakeUnique<SessionHistoryInfo>(mLoadingEntry->mInfo); |
13633 | mLoadingEntry.swap(loadingEntry); |
13634 | if (!mActiveEntryIsLoadingFromSessionHistory) { |
13635 | if (mNeedToReportActiveAfterLoadingBecomesActive) { |
13636 | // Needed to pass various history length WPTs. |
13637 | mBrowsingContext->SetActiveSessionHistoryEntry( |
13638 | mozilla::Nothing(), mActiveEntry.get(), mLoadType, |
13639 | /* aUpdatedCacheKey = */ 0, false); |
13640 | } |
13641 | mBrowsingContext->IncrementHistoryEntryCountForBrowsingContext(); |
13642 | } |
13643 | } |
13644 | mNeedToReportActiveAfterLoadingBecomesActive = false; |
13645 | |
13646 | if (mActiveEntry) { |
13647 | if (aCacheKey != 0) { |
13648 | mActiveEntry->SetCacheKey(aCacheKey); |
13649 | } |
13650 | 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" , 13650); AnnotateMozCrashReason("MOZ_ASSERT" "(" "loadingEntry" ")"); do { *((volatile int*)__null) = 13650; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
13651 | uint32_t loadType = |
13652 | mLoadType == LOAD_ERROR_PAGE ? mFailedLoadType : mLoadType; |
13653 | |
13654 | if (loadingEntry->mLoadId != UINT64_MAX(18446744073709551615UL)) { |
13655 | // We're passing in mCurrentURI, which could be null. SessionHistoryCommit |
13656 | // does require a non-null uri if this is for a refresh load of the same |
13657 | // URI, but in that case mCurrentURI won't be null here. |
13658 | mBrowsingContext->SessionHistoryCommit( |
13659 | *loadingEntry, loadType, aPreviousURI, previousActiveEntry.get(), |
13660 | aPersist, false, aExpired, aCacheKey); |
13661 | } |
13662 | } |
13663 | } |
13664 | |
13665 | static bool IsFaviconLoad(nsIRequest* aRequest) { |
13666 | nsCOMPtr<nsIChannel> channel = do_QueryInterface(aRequest); |
13667 | if (!channel) { |
13668 | return false; |
13669 | } |
13670 | |
13671 | nsCOMPtr<nsILoadInfo> li = channel->LoadInfo(); |
13672 | return li && li->InternalContentPolicyType() == |
13673 | nsIContentPolicy::TYPE_INTERNAL_IMAGE_FAVICON; |
13674 | } |
13675 | |
13676 | void nsDocShell::RecordSingleChannelId(bool aStartRequest, |
13677 | nsIRequest* aRequest) { |
13678 | // Ignore favicon loads, they don't need to block caching. |
13679 | if (IsFaviconLoad(aRequest)) { |
13680 | return; |
13681 | } |
13682 | |
13683 | 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" , 13683); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mRequestForBlockingFromBFCacheCount > 0" ")"); do { *((volatile int*)__null) = 13683; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); } } while (false); |
13684 | |
13685 | mRequestForBlockingFromBFCacheCount += aStartRequest ? 1 : -1; |
13686 | |
13687 | if (mBrowsingContext->GetCurrentWindowContext()) { |
13688 | // We have three states: no request, one request with an id and |
13689 | // eiher one request without an id or multiple requests. Nothing() is no |
13690 | // request, Some(non-zero) is one request with an id and Some(0) is one |
13691 | // request without an id or multiple requests. |
13692 | Maybe<uint64_t> singleChannelId; |
13693 | if (mRequestForBlockingFromBFCacheCount > 1) { |
13694 | singleChannelId = Some(0); |
13695 | } else if (mRequestForBlockingFromBFCacheCount == 1) { |
13696 | nsCOMPtr<nsIIdentChannel> identChannel; |
13697 | if (aStartRequest) { |
13698 | identChannel = do_QueryInterface(aRequest); |
13699 | } else { |
13700 | // aChannel is the channel that's being removed, but we need to check if |
13701 | // the remaining channel in the loadgroup has an id. |
13702 | nsCOMPtr<nsISimpleEnumerator> requests; |
13703 | mLoadGroup->GetRequests(getter_AddRefs(requests)); |
13704 | for (const auto& request : SimpleEnumerator<nsIRequest>(requests)) { |
13705 | if (!IsFaviconLoad(request) && |
13706 | !!(identChannel = do_QueryInterface(request))) { |
13707 | break; |
13708 | } |
13709 | } |
13710 | } |
13711 | |
13712 | if (identChannel) { |
13713 | singleChannelId = Some(identChannel->ChannelId()); |
13714 | } else { |
13715 | singleChannelId = Some(0); |
13716 | } |
13717 | } else { |
13718 | 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" , 13718); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mRequestForBlockingFromBFCacheCount == 0" ")"); do { *((volatile int*)__null) = 13718; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
13719 | singleChannelId = Nothing(); |
13720 | } |
13721 | |
13722 | if (MOZ_UNLIKELY(MOZ_LOG_TEST(gSHIPBFCacheLog, LogLevel::Verbose))(__builtin_expect(!!((__builtin_expect(!!(mozilla::detail::log_test (gSHIPBFCacheLog, LogLevel::Verbose)), 0))), 0))) { |
13723 | nsAutoCString uri("[no uri]"); |
13724 | if (mCurrentURI) { |
13725 | uri = mCurrentURI->GetSpecOrDefault(); |
13726 | } |
13727 | if (singleChannelId.isNothing()) { |
13728 | 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) |
13729 | ("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) |
13730 | "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) |
13731 | 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); |
13732 | } else if (singleChannelId.value() == 0) { |
13733 | 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) |
13734 | ("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) |
13735 | "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) |
13736 | 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); |
13737 | } else { |
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, "Loadgroup for %s has one request with id %" "l" "u" " relevant for blocking BFCache", uri.get(), singleChannelId .value()); } } while (0) |
13739 | ("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) |
13740 | " 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) |
13741 | 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); |
13742 | } |
13743 | } |
13744 | |
13745 | if (mSingleChannelId != singleChannelId) { |
13746 | mSingleChannelId = singleChannelId; |
13747 | WindowGlobalChild* wgc = |
13748 | mBrowsingContext->GetCurrentWindowContext()->GetWindowGlobalChild(); |
13749 | if (wgc) { |
13750 | wgc->SendSetSingleChannelId(singleChannelId); |
13751 | } |
13752 | } |
13753 | } |
13754 | } |
13755 | |
13756 | NS_IMETHODIMPnsresult |
13757 | nsDocShell::OnStartRequest(nsIRequest* aRequest) { |
13758 | if (MOZ_UNLIKELY(MOZ_LOG_TEST(gSHIPBFCacheLog, LogLevel::Verbose))(__builtin_expect(!!((__builtin_expect(!!(mozilla::detail::log_test (gSHIPBFCacheLog, LogLevel::Verbose)), 0))), 0))) { |
13759 | nsAutoCString uri("[no uri]"); |
13760 | if (mCurrentURI) { |
13761 | uri = mCurrentURI->GetSpecOrDefault(); |
13762 | } |
13763 | nsAutoCString name; |
13764 | aRequest->GetName(name); |
13765 | 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) |
13766 | ("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); |
13767 | } |
13768 | RecordSingleChannelId(true, aRequest); |
13769 | return nsDocLoader::OnStartRequest(aRequest); |
13770 | } |
13771 | |
13772 | NS_IMETHODIMPnsresult |
13773 | nsDocShell::OnStopRequest(nsIRequest* aRequest, nsresult aStatusCode) { |
13774 | if (MOZ_UNLIKELY(MOZ_LOG_TEST(gSHIPBFCacheLog, LogLevel::Verbose))(__builtin_expect(!!((__builtin_expect(!!(mozilla::detail::log_test (gSHIPBFCacheLog, LogLevel::Verbose)), 0))), 0))) { |
13775 | nsAutoCString uri("[no uri]"); |
13776 | if (mCurrentURI) { |
13777 | uri = mCurrentURI->GetSpecOrDefault(); |
13778 | } |
13779 | nsAutoCString name; |
13780 | aRequest->GetName(name); |
13781 | 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) |
13782 | 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) |
13783 | ("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); |
13784 | } |
13785 | RecordSingleChannelId(false, aRequest); |
13786 | return nsDocLoader::OnStopRequest(aRequest, aStatusCode); |
13787 | } |
13788 | |
13789 | void nsDocShell::MaybeDisconnectChildListenersOnPageHide() { |
13790 | 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" , 13790); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "XRE_IsContentProcess()" ")"); do { *((volatile int*)__null) = 13790; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
13791 | |
13792 | if (mChannelToDisconnectOnPageHide != 0 && mLoadGroup) { |
13793 | nsCOMPtr<nsISimpleEnumerator> requests; |
13794 | mLoadGroup->GetRequests(getter_AddRefs(requests)); |
13795 | for (const auto& request : SimpleEnumerator<nsIRequest>(requests)) { |
13796 | RefPtr<DocumentChannel> channel = do_QueryObject(request); |
13797 | if (channel && channel->ChannelId() == mChannelToDisconnectOnPageHide) { |
13798 | static_cast<DocumentChannelChild*>(channel.get()) |
13799 | ->DisconnectChildListeners(NS_BINDING_ABORTED, NS_BINDING_ABORTED); |
13800 | } |
13801 | } |
13802 | mChannelToDisconnectOnPageHide = 0; |
13803 | } |
13804 | } |