File: | var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp |
Warning: | line 3504, 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/ScrollTypes.h" |
39 | #include "mozilla/SimpleEnumerator.h" |
40 | #include "mozilla/StaticPrefs_browser.h" |
41 | #include "mozilla/StaticPrefs_docshell.h" |
42 | #include "mozilla/StaticPrefs_dom.h" |
43 | #include "mozilla/StaticPrefs_extensions.h" |
44 | #include "mozilla/StaticPrefs_privacy.h" |
45 | #include "mozilla/StaticPrefs_security.h" |
46 | #include "mozilla/StaticPrefs_ui.h" |
47 | #include "mozilla/StaticPrefs_fission.h" |
48 | #include "mozilla/StartupTimeline.h" |
49 | #include "mozilla/StorageAccess.h" |
50 | #include "mozilla/StoragePrincipalHelper.h" |
51 | #include "mozilla/Telemetry.h" |
52 | |
53 | #include "mozilla/Unused.h" |
54 | #include "mozilla/WidgetUtils.h" |
55 | |
56 | #include "mozilla/dom/AutoEntryScript.h" |
57 | #include "mozilla/dom/ChildProcessChannelListener.h" |
58 | #include "mozilla/dom/ClientChannelHelper.h" |
59 | #include "mozilla/dom/ClientHandle.h" |
60 | #include "mozilla/dom/ClientInfo.h" |
61 | #include "mozilla/dom/ClientManager.h" |
62 | #include "mozilla/dom/ClientSource.h" |
63 | #include "mozilla/dom/ContentChild.h" |
64 | #include "mozilla/dom/ContentFrameMessageManager.h" |
65 | #include "mozilla/dom/DocGroup.h" |
66 | #include "mozilla/dom/Element.h" |
67 | #include "mozilla/dom/HTMLAnchorElement.h" |
68 | #include "mozilla/dom/HTMLIFrameElement.h" |
69 | #include "mozilla/dom/PerformanceNavigation.h" |
70 | #include "mozilla/dom/PermissionMessageUtils.h" |
71 | #include "mozilla/dom/PopupBlocker.h" |
72 | #include "mozilla/dom/ScreenOrientation.h" |
73 | #include "mozilla/dom/ScriptSettings.h" |
74 | #include "mozilla/dom/ServiceWorkerInterceptController.h" |
75 | #include "mozilla/dom/ServiceWorkerUtils.h" |
76 | #include "mozilla/dom/SessionHistoryEntry.h" |
77 | #include "mozilla/dom/SessionStorageManager.h" |
78 | #include "mozilla/dom/SessionStoreChangeListener.h" |
79 | #include "mozilla/dom/SessionStoreChild.h" |
80 | #include "mozilla/dom/SessionStoreUtils.h" |
81 | #include "mozilla/dom/BrowserChild.h" |
82 | #include "mozilla/dom/ToJSValue.h" |
83 | #include "mozilla/dom/UserActivation.h" |
84 | #include "mozilla/dom/ChildSHistory.h" |
85 | #include "mozilla/dom/nsCSPContext.h" |
86 | #include "mozilla/dom/nsHTTPSOnlyUtils.h" |
87 | #include "mozilla/dom/LoadURIOptionsBinding.h" |
88 | #include "mozilla/dom/JSWindowActorChild.h" |
89 | #include "mozilla/dom/DocumentBinding.h" |
90 | #include "mozilla/ipc/ProtocolUtils.h" |
91 | #include "mozilla/net/DocumentChannel.h" |
92 | #include "mozilla/net/DocumentChannelChild.h" |
93 | #include "mozilla/net/ParentChannelWrapper.h" |
94 | #include "mozilla/net/UrlClassifierFeatureFactory.h" |
95 | #include "ReferrerInfo.h" |
96 | |
97 | #include "nsIAuthPrompt.h" |
98 | #include "nsIAuthPrompt2.h" |
99 | #include "nsICachingChannel.h" |
100 | #include "nsICaptivePortalService.h" |
101 | #include "nsIChannel.h" |
102 | #include "nsIChannelEventSink.h" |
103 | #include "nsIClassOfService.h" |
104 | #include "nsIConsoleReportCollector.h" |
105 | #include "nsIContent.h" |
106 | #include "nsIContentInlines.h" |
107 | #include "nsIContentSecurityPolicy.h" |
108 | #include "nsIController.h" |
109 | #include "nsIDocShellTreeItem.h" |
110 | #include "nsIDocShellTreeOwner.h" |
111 | #include "nsIDocumentViewer.h" |
112 | #include "mozilla/dom/Document.h" |
113 | #include "nsHTMLDocument.h" |
114 | #include "nsIDocumentLoaderFactory.h" |
115 | #include "nsIDOMWindow.h" |
116 | #include "nsIEditingSession.h" |
117 | #include "nsIEffectiveTLDService.h" |
118 | #include "nsIExternalProtocolService.h" |
119 | #include "nsIFormPOSTActionChannel.h" |
120 | #include "nsIFrame.h" |
121 | #include "nsIGlobalObject.h" |
122 | #include "nsIHttpChannel.h" |
123 | #include "nsIHttpChannelInternal.h" |
124 | #include "nsIIDNService.h" |
125 | #include "nsIInputStreamChannel.h" |
126 | #include "nsIInterfaceRequestorUtils.h" |
127 | #include "nsILayoutHistoryState.h" |
128 | #include "nsILoadInfo.h" |
129 | #include "nsILoadURIDelegate.h" |
130 | #include "nsIMultiPartChannel.h" |
131 | #include "nsINestedURI.h" |
132 | #include "nsINetworkPredictor.h" |
133 | #include "nsINode.h" |
134 | #include "nsINSSErrorsService.h" |
135 | #include "nsIObserverService.h" |
136 | #include "nsIOService.h" |
137 | #include "nsIPrincipal.h" |
138 | #include "nsIPrivacyTransitionObserver.h" |
139 | #include "nsIPrompt.h" |
140 | #include "nsIPromptCollection.h" |
141 | #include "nsIPromptFactory.h" |
142 | #include "nsIPublicKeyPinningService.h" |
143 | #include "nsIReflowObserver.h" |
144 | #include "nsIScriptChannel.h" |
145 | #include "nsIScriptObjectPrincipal.h" |
146 | #include "nsIScriptSecurityManager.h" |
147 | #include "nsIScrollableFrame.h" |
148 | #include "nsIScrollObserver.h" |
149 | #include "nsISupportsPrimitives.h" |
150 | #include "nsISecureBrowserUI.h" |
151 | #include "nsISeekableStream.h" |
152 | #include "nsISelectionDisplay.h" |
153 | #include "nsISHEntry.h" |
154 | #include "nsISiteSecurityService.h" |
155 | #include "nsISocketProvider.h" |
156 | #include "nsIStringBundle.h" |
157 | #include "nsIStructuredCloneContainer.h" |
158 | #include "nsIBrowserChild.h" |
159 | #include "nsITextToSubURI.h" |
160 | #include "nsITimedChannel.h" |
161 | #include "nsITimer.h" |
162 | #include "nsITransportSecurityInfo.h" |
163 | #include "nsIUploadChannel.h" |
164 | #include "nsIURIFixup.h" |
165 | #include "nsIURIMutator.h" |
166 | #include "nsIURILoader.h" |
167 | #include "nsIViewSourceChannel.h" |
168 | #include "nsIWebBrowserChrome.h" |
169 | #include "nsIWebBrowserChromeFocus.h" |
170 | #include "nsIWebBrowserFind.h" |
171 | #include "nsIWebProgress.h" |
172 | #include "nsIWidget.h" |
173 | #include "nsIWindowWatcher.h" |
174 | #include "nsIWritablePropertyBag2.h" |
175 | #include "nsIX509Cert.h" |
176 | #include "nsIXULRuntime.h" |
177 | |
178 | #include "nsCommandManager.h" |
179 | #include "nsPIDOMWindow.h" |
180 | #include "nsPIWindowRoot.h" |
181 | |
182 | #include "IHistory.h" |
183 | #include "IUrlClassifierUITelemetry.h" |
184 | |
185 | #include "nsArray.h" |
186 | #include "nsArrayUtils.h" |
187 | #include "nsCExternalHandlerService.h" |
188 | #include "nsContentDLF.h" |
189 | #include "nsContentPolicyUtils.h" // NS_CheckContentLoadPolicy(...) |
190 | #include "nsContentSecurityManager.h" |
191 | #include "nsContentSecurityUtils.h" |
192 | #include "nsContentUtils.h" |
193 | #include "nsCURILoader.h" |
194 | #include "nsDocShellCID.h" |
195 | #include "nsDocShellEditorData.h" |
196 | #include "nsDocShellEnumerator.h" |
197 | #include "nsDocShellLoadState.h" |
198 | #include "nsDocShellLoadTypes.h" |
199 | #include "nsDOMCID.h" |
200 | #include "nsDOMNavigationTiming.h" |
201 | #include "nsDSURIContentListener.h" |
202 | #include "nsEditingSession.h" |
203 | #include "nsError.h" |
204 | #include "nsEscape.h" |
205 | #include "nsFocusManager.h" |
206 | #include "nsGlobalWindowInner.h" |
207 | #include "nsGlobalWindowOuter.h" |
208 | #include "nsJSEnvironment.h" |
209 | #include "nsNetCID.h" |
210 | #include "nsNetUtil.h" |
211 | #include "nsObjectLoadingContent.h" |
212 | #include "nsPingListener.h" |
213 | #include "nsPoint.h" |
214 | #include "nsQueryObject.h" |
215 | #include "nsQueryActor.h" |
216 | #include "nsRect.h" |
217 | #include "nsRefreshTimer.h" |
218 | #include "nsSandboxFlags.h" |
219 | #include "nsSHEntry.h" |
220 | #include "nsSHistory.h" |
221 | #include "nsSHEntry.h" |
222 | #include "nsStructuredCloneContainer.h" |
223 | #include "nsSubDocumentFrame.h" |
224 | #include "nsURILoader.h" |
225 | #include "nsURLHelper.h" |
226 | #include "nsView.h" |
227 | #include "nsViewManager.h" |
228 | #include "nsViewSourceHandler.h" |
229 | #include "nsWebBrowserFind.h" |
230 | #include "nsWhitespaceTokenizer.h" |
231 | #include "nsWidgetsCID.h" |
232 | #include "nsXULAppAPI.h" |
233 | |
234 | #include "ThirdPartyUtil.h" |
235 | #include "GeckoProfiler.h" |
236 | #include "mozilla/NullPrincipal.h" |
237 | #include "Navigator.h" |
238 | #include "prenv.h" |
239 | #include "mozilla/ipc/URIUtils.h" |
240 | #include "sslerr.h" |
241 | #include "mozpkix/pkix.h" |
242 | #include "NSSErrorsService.h" |
243 | |
244 | #include "nsDocShellTelemetryUtils.h" |
245 | |
246 | #ifdef MOZ_PLACES1 |
247 | # include "nsIFaviconService.h" |
248 | # include "mozIPlacesPendingOperation.h" |
249 | #endif |
250 | |
251 | #if NS_PRINT_PREVIEW1 |
252 | # include "nsIDocumentViewerPrint.h" |
253 | # include "nsIWebBrowserPrint.h" |
254 | #endif |
255 | |
256 | using namespace mozilla; |
257 | using namespace mozilla::dom; |
258 | using namespace mozilla::net; |
259 | |
260 | using mozilla::ipc::Endpoint; |
261 | |
262 | // Threshold value in ms for META refresh based redirects |
263 | #define REFRESH_REDIRECT_TIMER15000 15000 |
264 | |
265 | static mozilla::LazyLogModule gCharsetMenuLog("CharsetMenu"); |
266 | |
267 | #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) \ |
268 | 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) |
269 | |
270 | #ifdef DEBUG1 |
271 | unsigned long nsDocShell::gNumberOfDocShells = 0; |
272 | static uint64_t gDocshellIDCounter = 0; |
273 | |
274 | static mozilla::LazyLogModule gDocShellLog("nsDocShell"); |
275 | static mozilla::LazyLogModule gDocShellAndDOMWindowLeakLogging( |
276 | "DocShellAndDOMWindowLeak"); |
277 | #endif |
278 | static mozilla::LazyLogModule gDocShellLeakLog("nsDocShellLeak"); |
279 | extern mozilla::LazyLogModule gPageCacheLog; |
280 | mozilla::LazyLogModule gSHLog("SessionHistory"); |
281 | extern mozilla::LazyLogModule gSHIPBFCacheLog; |
282 | |
283 | const char kAppstringsBundleURL[] = |
284 | "chrome://global/locale/appstrings.properties"; |
285 | |
286 | static bool IsTopLevelDoc(BrowsingContext* aBrowsingContext, |
287 | nsILoadInfo* aLoadInfo) { |
288 | 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" , 288); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aBrowsingContext" ")"); do { *((volatile int*)__null) = 288; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
289 | 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" , 289); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadInfo" ")" ); do { *((volatile int*)__null) = 289; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
290 | |
291 | if (aLoadInfo->GetExternalContentPolicyType() != |
292 | ExtContentPolicy::TYPE_DOCUMENT) { |
293 | return false; |
294 | } |
295 | |
296 | return aBrowsingContext->IsTopContent(); |
297 | } |
298 | |
299 | // True if loading for top level document loading in active tab. |
300 | static bool IsUrgentStart(BrowsingContext* aBrowsingContext, |
301 | nsILoadInfo* aLoadInfo, uint32_t aLoadType) { |
302 | 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" , 302); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aBrowsingContext" ")"); do { *((volatile int*)__null) = 302; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
303 | 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" , 303); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadInfo" ")" ); do { *((volatile int*)__null) = 303; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
304 | |
305 | if (!IsTopLevelDoc(aBrowsingContext, aLoadInfo)) { |
306 | return false; |
307 | } |
308 | |
309 | if (aLoadType & |
310 | (nsIDocShell::LOAD_CMD_NORMAL | nsIDocShell::LOAD_CMD_HISTORY)) { |
311 | return true; |
312 | } |
313 | |
314 | return aBrowsingContext->IsActive(); |
315 | } |
316 | |
317 | nsDocShell::nsDocShell(BrowsingContext* aBrowsingContext, |
318 | uint64_t aContentWindowID) |
319 | : nsDocLoader(true), |
320 | mContentWindowID(aContentWindowID), |
321 | mBrowsingContext(aBrowsingContext), |
322 | mParentCharset(nullptr), |
323 | mTreeOwner(nullptr), |
324 | mScrollbarPref(ScrollbarPreference::Auto), |
325 | mCharsetReloadState(eCharsetReloadInit), |
326 | mParentCharsetSource(0), |
327 | mFrameMargins(-1, -1), |
328 | mItemType(aBrowsingContext->IsContent() ? typeContent : typeChrome), |
329 | mPreviousEntryIndex(-1), |
330 | mLoadedEntryIndex(-1), |
331 | mBusyFlags(BUSY_FLAGS_NONE), |
332 | mAppType(nsIDocShell::APP_TYPE_UNKNOWN), |
333 | mLoadType(0), |
334 | mFailedLoadType(0), |
335 | mMetaViewportOverride(nsIDocShell::META_VIEWPORT_OVERRIDE_NONE), |
336 | mChannelToDisconnectOnPageHide(0), |
337 | mCreatingDocument(false), |
338 | #ifdef DEBUG1 |
339 | mInEnsureScriptEnv(false), |
340 | #endif |
341 | mInitialized(false), |
342 | mAllowSubframes(true), |
343 | mAllowMetaRedirects(true), |
344 | mAllowImages(true), |
345 | mAllowMedia(true), |
346 | mAllowDNSPrefetch(true), |
347 | mAllowWindowControl(true), |
348 | mCSSErrorReportingEnabled(false), |
349 | mAllowAuth(mItemType == typeContent), |
350 | mAllowKeywordFixup(false), |
351 | mDisableMetaRefreshWhenInactive(false), |
352 | mWindowDraggingAllowed(false), |
353 | mInFrameSwap(false), |
354 | mFiredUnloadEvent(false), |
355 | mEODForCurrentDocument(false), |
356 | mURIResultedInDocument(false), |
357 | mIsBeingDestroyed(false), |
358 | mIsExecutingOnLoadHandler(false), |
359 | mSavingOldViewer(false), |
360 | mInvisible(false), |
361 | mHasLoadedNonBlankURI(false), |
362 | mBlankTiming(false), |
363 | mTitleValidForCurrentURI(false), |
364 | mWillChangeProcess(false), |
365 | mIsNavigating(false), |
366 | mForcedAutodetection(false), |
367 | mCheckingSessionHistory(false), |
368 | mNeedToReportActiveAfterLoadingBecomesActive(false) { |
369 | // If no outer window ID was provided, generate a new one. |
370 | if (aContentWindowID == 0) { |
371 | mContentWindowID = nsContentUtils::GenerateWindowId(); |
372 | } |
373 | |
374 | 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); |
375 | |
376 | #ifdef DEBUG1 |
377 | mDocShellID = gDocshellIDCounter++; |
378 | // We're counting the number of |nsDocShells| to help find leaks |
379 | ++gNumberOfDocShells; |
380 | 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) |
381 | ("++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) |
382 | 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); |
383 | #endif |
384 | } |
385 | |
386 | nsDocShell::~nsDocShell() { |
387 | // Avoid notifying observers while we're in the dtor. |
388 | mIsBeingDestroyed = true; |
389 | |
390 | Destroy(); |
391 | |
392 | if (mDocumentViewer) { |
393 | mDocumentViewer->Close(nullptr); |
394 | mDocumentViewer->Destroy(); |
395 | mDocumentViewer = nullptr; |
396 | } |
397 | |
398 | 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); |
399 | |
400 | #ifdef DEBUG1 |
401 | if (MOZ_LOG_TEST(gDocShellAndDOMWindowLeakLogging, LogLevel::Info)(__builtin_expect(!!(mozilla::detail::log_test(gDocShellAndDOMWindowLeakLogging , LogLevel::Info)), 0))) { |
402 | nsAutoCString url; |
403 | if (mLastOpenedURI) { |
404 | url = mLastOpenedURI->GetSpecOrDefault(); |
405 | |
406 | // Data URLs can be very long, so truncate to avoid flooding the log. |
407 | const uint32_t maxURLLength = 1000; |
408 | if (url.Length() > maxURLLength) { |
409 | url.Truncate(maxURLLength); |
410 | } |
411 | } |
412 | |
413 | // We're counting the number of |nsDocShells| to help find leaks |
414 | --gNumberOfDocShells; |
415 | 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) |
416 | 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) |
417 | ("--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) |
418 | (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); |
419 | } |
420 | #endif |
421 | } |
422 | |
423 | bool nsDocShell::Initialize() { |
424 | if (mInitialized) { |
425 | // We've already been initialized. |
426 | return true; |
427 | } |
428 | |
429 | 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" , 430); MOZ_PretendNoReturn(); } } while (0) |
430 | "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" , 430); MOZ_PretendNoReturn(); } } while (0); |
431 | |
432 | 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" , 432); return false; } } while (false); |
433 | mInitialized = true; |
434 | |
435 | mDisableMetaRefreshWhenInactive = |
436 | Preferences::GetBool("browser.meta_refresh_when_inactive.disabled", |
437 | mDisableMetaRefreshWhenInactive); |
438 | |
439 | if (nsCOMPtr<nsIObserverService> serv = services::GetObserverService()) { |
440 | const char* msg = mItemType == typeContent ? NS_WEBNAVIGATION_CREATE"webnavigation-create" |
441 | : NS_CHROME_WEBNAVIGATION_CREATE"chrome-webnavigation-create"; |
442 | serv->NotifyWhenScriptSafe(GetAsSupports(this), msg, nullptr); |
443 | } |
444 | |
445 | return true; |
446 | } |
447 | |
448 | /* static */ |
449 | already_AddRefed<nsDocShell> nsDocShell::Create( |
450 | BrowsingContext* aBrowsingContext, uint64_t aContentWindowID) { |
451 | 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" , 451); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aBrowsingContext" ") (" "DocShell without a BrowsingContext!" ")"); do { *((volatile int*)__null) = 451; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
452 | |
453 | nsresult rv; |
454 | RefPtr<nsDocShell> ds = new nsDocShell(aBrowsingContext, aContentWindowID); |
455 | |
456 | // Initialize the underlying nsDocLoader. |
457 | rv = ds->nsDocLoader::InitWithBrowsingContext(aBrowsingContext); |
458 | 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" , 458)) { |
459 | return nullptr; |
460 | } |
461 | |
462 | // Create our ContentListener |
463 | ds->mContentListener = new nsDSURIContentListener(ds); |
464 | |
465 | // We enable if we're in the parent process in order to support non-e10s |
466 | // configurations. |
467 | // Note: This check is duplicated in SharedWorkerInterfaceRequestor's |
468 | // constructor. |
469 | if (XRE_IsParentProcess()) { |
470 | ds->mInterceptController = new ServiceWorkerInterceptController(); |
471 | } |
472 | |
473 | // We want to hold a strong ref to the loadgroup, so it better hold a weak |
474 | // ref to us... use an InterfaceRequestorProxy to do this. |
475 | nsCOMPtr<nsIInterfaceRequestor> proxy = new InterfaceRequestorProxy(ds); |
476 | ds->mLoadGroup->SetNotificationCallbacks(proxy); |
477 | |
478 | // XXX(nika): We have our BrowsingContext, so we might be able to skip this. |
479 | // It could be nice to directly set up our DocLoader tree? |
480 | rv = nsDocLoader::AddDocLoaderAsChildOfRoot(ds); |
481 | 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" , 481)) { |
482 | return nullptr; |
483 | } |
484 | |
485 | // Add |ds| as a progress listener to itself. A little weird, but simpler |
486 | // than reproducing all the listener-notification logic in overrides of the |
487 | // various methods via which nsDocLoader can be notified. Note that this |
488 | // holds an nsWeakPtr to |ds|, so it's ok. |
489 | rv = ds->AddProgressListener(ds, nsIWebProgress::NOTIFY_STATE_DOCUMENT | |
490 | nsIWebProgress::NOTIFY_STATE_NETWORK | |
491 | nsIWebProgress::NOTIFY_LOCATION); |
492 | 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" , 492)) { |
493 | return nullptr; |
494 | } |
495 | |
496 | // If our BrowsingContext has private browsing enabled, update the number of |
497 | // private browsing docshells. |
498 | if (aBrowsingContext->UsePrivateBrowsing()) { |
499 | ds->NotifyPrivateBrowsingChanged(); |
500 | } |
501 | |
502 | // If our parent window is present in this process, set up our parent now. |
503 | RefPtr<WindowContext> parentWC = aBrowsingContext->GetParentWindowContext(); |
504 | if (parentWC && parentWC->IsInProcess()) { |
505 | // If we don't have a parent element anymore, we can't finish this load! |
506 | // How'd we get here? |
507 | RefPtr<Element> parentElement = aBrowsingContext->GetEmbedderElement(); |
508 | if (!parentElement) { |
509 | 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" , 509); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: " "nsDocShell::Create() - !parentElement" ")"); do { *((volatile int*)__null) = 509; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
510 | return nullptr; |
511 | } |
512 | |
513 | // We have an in-process parent window, but don't have a parent nsDocShell? |
514 | // How'd we get here! |
515 | nsCOMPtr<nsIDocShell> parentShell = |
516 | parentElement->OwnerDoc()->GetDocShell(); |
517 | if (!parentShell) { |
518 | 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" , 518); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: " "nsDocShell::Create() - !parentShell" ")"); do { *((volatile int*)__null) = 518; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
519 | return nullptr; |
520 | } |
521 | parentShell->AddChild(ds); |
522 | } |
523 | |
524 | // Make |ds| the primary DocShell for the given context. |
525 | aBrowsingContext->SetDocShell(ds); |
526 | |
527 | // Set |ds| default load flags on load group. |
528 | ds->SetLoadGroupDefaultLoadFlags(aBrowsingContext->GetDefaultLoadFlags()); |
529 | |
530 | if (XRE_IsParentProcess()) { |
531 | aBrowsingContext->Canonical()->MaybeAddAsProgressListener(ds); |
532 | } |
533 | |
534 | return ds.forget(); |
535 | } |
536 | |
537 | void nsDocShell::DestroyChildren() { |
538 | for (auto* child : mChildList.ForwardRange()) { |
539 | nsCOMPtr<nsIDocShellTreeItem> shell = do_QueryObject(child); |
540 | 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" , 540); MOZ_PretendNoReturn(); } } while (0); |
541 | |
542 | if (shell) { |
543 | shell->SetTreeOwner(nullptr); |
544 | } |
545 | } |
546 | |
547 | nsDocLoader::DestroyChildren(); |
548 | } |
549 | |
550 | 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; } |
551 | 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; } |
552 | 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; } |
553 | 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; } |
554 | |
555 | 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; } |
556 | 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; } |
557 | |
558 | 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" , 558); 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 |
559 | NS_INTERFACE_MAP_ENTRY(nsIDocShell)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t <decltype(*this)>, nsIDocShell>)) foundInterface = static_cast <nsIDocShell*>(this); else |
560 | NS_INTERFACE_MAP_ENTRY(nsIDocShellTreeItem)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t <decltype(*this)>, nsIDocShellTreeItem>)) foundInterface = static_cast<nsIDocShellTreeItem*>(this); else |
561 | NS_INTERFACE_MAP_ENTRY(nsIWebNavigation)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t <decltype(*this)>, nsIWebNavigation>)) foundInterface = static_cast<nsIWebNavigation*>(this); else |
562 | NS_INTERFACE_MAP_ENTRY(nsIBaseWindow)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t <decltype(*this)>, nsIBaseWindow>)) foundInterface = static_cast<nsIBaseWindow*>(this); else |
563 | NS_INTERFACE_MAP_ENTRY(nsIRefreshURI)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t <decltype(*this)>, nsIRefreshURI>)) foundInterface = static_cast<nsIRefreshURI*>(this); else |
564 | NS_INTERFACE_MAP_ENTRY(nsIWebProgressListener)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t <decltype(*this)>, nsIWebProgressListener>)) foundInterface = static_cast<nsIWebProgressListener*>(this); else |
565 | NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t <decltype(*this)>, nsISupportsWeakReference>)) foundInterface = static_cast<nsISupportsWeakReference*>(this); else |
566 | NS_INTERFACE_MAP_ENTRY(nsIWebPageDescriptor)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t <decltype(*this)>, nsIWebPageDescriptor>)) foundInterface = static_cast<nsIWebPageDescriptor*>(this); else |
567 | NS_INTERFACE_MAP_ENTRY(nsIAuthPromptProvider)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t <decltype(*this)>, nsIAuthPromptProvider>)) foundInterface = static_cast<nsIAuthPromptProvider*>(this); else |
568 | NS_INTERFACE_MAP_ENTRY(nsILoadContext)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t <decltype(*this)>, nsILoadContext>)) foundInterface = static_cast<nsILoadContext*>(this); else |
569 | 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 |
570 | mInterceptController)if ((mInterceptController) && aIID.Equals(mozilla::detail ::kImplementedIID<std::remove_reference_t<decltype(*this )>, nsINetworkInterceptController>)) foundInterface = static_cast <nsINetworkInterceptController*>(this); else |
571 | 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; } |
572 | |
573 | NS_IMETHODIMPnsresult |
574 | nsDocShell::GetInterface(const nsIID& aIID, void** aSink) { |
575 | 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" , 575); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aSink" ") (" "null out param" ")"); do { *((volatile int*)__null) = 575; __attribute__ ((nomerge)) ::abort(); } while (false); } } while (false); |
576 | |
577 | *aSink = nullptr; |
578 | |
579 | if (aIID.Equals(NS_GET_IID(nsICommandManager)(nsICommandManager::COMTypeInfo<nsICommandManager, void> ::kIID))) { |
580 | 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" , 580); return NS_ERROR_FAILURE; } } while (false); |
581 | *aSink = static_cast<nsICommandManager*>(mCommandManager.get()); |
582 | } else if (aIID.Equals(NS_GET_IID(nsIURIContentListener)(nsIURIContentListener::COMTypeInfo<nsIURIContentListener, void>::kIID))) { |
583 | *aSink = mContentListener; |
584 | } else if ((aIID.Equals(NS_GET_IID(nsIScriptGlobalObject)(nsIScriptGlobalObject::COMTypeInfo<nsIScriptGlobalObject, void>::kIID)) || |
585 | aIID.Equals(NS_GET_IID(nsIGlobalObject)(nsIGlobalObject::COMTypeInfo<nsIGlobalObject, void>::kIID )) || |
586 | aIID.Equals(NS_GET_IID(nsPIDOMWindowOuter)(nsPIDOMWindowOuter::COMTypeInfo<nsPIDOMWindowOuter, void> ::kIID)) || |
587 | aIID.Equals(NS_GET_IID(mozIDOMWindowProxy)(mozIDOMWindowProxy::COMTypeInfo<mozIDOMWindowProxy, void> ::kIID)) || |
588 | aIID.Equals(NS_GET_IID(nsIDOMWindow)(nsIDOMWindow::COMTypeInfo<nsIDOMWindow, void>::kIID))) && |
589 | NS_SUCCEEDED(EnsureScriptEnvironment())((bool)(__builtin_expect(!!(!NS_FAILED_impl(EnsureScriptEnvironment ())), 1)))) { |
590 | return mScriptGlobal->QueryInterface(aIID, aSink); |
591 | } else if (aIID.Equals(NS_GET_IID(Document)(Document::COMTypeInfo<Document, void>::kIID)) && |
592 | NS_SUCCEEDED(EnsureDocumentViewer())((bool)(__builtin_expect(!!(!NS_FAILED_impl(EnsureDocumentViewer ())), 1)))) { |
593 | RefPtr<Document> doc = mDocumentViewer->GetDocument(); |
594 | doc.forget(aSink); |
595 | return *aSink ? NS_OK : NS_NOINTERFACE; |
596 | } else if (aIID.Equals(NS_GET_IID(nsIPrompt)(nsIPrompt::COMTypeInfo<nsIPrompt, void>::kIID)) && |
597 | NS_SUCCEEDED(EnsureScriptEnvironment())((bool)(__builtin_expect(!!(!NS_FAILED_impl(EnsureScriptEnvironment ())), 1)))) { |
598 | nsresult rv; |
599 | nsCOMPtr<nsIWindowWatcher> wwatch = |
600 | do_GetService(NS_WINDOWWATCHER_CONTRACTID"@mozilla.org/embedcomp/window-watcher;1", &rv); |
601 | 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" , 601); return rv; } } while (false); |
602 | |
603 | // Get the an auth prompter for our window so that the parenting |
604 | // of the dialogs works as it should when using tabs. |
605 | nsIPrompt* prompt; |
606 | rv = wwatch->GetNewPrompter(mScriptGlobal, &prompt); |
607 | 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" , 607); return rv; } } while (false); |
608 | |
609 | *aSink = prompt; |
610 | return NS_OK; |
611 | } else if (aIID.Equals(NS_GET_IID(nsIAuthPrompt)(nsIAuthPrompt::COMTypeInfo<nsIAuthPrompt, void>::kIID)) || |
612 | aIID.Equals(NS_GET_IID(nsIAuthPrompt2)(nsIAuthPrompt2::COMTypeInfo<nsIAuthPrompt2, void>::kIID ))) { |
613 | return NS_SUCCEEDED(GetAuthPrompt(PROMPT_NORMAL, aIID, aSink))((bool)(__builtin_expect(!!(!NS_FAILED_impl(GetAuthPrompt(PROMPT_NORMAL , aIID, aSink))), 1))) |
614 | ? NS_OK |
615 | : NS_NOINTERFACE; |
616 | } else if (aIID.Equals(NS_GET_IID(nsISHistory)(nsISHistory::COMTypeInfo<nsISHistory, void>::kIID))) { |
617 | // This is deprecated, you should instead directly get |
618 | // ChildSHistory from the browsing context. |
619 | 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" , 620); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false" ") (" "Do not try to get a nsISHistory interface from nsIDocShell" ")"); do { *((volatile int*)__null) = 620; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
620 | 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" , 620); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false" ") (" "Do not try to get a nsISHistory interface from nsIDocShell" ")"); do { *((volatile int*)__null) = 620; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
621 | return NS_NOINTERFACE; |
622 | } else if (aIID.Equals(NS_GET_IID(nsIWebBrowserFind)(nsIWebBrowserFind::COMTypeInfo<nsIWebBrowserFind, void> ::kIID))) { |
623 | nsresult rv = EnsureFind(); |
624 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
625 | return rv; |
626 | } |
627 | |
628 | *aSink = mFind; |
629 | NS_ADDREF((nsISupports*)*aSink)((nsISupports*)*aSink)->AddRef(); |
630 | return NS_OK; |
631 | } else if (aIID.Equals(NS_GET_IID(nsISelectionDisplay)(nsISelectionDisplay::COMTypeInfo<nsISelectionDisplay, void >::kIID))) { |
632 | if (PresShell* presShell = GetPresShell()) { |
633 | return presShell->QueryInterface(aIID, aSink); |
634 | } |
635 | } else if (aIID.Equals(NS_GET_IID(nsIDocShellTreeOwner)(nsIDocShellTreeOwner::COMTypeInfo<nsIDocShellTreeOwner, void >::kIID))) { |
636 | nsCOMPtr<nsIDocShellTreeOwner> treeOwner; |
637 | nsresult rv = GetTreeOwner(getter_AddRefs(treeOwner)); |
638 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && treeOwner) { |
639 | return treeOwner->QueryInterface(aIID, aSink); |
640 | } |
641 | } else if (aIID.Equals(NS_GET_IID(nsIBrowserChild)(nsIBrowserChild::COMTypeInfo<nsIBrowserChild, void>::kIID ))) { |
642 | *aSink = GetBrowserChild().take(); |
643 | return *aSink ? NS_OK : NS_ERROR_FAILURE; |
644 | } else { |
645 | return nsDocLoader::GetInterface(aIID, aSink); |
646 | } |
647 | |
648 | NS_IF_ADDREF(((nsISupports*)*aSink))ns_if_addref(((nsISupports*)*aSink)); |
649 | return *aSink ? NS_OK : NS_NOINTERFACE; |
650 | } |
651 | |
652 | NS_IMETHODIMPnsresult |
653 | nsDocShell::SetCancelContentJSEpoch(int32_t aEpoch) { |
654 | // Note: this gets called fairly early (before a pageload actually starts). |
655 | // We could probably defer this even longer. |
656 | nsCOMPtr<nsIBrowserChild> browserChild = GetBrowserChild(); |
657 | static_cast<BrowserChild*>(browserChild.get()) |
658 | ->SetCancelContentJSEpoch(aEpoch); |
659 | return NS_OK; |
660 | } |
661 | |
662 | nsresult nsDocShell::CheckDisallowedJavascriptLoad( |
663 | nsDocShellLoadState* aLoadState) { |
664 | if (!net::SchemeIsJavascript(aLoadState->URI())) { |
665 | return NS_OK; |
666 | } |
667 | |
668 | if (nsCOMPtr<nsIPrincipal> targetPrincipal = |
669 | GetInheritedPrincipal(/* aConsiderCurrentDocument */ true)) { |
670 | if (!aLoadState->TriggeringPrincipal()->Subsumes(targetPrincipal)) { |
671 | return NS_ERROR_DOM_BAD_CROSS_ORIGIN_URI; |
672 | } |
673 | return NS_OK; |
674 | } |
675 | return NS_ERROR_DOM_BAD_CROSS_ORIGIN_URI; |
676 | } |
677 | |
678 | NS_IMETHODIMPnsresult |
679 | nsDocShell::LoadURI(nsDocShellLoadState* aLoadState, bool aSetNavigating) { |
680 | return LoadURI(aLoadState, aSetNavigating, false); |
681 | } |
682 | |
683 | nsresult nsDocShell::LoadURI(nsDocShellLoadState* aLoadState, |
684 | bool aSetNavigating, |
685 | bool aContinueHandlingSubframeHistory) { |
686 | 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" , 686); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState" ") (" "Must have a valid load state!" ")"); do { *((volatile int*) __null) = 686; __attribute__((nomerge)) ::abort(); } while (false ); } } while (false); |
687 | // NOTE: This comparison between what appears to be internal/external load |
688 | // flags is intentional, as it's ensuring that the caller isn't using any of |
689 | // the flags reserved for implementations by the `nsIWebNavigation` interface. |
690 | // In the future, this check may be dropped. |
691 | 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" , 693); AnnotateMozCrashReason("MOZ_ASSERT" "(" "(aLoadState->LoadFlags() & INTERNAL_LOAD_FLAGS_LOADURI_SETUP_FLAGS) == 0" ") (" "Should not have these flags set" ")"); do { *((volatile int*)__null) = 693; __attribute__((nomerge)) ::abort(); } while (false); } } while (false) |
692 | (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" , 693); AnnotateMozCrashReason("MOZ_ASSERT" "(" "(aLoadState->LoadFlags() & INTERNAL_LOAD_FLAGS_LOADURI_SETUP_FLAGS) == 0" ") (" "Should not have these flags set" ")"); do { *((volatile int*)__null) = 693; __attribute__((nomerge)) ::abort(); } while (false); } } while (false) |
693 | "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" , 693); AnnotateMozCrashReason("MOZ_ASSERT" "(" "(aLoadState->LoadFlags() & INTERNAL_LOAD_FLAGS_LOADURI_SETUP_FLAGS) == 0" ") (" "Should not have these flags set" ")"); do { *((volatile int*)__null) = 693; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
694 | 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" , 695); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->TargetBrowsingContext().IsNull()" ") (" "Targeting doesn't occur until InternalLoad" ")"); do { *((volatile int*)__null) = 695; __attribute__((nomerge)) ::abort (); } while (false); } } while (false) |
695 | "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" , 695); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->TargetBrowsingContext().IsNull()" ") (" "Targeting doesn't occur until InternalLoad" ")"); do { *((volatile int*)__null) = 695; __attribute__((nomerge)) ::abort (); } while (false); } } while (false); |
696 | |
697 | if (!aLoadState->TriggeringPrincipal()) { |
698 | 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" , 698); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "LoadURI must have a triggering principal" ")"); do { *((volatile int*)__null) = 698; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
699 | return NS_ERROR_FAILURE; |
700 | } |
701 | |
702 | MOZ_TRY(CheckDisallowedJavascriptLoad(aLoadState))do { auto mozTryTempResult_ = ::mozilla::ToResult(CheckDisallowedJavascriptLoad (aLoadState)); if ((__builtin_expect(!!(mozTryTempResult_.isErr ()), 0))) { return mozTryTempResult_.propagateErr(); } } while (0); |
703 | |
704 | bool oldIsNavigating = mIsNavigating; |
705 | auto cleanupIsNavigating = |
706 | MakeScopeExit([&]() { mIsNavigating = oldIsNavigating; }); |
707 | if (aSetNavigating) { |
708 | mIsNavigating = true; |
709 | } |
710 | |
711 | PopupBlocker::PopupControlState popupState = PopupBlocker::openOverridden; |
712 | if (aLoadState->HasLoadFlags(LOAD_FLAGS_ALLOW_POPUPS)) { |
713 | popupState = PopupBlocker::openAllowed; |
714 | // If we allow popups as part of the navigation, ensure we fake a user |
715 | // interaction, so that popups can, in fact, be allowed to open. |
716 | if (WindowContext* wc = mBrowsingContext->GetCurrentWindowContext()) { |
717 | wc->NotifyUserGestureActivation(); |
718 | } |
719 | } |
720 | |
721 | AutoPopupStatePusherAutoPopupStatePusherInternal statePusher(popupState); |
722 | |
723 | if (aLoadState->GetCancelContentJSEpoch().isSome()) { |
724 | SetCancelContentJSEpoch(*aLoadState->GetCancelContentJSEpoch()); |
725 | } |
726 | |
727 | // Note: we allow loads to get through here even if mFiredUnloadEvent is |
728 | // true; that case will get handled in LoadInternal or LoadHistoryEntry, |
729 | // so we pass false as the second parameter to IsNavigationAllowed. |
730 | // However, we don't allow the page to change location *in the middle of* |
731 | // firing beforeunload, so we do need to check if *beforeunload* is currently |
732 | // firing, so we call IsNavigationAllowed rather than just IsPrintingOrPP. |
733 | if (!IsNavigationAllowed(true, false)) { |
734 | return NS_OK; // JS may not handle returning of an error code |
735 | } |
736 | |
737 | nsLoadFlags defaultLoadFlags = mBrowsingContext->GetDefaultLoadFlags(); |
738 | if (aLoadState->HasLoadFlags(LOAD_FLAGS_FORCE_TRR)) { |
739 | defaultLoadFlags |= nsIRequest::LOAD_TRR_ONLY_MODE; |
740 | } else if (aLoadState->HasLoadFlags(LOAD_FLAGS_DISABLE_TRR)) { |
741 | defaultLoadFlags |= nsIRequest::LOAD_TRR_DISABLED_MODE; |
742 | } |
743 | |
744 | 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" , 744); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false" ") (" "NS_SUCCEEDED(mBrowsingContext->SetDefaultLoadFlags(defaultLoadFlags))" ")"); do { *((volatile int*)__null) = 744; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); |
745 | |
746 | if (!StartupTimeline::HasRecord(StartupTimeline::FIRST_LOAD_URI) && |
747 | mItemType == typeContent && !NS_IsAboutBlank(aLoadState->URI())) { |
748 | StartupTimeline::RecordOnce(StartupTimeline::FIRST_LOAD_URI); |
749 | } |
750 | |
751 | // LoadType used to be set to a default value here, if no LoadInfo/LoadState |
752 | // object was passed in. That functionality has been removed as of bug |
753 | // 1492648. LoadType should now be set up by the caller at the time they |
754 | // create their nsDocShellLoadState object to pass into LoadURI. |
755 | |
756 | 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) |
757 | 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) |
758 | ("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) |
759 | 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); |
760 | |
761 | if ((!aLoadState->LoadIsFromSessionHistory() && |
762 | !LOAD_TYPE_HAS_FLAGS(aLoadState->LoadType(),((aLoadState->LoadType()) & ((LOAD_FLAGS_REPLACE_HISTORY ) << 16)) |
763 | LOAD_FLAGS_REPLACE_HISTORY)((aLoadState->LoadType()) & ((LOAD_FLAGS_REPLACE_HISTORY ) << 16))) || |
764 | aContinueHandlingSubframeHistory) { |
765 | // This is possibly a subframe, so handle it accordingly. |
766 | // |
767 | // If history exists, it will be loaded into the aLoadState object, and the |
768 | // LoadType will be changed. |
769 | if (MaybeHandleSubframeHistory(aLoadState, |
770 | aContinueHandlingSubframeHistory)) { |
771 | // MaybeHandleSubframeHistory returns true if we need to continue loading |
772 | // asynchronously. |
773 | return NS_OK; |
774 | } |
775 | } |
776 | |
777 | if (aLoadState->LoadIsFromSessionHistory()) { |
778 | 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) |
779 | ("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); |
780 | |
781 | if (!mozilla::SessionHistoryInParent()) { |
782 | nsCOMPtr<nsISHEntry> entry = aLoadState->SHEntry(); |
783 | return LoadHistoryEntry(entry, aLoadState->LoadType(), |
784 | aLoadState->HasValidUserGestureActivation()); |
785 | } |
786 | |
787 | // FIXME Null check aLoadState->GetLoadingSessionHistoryInfo()? |
788 | return LoadHistoryEntry(*aLoadState->GetLoadingSessionHistoryInfo(), |
789 | aLoadState->LoadType(), |
790 | aLoadState->HasValidUserGestureActivation()); |
791 | } |
792 | |
793 | // On history navigation via Back/Forward buttons, don't execute |
794 | // automatic JavaScript redirection such as |location.href = ...| or |
795 | // |window.open()| |
796 | // |
797 | // LOAD_NORMAL: window.open(...) etc. |
798 | // LOAD_STOP_CONTENT: location.href = ..., location.assign(...) |
799 | if ((aLoadState->LoadType() == LOAD_NORMAL || |
800 | aLoadState->LoadType() == LOAD_STOP_CONTENT) && |
801 | ShouldBlockLoadingForBackButton()) { |
802 | return NS_OK; |
803 | } |
804 | |
805 | BrowsingContext::Type bcType = mBrowsingContext->GetType(); |
806 | |
807 | // Set up the inheriting principal in LoadState. |
808 | nsresult rv = aLoadState->SetupInheritingPrincipal( |
809 | bcType, mBrowsingContext->OriginAttributesRef()); |
810 | 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" , 810); return rv; } } while (false); |
811 | |
812 | rv = aLoadState->SetupTriggeringPrincipal( |
813 | mBrowsingContext->OriginAttributesRef()); |
814 | 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" , 814); return rv; } } while (false); |
815 | |
816 | aLoadState->CalculateLoadURIFlags(); |
817 | |
818 | 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" , 819); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->TypeHint().IsVoid()" ") (" "Typehint should be null when calling InternalLoad from LoadURI" ")"); do { *((volatile int*)__null) = 819; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
819 | "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" , 819); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->TypeHint().IsVoid()" ") (" "Typehint should be null when calling InternalLoad from LoadURI" ")"); do { *((volatile int*)__null) = 819; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
820 | 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" , 821); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->FileName().IsVoid()" ") (" "FileName should be null when calling InternalLoad from LoadURI" ")"); do { *((volatile int*)__null) = 821; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
821 | "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" , 821); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->FileName().IsVoid()" ") (" "FileName should be null when calling InternalLoad from LoadURI" ")"); do { *((volatile int*)__null) = 821; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
822 | 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" , 824); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aLoadState->LoadIsFromSessionHistory()" ") (" "Shouldn't be loading from an entry when calling InternalLoad " "from LoadURI" ")"); do { *((volatile int*)__null) = 824; __attribute__ ((nomerge)) ::abort(); } while (false); } } while (false) |
823 | "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" , 824); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aLoadState->LoadIsFromSessionHistory()" ") (" "Shouldn't be loading from an entry when calling InternalLoad " "from LoadURI" ")"); do { *((volatile int*)__null) = 824; __attribute__ ((nomerge)) ::abort(); } while (false); } } while (false) |
824 | "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" , 824); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aLoadState->LoadIsFromSessionHistory()" ") (" "Shouldn't be loading from an entry when calling InternalLoad " "from LoadURI" ")"); do { *((volatile int*)__null) = 824; __attribute__ ((nomerge)) ::abort(); } while (false); } } while (false); |
825 | |
826 | // If we have a system triggering principal, we can assume that this load was |
827 | // triggered by some UI in the browser chrome, such as the URL bar or |
828 | // bookmark bar. This should count as a user interaction for the current sh |
829 | // entry, so that the user may navigate back to the current entry, from the |
830 | // entry that is going to be added as part of this load. |
831 | nsCOMPtr<nsIPrincipal> triggeringPrincipal = |
832 | aLoadState->TriggeringPrincipal(); |
833 | if (triggeringPrincipal && triggeringPrincipal->IsSystemPrincipal()) { |
834 | if (mozilla::SessionHistoryInParent()) { |
835 | WindowContext* topWc = mBrowsingContext->GetTopWindowContext(); |
836 | if (topWc && !topWc->IsDiscarded()) { |
837 | 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" , 837); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false" ") (" "NS_SUCCEEDED(topWc->SetSHEntryHasUserInteraction(true))" ")"); do { *((volatile int*)__null) = 837; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); |
838 | } |
839 | } else { |
840 | bool oshe = false; |
841 | nsCOMPtr<nsISHEntry> currentSHEntry; |
842 | GetCurrentSHEntry(getter_AddRefs(currentSHEntry), &oshe); |
843 | if (currentSHEntry) { |
844 | currentSHEntry->SetHasUserInteraction(true); |
845 | } |
846 | } |
847 | } |
848 | |
849 | rv = InternalLoad(aLoadState); |
850 | 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" , 850); return rv; } } while (false); |
851 | |
852 | if (aLoadState->GetOriginalURIString().isSome()) { |
853 | // Save URI string in case it's needed later when |
854 | // sending to search engine service in EndPageLoad() |
855 | mOriginalUriString = *aLoadState->GetOriginalURIString(); |
856 | } |
857 | |
858 | return NS_OK; |
859 | } |
860 | |
861 | bool nsDocShell::IsLoadingFromSessionHistory() { |
862 | return mActiveEntryIsLoadingFromSessionHistory; |
863 | } |
864 | |
865 | // StopDetector is modeled similarly to OnloadBlocker; it is a rather |
866 | // dummy nsIRequest implementation which can be added to an nsILoadGroup to |
867 | // detect Cancel calls. |
868 | class StopDetector final : public nsIRequest { |
869 | public: |
870 | StopDetector() = default; |
871 | |
872 | 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: |
873 | 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; |
874 | |
875 | bool Canceled() { return mCanceled; } |
876 | |
877 | private: |
878 | ~StopDetector() = default; |
879 | |
880 | bool mCanceled = false; |
881 | }; |
882 | |
883 | 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" , 883); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0" ") (" "illegal refcnt" ")"); do { *((volatile int*)__null) = 883; __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" , 883); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"StopDetector\" != nullptr" ") (" "Must specify a name" ")"); do { *((volatile int*)__null ) = 883; __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" , 883); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0" ") (" "dup release" ")"); do { *((volatile int*)__null) = 883 ; __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" , 883); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"StopDetector\" != nullptr" ") (" "Must specify a name" ")"); do { *((volatile int*)__null ) = 883; __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" , 883); 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; } |
884 | |
885 | NS_IMETHODIMPnsresult |
886 | StopDetector::GetName(nsACString& aResult) { |
887 | aResult.AssignLiteral("about:stop-detector"); |
888 | return NS_OK; |
889 | } |
890 | |
891 | NS_IMETHODIMPnsresult |
892 | StopDetector::IsPending(bool* aRetVal) { |
893 | *aRetVal = true; |
894 | return NS_OK; |
895 | } |
896 | |
897 | NS_IMETHODIMPnsresult |
898 | StopDetector::GetStatus(nsresult* aStatus) { |
899 | *aStatus = NS_OK; |
900 | return NS_OK; |
901 | } |
902 | |
903 | NS_IMETHODIMPnsresult StopDetector::SetCanceledReason(const nsACString& aReason) { |
904 | return SetCanceledReasonImpl(aReason); |
905 | } |
906 | |
907 | NS_IMETHODIMPnsresult StopDetector::GetCanceledReason(nsACString& aReason) { |
908 | return GetCanceledReasonImpl(aReason); |
909 | } |
910 | |
911 | NS_IMETHODIMPnsresult StopDetector::CancelWithReason(nsresult aStatus, |
912 | const nsACString& aReason) { |
913 | return CancelWithReasonImpl(aStatus, aReason); |
914 | } |
915 | |
916 | NS_IMETHODIMPnsresult |
917 | StopDetector::Cancel(nsresult aStatus) { |
918 | mCanceled = true; |
919 | return NS_OK; |
920 | } |
921 | |
922 | NS_IMETHODIMPnsresult |
923 | StopDetector::Suspend(void) { return NS_OK; } |
924 | NS_IMETHODIMPnsresult |
925 | StopDetector::Resume(void) { return NS_OK; } |
926 | |
927 | NS_IMETHODIMPnsresult |
928 | StopDetector::GetLoadGroup(nsILoadGroup** aLoadGroup) { |
929 | *aLoadGroup = nullptr; |
930 | return NS_OK; |
931 | } |
932 | |
933 | NS_IMETHODIMPnsresult |
934 | StopDetector::SetLoadGroup(nsILoadGroup* aLoadGroup) { return NS_OK; } |
935 | |
936 | NS_IMETHODIMPnsresult |
937 | StopDetector::GetLoadFlags(nsLoadFlags* aLoadFlags) { |
938 | *aLoadFlags = nsIRequest::LOAD_NORMAL; |
939 | return NS_OK; |
940 | } |
941 | |
942 | NS_IMETHODIMPnsresult |
943 | StopDetector::GetTRRMode(nsIRequest::TRRMode* aTRRMode) { |
944 | return GetTRRModeImpl(aTRRMode); |
945 | } |
946 | |
947 | NS_IMETHODIMPnsresult |
948 | StopDetector::SetTRRMode(nsIRequest::TRRMode aTRRMode) { |
949 | return SetTRRModeImpl(aTRRMode); |
950 | } |
951 | |
952 | NS_IMETHODIMPnsresult |
953 | StopDetector::SetLoadFlags(nsLoadFlags aLoadFlags) { return NS_OK; } |
954 | |
955 | bool nsDocShell::MaybeHandleSubframeHistory( |
956 | nsDocShellLoadState* aLoadState, bool aContinueHandlingSubframeHistory) { |
957 | // First, verify if this is a subframe. |
958 | // Note, it is ok to rely on docshell here and not browsing context since when |
959 | // an iframe is created, it has first in-process docshell. |
960 | nsCOMPtr<nsIDocShellTreeItem> parentAsItem; |
961 | GetInProcessSameTypeParent(getter_AddRefs(parentAsItem)); |
962 | nsCOMPtr<nsIDocShell> parentDS(do_QueryInterface(parentAsItem)); |
963 | |
964 | if (!parentDS || parentDS == static_cast<nsIDocShell*>(this)) { |
965 | if (mBrowsingContext && mBrowsingContext->IsTop()) { |
966 | // This is the root docshell. If we got here while |
967 | // executing an onLoad Handler,this load will not go |
968 | // into session history. |
969 | // XXX Why is this code in a method which deals with iframes! |
970 | if (aLoadState->IsFormSubmission()) { |
971 | #ifdef DEBUG1 |
972 | if (!mEODForCurrentDocument) { |
973 | const MaybeDiscarded<BrowsingContext>& targetBC = |
974 | aLoadState->TargetBrowsingContext(); |
975 | 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" , 976); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->LoadType() == LOAD_NORMAL_REPLACE" ")"); do { *((volatile int*)__null) = 976; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) |
976 | 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" , 976); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->LoadType() == LOAD_NORMAL_REPLACE" ")"); do { *((volatile int*)__null) = 976; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); |
977 | } |
978 | #endif |
979 | } else { |
980 | bool inOnLoadHandler = false; |
981 | GetIsExecutingOnLoadHandler(&inOnLoadHandler); |
982 | if (inOnLoadHandler) { |
983 | aLoadState->SetLoadType(LOAD_NORMAL_REPLACE); |
984 | } |
985 | } |
986 | } |
987 | return false; |
988 | } |
989 | |
990 | /* OK. It is a subframe. Checkout the parent's loadtype. If the parent was |
991 | * loaded through a history mechanism, then get the SH entry for the child |
992 | * from the parent. This is done to restore frameset navigation while going |
993 | * back/forward. If the parent was loaded through any other loadType, set the |
994 | * child's loadType too accordingly, so that session history does not get |
995 | * confused. |
996 | */ |
997 | |
998 | // Get the parent's load type |
999 | uint32_t parentLoadType; |
1000 | parentDS->GetLoadType(&parentLoadType); |
1001 | |
1002 | if (!aContinueHandlingSubframeHistory) { |
1003 | if (mozilla::SessionHistoryInParent()) { |
1004 | if (nsDocShell::Cast(parentDS.get())->IsLoadingFromSessionHistory() && |
1005 | !GetCreatedDynamically()) { |
1006 | if (XRE_IsContentProcess()) { |
1007 | dom::ContentChild* contentChild = dom::ContentChild::GetSingleton(); |
1008 | nsCOMPtr<nsILoadGroup> loadGroup; |
1009 | GetLoadGroup(getter_AddRefs(loadGroup)); |
1010 | if (contentChild && loadGroup && !mCheckingSessionHistory) { |
1011 | RefPtr<Document> parentDoc = parentDS->GetDocument(); |
1012 | parentDoc->BlockOnload(); |
1013 | RefPtr<BrowsingContext> browsingContext = mBrowsingContext; |
1014 | Maybe<uint64_t> currentLoadIdentifier = |
1015 | mBrowsingContext->GetCurrentLoadIdentifier(); |
1016 | RefPtr<nsDocShellLoadState> loadState = aLoadState; |
1017 | bool isNavigating = mIsNavigating; |
1018 | RefPtr<StopDetector> stopDetector = new StopDetector(); |
1019 | loadGroup->AddRequest(stopDetector, nullptr); |
1020 | // Need to set mCheckingSessionHistory so that |
1021 | // GetIsAttemptingToNavigate() returns true. |
1022 | mCheckingSessionHistory = true; |
1023 | |
1024 | auto resolve = |
1025 | [currentLoadIdentifier, browsingContext, parentDoc, loadState, |
1026 | isNavigating, loadGroup, stopDetector]( |
1027 | mozilla::Maybe<LoadingSessionHistoryInfo>&& aResult) { |
1028 | RefPtr<nsDocShell> docShell = |
1029 | static_cast<nsDocShell*>(browsingContext->GetDocShell()); |
1030 | auto unblockParent = MakeScopeExit( |
1031 | [loadGroup, stopDetector, parentDoc, docShell]() { |
1032 | if (docShell) { |
1033 | docShell->mCheckingSessionHistory = false; |
1034 | } |
1035 | loadGroup->RemoveRequest(stopDetector, nullptr, NS_OK); |
1036 | parentDoc->UnblockOnload(false); |
1037 | }); |
1038 | |
1039 | if (!docShell || !docShell->mCheckingSessionHistory) { |
1040 | return; |
1041 | } |
1042 | |
1043 | if (stopDetector->Canceled()) { |
1044 | return; |
1045 | } |
1046 | if (currentLoadIdentifier == |
1047 | browsingContext->GetCurrentLoadIdentifier() && |
1048 | aResult.isSome()) { |
1049 | loadState->SetLoadingSessionHistoryInfo(aResult.value()); |
1050 | // This is an initial subframe load from the session |
1051 | // history, index doesn't need to be updated. |
1052 | loadState->SetLoadIsFromSessionHistory(0, false); |
1053 | } |
1054 | |
1055 | // We got the results back from the parent process, call |
1056 | // LoadURI again with the possibly updated data. |
1057 | docShell->LoadURI(loadState, isNavigating, true); |
1058 | }; |
1059 | auto reject = [loadGroup, stopDetector, browsingContext, |
1060 | parentDoc](mozilla::ipc::ResponseRejectReason) { |
1061 | RefPtr<nsDocShell> docShell = |
1062 | static_cast<nsDocShell*>(browsingContext->GetDocShell()); |
1063 | if (docShell) { |
1064 | docShell->mCheckingSessionHistory = false; |
1065 | } |
1066 | // In practise reject shouldn't be called ever. |
1067 | loadGroup->RemoveRequest(stopDetector, nullptr, NS_OK); |
1068 | parentDoc->UnblockOnload(false); |
1069 | }; |
1070 | contentChild->SendGetLoadingSessionHistoryInfoFromParent( |
1071 | mBrowsingContext, std::move(resolve), std::move(reject)); |
1072 | return true; |
1073 | } |
1074 | } else { |
1075 | Maybe<LoadingSessionHistoryInfo> info; |
1076 | mBrowsingContext->Canonical()->GetLoadingSessionHistoryInfoFromParent( |
1077 | info); |
1078 | if (info.isSome()) { |
1079 | aLoadState->SetLoadingSessionHistoryInfo(info.value()); |
1080 | // This is an initial subframe load from the session |
1081 | // history, index doesn't need to be updated. |
1082 | aLoadState->SetLoadIsFromSessionHistory(0, false); |
1083 | } |
1084 | } |
1085 | } |
1086 | } else { |
1087 | // Get the ShEntry for the child from the parent |
1088 | nsCOMPtr<nsISHEntry> currentSH; |
1089 | bool oshe = false; |
1090 | parentDS->GetCurrentSHEntry(getter_AddRefs(currentSH), &oshe); |
1091 | bool dynamicallyAddedChild = GetCreatedDynamically(); |
1092 | |
1093 | if (!dynamicallyAddedChild && !oshe && currentSH) { |
1094 | // Only use the old SHEntry, if we're sure enough that |
1095 | // it wasn't originally for some other frame. |
1096 | nsCOMPtr<nsISHEntry> shEntry; |
1097 | currentSH->GetChildSHEntryIfHasNoDynamicallyAddedChild( |
1098 | mBrowsingContext->ChildOffset(), getter_AddRefs(shEntry)); |
1099 | if (shEntry) { |
1100 | aLoadState->SetSHEntry(shEntry); |
1101 | } |
1102 | } |
1103 | } |
1104 | } |
1105 | |
1106 | // Make some decisions on the child frame's loadType based on the |
1107 | // parent's loadType, if the subframe hasn't loaded anything into it. |
1108 | // |
1109 | // In some cases privileged scripts may try to get the DOMWindow |
1110 | // reference of this docshell before the loading starts, causing the |
1111 | // initial about:blank content viewer being created and mCurrentURI being |
1112 | // set. To handle this case we check if mCurrentURI is about:blank and |
1113 | // currentSHEntry is null. |
1114 | bool oshe = false; |
1115 | nsCOMPtr<nsISHEntry> currentChildEntry; |
1116 | GetCurrentSHEntry(getter_AddRefs(currentChildEntry), &oshe); |
1117 | |
1118 | if (mCurrentURI && (!NS_IsAboutBlank(mCurrentURI) || currentChildEntry || |
1119 | mLoadingEntry || mActiveEntry)) { |
1120 | // This is a pre-existing subframe. If |
1121 | // 1. The load of this frame was not originally initiated by session |
1122 | // history directly (i.e. (!shEntry) condition succeeded, but it can |
1123 | // still be a history load on parent which causes this frame being |
1124 | // loaded), which we checked with the above assert, and |
1125 | // 2. mCurrentURI is not null, nor the initial about:blank, |
1126 | // it is possible that a parent's onLoadHandler or even self's |
1127 | // onLoadHandler is loading a new page in this child. Check parent's and |
1128 | // self's busy flag and if it is set, we don't want this onLoadHandler |
1129 | // load to get in to session history. |
1130 | BusyFlags parentBusy = parentDS->GetBusyFlags(); |
1131 | BusyFlags selfBusy = GetBusyFlags(); |
1132 | |
1133 | if (parentBusy & BUSY_FLAGS_BUSY || selfBusy & BUSY_FLAGS_BUSY) { |
1134 | aLoadState->SetLoadType(LOAD_NORMAL_REPLACE); |
1135 | aLoadState->ClearLoadIsFromSessionHistory(); |
1136 | } |
1137 | return false; |
1138 | } |
1139 | |
1140 | // This is a newly created frame. Check for exception cases first. |
1141 | // By default the subframe will inherit the parent's loadType. |
1142 | if (aLoadState->LoadIsFromSessionHistory() && |
1143 | (parentLoadType == LOAD_NORMAL || parentLoadType == LOAD_LINK)) { |
1144 | // The parent was loaded normally. In this case, this *brand new* |
1145 | // child really shouldn't have a SHEntry. If it does, it could be |
1146 | // because the parent is replacing an existing frame with a new frame, |
1147 | // in the onLoadHandler. We don't want this url to get into session |
1148 | // history. Clear off shEntry, and set load type to |
1149 | // LOAD_BYPASS_HISTORY. |
1150 | bool inOnLoadHandler = false; |
1151 | parentDS->GetIsExecutingOnLoadHandler(&inOnLoadHandler); |
1152 | if (inOnLoadHandler) { |
1153 | aLoadState->SetLoadType(LOAD_NORMAL_REPLACE); |
1154 | aLoadState->ClearLoadIsFromSessionHistory(); |
1155 | } |
1156 | } else if (parentLoadType == LOAD_REFRESH) { |
1157 | // Clear shEntry. For refresh loads, we have to load |
1158 | // what comes through the pipe, not what's in history. |
1159 | aLoadState->ClearLoadIsFromSessionHistory(); |
1160 | } else if ((parentLoadType == LOAD_BYPASS_HISTORY) || |
1161 | (aLoadState->LoadIsFromSessionHistory() && |
1162 | ((parentLoadType & LOAD_CMD_HISTORY) || |
1163 | (parentLoadType == LOAD_RELOAD_NORMAL) || |
1164 | (parentLoadType == LOAD_RELOAD_CHARSET_CHANGE) || |
1165 | (parentLoadType == LOAD_RELOAD_CHARSET_CHANGE_BYPASS_CACHE) || |
1166 | (parentLoadType == |
1167 | LOAD_RELOAD_CHARSET_CHANGE_BYPASS_PROXY_AND_CACHE)))) { |
1168 | // If the parent url, bypassed history or was loaded from |
1169 | // history, pass on the parent's loadType to the new child |
1170 | // frame too, so that the child frame will also |
1171 | // avoid getting into history. |
1172 | aLoadState->SetLoadType(parentLoadType); |
1173 | } else if (parentLoadType == LOAD_ERROR_PAGE) { |
1174 | // If the parent document is an error page, we don't |
1175 | // want to update global/session history. However, |
1176 | // this child frame is not an error page. |
1177 | aLoadState->SetLoadType(LOAD_BYPASS_HISTORY); |
1178 | } else if ((parentLoadType == LOAD_RELOAD_BYPASS_CACHE) || |
1179 | (parentLoadType == LOAD_RELOAD_BYPASS_PROXY) || |
1180 | (parentLoadType == LOAD_RELOAD_BYPASS_PROXY_AND_CACHE)) { |
1181 | // the new frame should inherit the parent's load type so that it also |
1182 | // bypasses the cache and/or proxy |
1183 | aLoadState->SetLoadType(parentLoadType); |
1184 | } |
1185 | |
1186 | return false; |
1187 | } |
1188 | |
1189 | /* |
1190 | * Reset state to a new content model within the current document and the |
1191 | * document viewer. Called by the document before initiating an out of band |
1192 | * document.write(). |
1193 | */ |
1194 | NS_IMETHODIMPnsresult |
1195 | nsDocShell::PrepareForNewContentModel() { |
1196 | // Clear out our form control state, because the state of controls |
1197 | // in the pre-open() document should not affect the state of |
1198 | // controls that are now going to be written. |
1199 | SetLayoutHistoryState(nullptr); |
1200 | mEODForCurrentDocument = false; |
1201 | return NS_OK; |
1202 | } |
1203 | |
1204 | NS_IMETHODIMPnsresult |
1205 | nsDocShell::FirePageHideNotification(bool aIsUnload) { |
1206 | FirePageHideNotificationInternal(aIsUnload, false); |
1207 | return NS_OK; |
1208 | } |
1209 | |
1210 | void nsDocShell::FirePageHideNotificationInternal( |
1211 | bool aIsUnload, bool aSkipCheckingDynEntries) { |
1212 | if (mDocumentViewer && !mFiredUnloadEvent) { |
1213 | // Keep an explicit reference since calling PageHide could release |
1214 | // mDocumentViewer |
1215 | nsCOMPtr<nsIDocumentViewer> viewer(mDocumentViewer); |
1216 | mFiredUnloadEvent = true; |
1217 | |
1218 | if (mTiming) { |
1219 | mTiming->NotifyUnloadEventStart(); |
1220 | } |
1221 | |
1222 | viewer->PageHide(aIsUnload); |
1223 | |
1224 | if (mTiming) { |
1225 | mTiming->NotifyUnloadEventEnd(); |
1226 | } |
1227 | |
1228 | AutoTArray<nsCOMPtr<nsIDocShell>, 8> kids; |
1229 | uint32_t n = mChildList.Length(); |
1230 | kids.SetCapacity(n); |
1231 | for (uint32_t i = 0; i < n; i++) { |
1232 | kids.AppendElement(do_QueryInterface(ChildAt(i))); |
1233 | } |
1234 | |
1235 | n = kids.Length(); |
1236 | for (uint32_t i = 0; i < n; ++i) { |
1237 | RefPtr<nsDocShell> child = static_cast<nsDocShell*>(kids[i].get()); |
1238 | if (child) { |
1239 | // Skip checking dynamic subframe entries in our children. |
1240 | child->FirePageHideNotificationInternal(aIsUnload, true); |
1241 | } |
1242 | } |
1243 | |
1244 | // If the document is unloading, remove all dynamic subframe entries. |
1245 | if (aIsUnload && !aSkipCheckingDynEntries) { |
1246 | RefPtr<ChildSHistory> rootSH = GetRootSessionHistory(); |
1247 | if (rootSH) { |
1248 | 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) |
1249 | 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) |
1250 | ("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); |
1251 | if (mozilla::SessionHistoryInParent()) { |
1252 | if (mActiveEntry) { |
1253 | mBrowsingContext->RemoveDynEntriesFromActiveSessionHistoryEntry(); |
1254 | } |
1255 | 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) |
1256 | ("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); |
1257 | } else if (mOSHE) { |
1258 | int32_t index = rootSH->Index(); |
1259 | rootSH->LegacySHistory()->RemoveDynEntries(index, mOSHE); |
1260 | } |
1261 | } |
1262 | } |
1263 | |
1264 | // Now make sure our editor, if any, is detached before we go |
1265 | // any farther. |
1266 | DetachEditorFromWindow(); |
1267 | } |
1268 | } |
1269 | |
1270 | void nsDocShell::ThawFreezeNonRecursive(bool aThaw) { |
1271 | 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" , 1271); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mozilla::BFCacheInParent()" ")"); do { *((volatile int*)__null) = 1271; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1272 | |
1273 | if (!mScriptGlobal) { |
1274 | return; |
1275 | } |
1276 | |
1277 | if (RefPtr<nsGlobalWindowInner> inner = |
1278 | nsGlobalWindowInner::Cast(mScriptGlobal->GetCurrentInnerWindow())) { |
1279 | if (aThaw) { |
1280 | inner->Thaw(false); |
1281 | } else { |
1282 | inner->Freeze(false); |
1283 | } |
1284 | } |
1285 | } |
1286 | |
1287 | void nsDocShell::FirePageHideShowNonRecursive(bool aShow) { |
1288 | 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" , 1288); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mozilla::BFCacheInParent()" ")"); do { *((volatile int*)__null) = 1288; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1289 | |
1290 | if (!mDocumentViewer) { |
1291 | return; |
1292 | } |
1293 | |
1294 | // Emulate what non-SHIP BFCache does too. In pageshow case |
1295 | // add and remove a request and before that call SetCurrentURI to get |
1296 | // the location change notification. |
1297 | // For pagehide, set mFiredUnloadEvent to true, so that unload doesn't fire. |
1298 | nsCOMPtr<nsIDocumentViewer> viewer(mDocumentViewer); |
1299 | if (aShow) { |
1300 | viewer->SetIsHidden(false); |
1301 | mRefreshURIList = std::move(mBFCachedRefreshURIList); |
1302 | RefreshURIFromQueue(); |
1303 | mFiredUnloadEvent = false; |
1304 | RefPtr<Document> doc = viewer->GetDocument(); |
1305 | if (doc) { |
1306 | doc->NotifyActivityChanged(); |
1307 | nsCOMPtr<nsPIDOMWindowInner> inner = |
1308 | mScriptGlobal ? mScriptGlobal->GetCurrentInnerWindow() : nullptr; |
1309 | if (mBrowsingContext->IsTop()) { |
1310 | doc->NotifyPossibleTitleChange(false); |
1311 | doc->SetLoadingOrRestoredFromBFCacheTimeStampToNow(); |
1312 | if (inner) { |
1313 | // Now that we have found the inner window of the page restored |
1314 | // from the history, we have to make sure that |
1315 | // performance.navigation.type is 2. |
1316 | // Traditionally this type change has been done to the top level page |
1317 | // only. |
1318 | Performance* performance = inner->GetPerformance(); |
1319 | if (performance) { |
1320 | performance->GetDOMTiming()->NotifyRestoreStart(); |
1321 | } |
1322 | } |
1323 | } |
1324 | |
1325 | nsCOMPtr<nsIChannel> channel = doc->GetChannel(); |
1326 | if (channel) { |
1327 | SetLoadType(LOAD_HISTORY); |
1328 | mEODForCurrentDocument = false; |
1329 | mIsRestoringDocument = true; |
1330 | mLoadGroup->AddRequest(channel, nullptr); |
1331 | SetCurrentURI(doc->GetDocumentURI(), channel, |
1332 | /* aFireOnLocationChange */ true, |
1333 | /* aIsInitialAboutBlank */ false, |
1334 | /* aLocationFlags */ 0); |
1335 | mLoadGroup->RemoveRequest(channel, nullptr, NS_OK); |
1336 | mIsRestoringDocument = false; |
1337 | } |
1338 | RefPtr<PresShell> presShell = GetPresShell(); |
1339 | if (presShell) { |
1340 | presShell->Thaw(false); |
1341 | } |
1342 | |
1343 | if (inner) { |
1344 | inner->FireDelayedDOMEvents(false); |
1345 | } |
1346 | } |
1347 | } else if (!mFiredUnloadEvent) { |
1348 | // XXXBFCache check again that the page can enter bfcache. |
1349 | // XXXBFCache should mTiming->NotifyUnloadEventStart()/End() be called here? |
1350 | |
1351 | if (mRefreshURIList) { |
1352 | RefreshURIToQueue(); |
1353 | mBFCachedRefreshURIList = std::move(mRefreshURIList); |
1354 | } else { |
1355 | // If Stop was called, the list was moved to mSavedRefreshURIList after |
1356 | // calling SuspendRefreshURIs, which calls RefreshURIToQueue. |
1357 | mBFCachedRefreshURIList = std::move(mSavedRefreshURIList); |
1358 | } |
1359 | |
1360 | mFiredUnloadEvent = true; |
1361 | viewer->PageHide(false); |
1362 | |
1363 | RefPtr<PresShell> presShell = GetPresShell(); |
1364 | if (presShell) { |
1365 | presShell->Freeze(false); |
1366 | } |
1367 | } |
1368 | } |
1369 | |
1370 | nsresult nsDocShell::Dispatch(already_AddRefed<nsIRunnable>&& aRunnable) { |
1371 | nsCOMPtr<nsIRunnable> runnable(aRunnable); |
1372 | if (NS_WARN_IF(!GetWindow())NS_warn_if_impl(!GetWindow(), "!GetWindow()", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 1372)) { |
1373 | // Window should only be unavailable after destroyed. |
1374 | 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" , 1374); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mIsBeingDestroyed" ")"); do { *((volatile int*)__null) = 1374; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1375 | return NS_ERROR_FAILURE; |
1376 | } |
1377 | return SchedulerGroup::Dispatch(runnable.forget()); |
1378 | } |
1379 | |
1380 | NS_IMETHODIMPnsresult |
1381 | nsDocShell::DispatchLocationChangeEvent() { |
1382 | return Dispatch(NewRunnableMethod("nsDocShell::FireDummyOnLocationChange", |
1383 | this, |
1384 | &nsDocShell::FireDummyOnLocationChange)); |
1385 | } |
1386 | |
1387 | NS_IMETHODIMPnsresult |
1388 | nsDocShell::StartDelayedAutoplayMediaComponents() { |
1389 | RefPtr<nsPIDOMWindowOuter> outerWindow = GetWindow(); |
1390 | if (outerWindow) { |
1391 | outerWindow->ActivateMediaComponents(); |
1392 | } |
1393 | return NS_OK; |
1394 | } |
1395 | |
1396 | bool nsDocShell::MaybeInitTiming() { |
1397 | if (mTiming && !mBlankTiming) { |
1398 | return false; |
1399 | } |
1400 | |
1401 | bool canBeReset = false; |
1402 | |
1403 | if (mScriptGlobal && mBlankTiming) { |
1404 | nsPIDOMWindowInner* innerWin = mScriptGlobal->GetCurrentInnerWindow(); |
1405 | if (innerWin && innerWin->GetPerformance()) { |
1406 | mTiming = innerWin->GetPerformance()->GetDOMTiming(); |
1407 | mBlankTiming = false; |
1408 | } |
1409 | } |
1410 | |
1411 | if (!mTiming) { |
1412 | mTiming = new nsDOMNavigationTiming(this); |
1413 | canBeReset = true; |
1414 | } |
1415 | |
1416 | mTiming->NotifyNavigationStart( |
1417 | mBrowsingContext->IsActive() |
1418 | ? nsDOMNavigationTiming::DocShellState::eActive |
1419 | : nsDOMNavigationTiming::DocShellState::eInactive); |
1420 | |
1421 | return canBeReset; |
1422 | } |
1423 | |
1424 | void nsDocShell::MaybeResetInitTiming(bool aReset) { |
1425 | if (aReset) { |
1426 | mTiming = nullptr; |
1427 | } |
1428 | } |
1429 | |
1430 | nsDOMNavigationTiming* nsDocShell::GetNavigationTiming() const { |
1431 | return mTiming; |
1432 | } |
1433 | |
1434 | nsPresContext* nsDocShell::GetEldestPresContext() { |
1435 | nsIDocumentViewer* viewer = mDocumentViewer; |
1436 | while (viewer) { |
1437 | nsIDocumentViewer* prevViewer = viewer->GetPreviousViewer(); |
1438 | if (!prevViewer) { |
1439 | return viewer->GetPresContext(); |
1440 | } |
1441 | viewer = prevViewer; |
1442 | } |
1443 | |
1444 | return nullptr; |
1445 | } |
1446 | |
1447 | nsPresContext* nsDocShell::GetPresContext() { |
1448 | if (!mDocumentViewer) { |
1449 | return nullptr; |
1450 | } |
1451 | |
1452 | return mDocumentViewer->GetPresContext(); |
1453 | } |
1454 | |
1455 | PresShell* nsDocShell::GetPresShell() { |
1456 | nsPresContext* presContext = GetPresContext(); |
1457 | return presContext ? presContext->GetPresShell() : nullptr; |
1458 | } |
1459 | |
1460 | PresShell* nsDocShell::GetEldestPresShell() { |
1461 | nsPresContext* presContext = GetEldestPresContext(); |
1462 | |
1463 | if (presContext) { |
1464 | return presContext->GetPresShell(); |
1465 | } |
1466 | |
1467 | return nullptr; |
1468 | } |
1469 | |
1470 | NS_IMETHODIMPnsresult |
1471 | nsDocShell::GetDocViewer(nsIDocumentViewer** aDocumentViewer) { |
1472 | 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" , 1472); return NS_ERROR_INVALID_POINTER; } } while (false); |
1473 | |
1474 | *aDocumentViewer = mDocumentViewer; |
1475 | NS_IF_ADDREF(*aDocumentViewer)ns_if_addref(*aDocumentViewer); |
1476 | return NS_OK; |
1477 | } |
1478 | |
1479 | NS_IMETHODIMPnsresult |
1480 | nsDocShell::GetOuterWindowID(uint64_t* aWindowID) { |
1481 | *aWindowID = mContentWindowID; |
1482 | return NS_OK; |
1483 | } |
1484 | |
1485 | NS_IMETHODIMPnsresult |
1486 | nsDocShell::SetChromeEventHandler(EventTarget* aChromeEventHandler) { |
1487 | mChromeEventHandler = aChromeEventHandler; |
1488 | |
1489 | if (mScriptGlobal) { |
1490 | mScriptGlobal->SetChromeEventHandler(mChromeEventHandler); |
1491 | } |
1492 | |
1493 | return NS_OK; |
1494 | } |
1495 | |
1496 | NS_IMETHODIMPnsresult |
1497 | nsDocShell::GetChromeEventHandler(EventTarget** aChromeEventHandler) { |
1498 | 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" , 1498); return NS_ERROR_INVALID_POINTER; } } while (false); |
1499 | RefPtr<EventTarget> handler = mChromeEventHandler; |
1500 | handler.forget(aChromeEventHandler); |
1501 | return NS_OK; |
1502 | } |
1503 | |
1504 | NS_IMETHODIMPnsresult |
1505 | nsDocShell::SetCurrentURIForSessionStore(nsIURI* aURI) { |
1506 | // Note that securityUI will set STATE_IS_INSECURE, even if |
1507 | // the scheme of |aURI| is "https". |
1508 | SetCurrentURI(aURI, nullptr, |
1509 | /* aFireOnLocationChange */ |
1510 | true, |
1511 | /* aIsInitialAboutBlank */ |
1512 | false, |
1513 | /* aLocationFlags */ |
1514 | nsIWebProgressListener::LOCATION_CHANGE_SESSION_STORE); |
1515 | return NS_OK; |
1516 | } |
1517 | |
1518 | bool nsDocShell::SetCurrentURI(nsIURI* aURI, nsIRequest* aRequest, |
1519 | bool aFireOnLocationChange, |
1520 | bool aIsInitialAboutBlank, |
1521 | uint32_t aLocationFlags) { |
1522 | 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" , 1522); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mIsBeingDestroyed" ")"); do { *((volatile int*)__null) = 1522; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1523 | |
1524 | 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) |
1525 | ("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) |
1526 | 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); |
1527 | |
1528 | // We don't want to send a location change when we're displaying an error |
1529 | // page, and we don't want to change our idea of "current URI" either |
1530 | if (mLoadType == LOAD_ERROR_PAGE) { |
1531 | return false; |
1532 | } |
1533 | |
1534 | bool uriIsEqual = false; |
1535 | if (!mCurrentURI || !aURI || |
1536 | NS_FAILED(mCurrentURI->Equals(aURI, &uriIsEqual))((bool)(__builtin_expect(!!(NS_FAILED_impl(mCurrentURI->Equals (aURI, &uriIsEqual))), 0))) || !uriIsEqual) { |
1537 | mTitleValidForCurrentURI = false; |
1538 | } |
1539 | |
1540 | SetCurrentURIInternal(aURI); |
1541 | |
1542 | #ifdef DEBUG1 |
1543 | mLastOpenedURI = aURI; |
1544 | #endif |
1545 | |
1546 | if (!NS_IsAboutBlank(mCurrentURI)) { |
1547 | mHasLoadedNonBlankURI = true; |
1548 | } |
1549 | |
1550 | // Don't fire onLocationChange when creating a subframe's initial about:blank |
1551 | // document, as this can happen when it's not safe for us to run script. |
1552 | if (aIsInitialAboutBlank && !mHasLoadedNonBlankURI && |
1553 | !mBrowsingContext->IsTop()) { |
1554 | 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" , 1554); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aRequest && aLocationFlags == 0" ")"); do { *((volatile int*)__null) = 1554; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1555 | return false; |
1556 | } |
1557 | |
1558 | 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" , 1558); AnnotateMozCrashReason("MOZ_ASSERT" "(" "nsContentUtils::IsSafeToRunScript()" ")"); do { *((volatile int*)__null) = 1558; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1559 | |
1560 | if (aFireOnLocationChange) { |
1561 | FireOnLocationChange(this, aRequest, aURI, aLocationFlags); |
1562 | } |
1563 | return !aFireOnLocationChange; |
1564 | } |
1565 | |
1566 | void nsDocShell::SetCurrentURIInternal(nsIURI* aURI) { |
1567 | mCurrentURI = aURI; |
1568 | if (mBrowsingContext) { |
1569 | mBrowsingContext->ClearCachedValuesOfLocations(); |
1570 | } |
1571 | } |
1572 | |
1573 | NS_IMETHODIMPnsresult |
1574 | nsDocShell::GetCharset(nsACString& aCharset) { |
1575 | aCharset.Truncate(); |
1576 | |
1577 | PresShell* presShell = GetPresShell(); |
1578 | 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" , 1578); return NS_ERROR_FAILURE; } } while (false); |
1579 | Document* doc = presShell->GetDocument(); |
1580 | 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" , 1580); return NS_ERROR_FAILURE; } } while (false); |
1581 | doc->GetDocumentCharacterSet()->Name(aCharset); |
1582 | return NS_OK; |
1583 | } |
1584 | |
1585 | NS_IMETHODIMPnsresult |
1586 | nsDocShell::ForceEncodingDetection() { |
1587 | nsCOMPtr<nsIDocumentViewer> viewer; |
1588 | GetDocViewer(getter_AddRefs(viewer)); |
1589 | if (!viewer) { |
1590 | return NS_OK; |
1591 | } |
1592 | |
1593 | Document* doc = viewer->GetDocument(); |
1594 | if (!doc || doc->WillIgnoreCharsetOverride()) { |
1595 | return NS_OK; |
1596 | } |
1597 | |
1598 | mForcedAutodetection = true; |
1599 | |
1600 | nsIURI* url = doc->GetOriginalURI(); |
1601 | bool isFileURL = url && SchemeIsFile(url); |
1602 | |
1603 | int32_t charsetSource = doc->GetDocumentCharacterSetSource(); |
1604 | auto encoding = doc->GetDocumentCharacterSet(); |
1605 | // AsHTMLDocument is valid, because we called |
1606 | // WillIgnoreCharsetOverride() above. |
1607 | if (doc->AsHTMLDocument()->IsPlainText()) { |
1608 | switch (charsetSource) { |
1609 | case kCharsetFromInitialAutoDetectionASCII: |
1610 | // Deliberately no final version |
1611 | 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); |
1612 | Telemetry::AccumulateCategorical( |
1613 | Telemetry::LABELS_ENCODING_OVERRIDE_SITUATION_TEXT::UnlabeledAscii); |
1614 | break; |
1615 | case kCharsetFromInitialAutoDetectionWouldNotHaveBeenUTF8Generic: |
1616 | case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8Generic: |
1617 | case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8GenericInitialWasASCII: |
1618 | case kCharsetFromInitialAutoDetectionWouldNotHaveBeenUTF8Content: |
1619 | case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8Content: |
1620 | case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8ContentInitialWasASCII: |
1621 | 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); |
1622 | Telemetry::AccumulateCategorical( |
1623 | Telemetry::LABELS_ENCODING_OVERRIDE_SITUATION_TEXT:: |
1624 | UnlabeledNonUtf8); |
1625 | break; |
1626 | case kCharsetFromInitialAutoDetectionWouldNotHaveBeenUTF8DependedOnTLD: |
1627 | case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8DependedOnTLD: |
1628 | case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8DependedOnTLDInitialWasASCII: |
1629 | 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); |
1630 | Telemetry::AccumulateCategorical( |
1631 | Telemetry::LABELS_ENCODING_OVERRIDE_SITUATION_TEXT:: |
1632 | UnlabeledNonUtf8TLD); |
1633 | break; |
1634 | case kCharsetFromInitialAutoDetectionWouldHaveBeenUTF8: |
1635 | case kCharsetFromFinalAutoDetectionWouldHaveBeenUTF8InitialWasASCII: |
1636 | 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); |
1637 | Telemetry::AccumulateCategorical( |
1638 | Telemetry::LABELS_ENCODING_OVERRIDE_SITUATION_TEXT::UnlabeledUtf8); |
1639 | break; |
1640 | case kCharsetFromChannel: |
1641 | if (encoding == UTF_8_ENCODING) { |
1642 | 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); |
1643 | Telemetry::AccumulateCategorical( |
1644 | Telemetry::LABELS_ENCODING_OVERRIDE_SITUATION_TEXT::ChannelUtf8); |
1645 | } else { |
1646 | 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); |
1647 | Telemetry::AccumulateCategorical( |
1648 | Telemetry::LABELS_ENCODING_OVERRIDE_SITUATION_TEXT:: |
1649 | ChannelNonUtf8); |
1650 | } |
1651 | break; |
1652 | default: |
1653 | 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); |
1654 | Telemetry::AccumulateCategorical( |
1655 | Telemetry::LABELS_ENCODING_OVERRIDE_SITUATION_TEXT::Bug); |
1656 | break; |
1657 | } |
1658 | } else { |
1659 | switch (charsetSource) { |
1660 | case kCharsetFromInitialAutoDetectionASCII: |
1661 | // Deliberately no final version |
1662 | 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); |
1663 | Telemetry::AccumulateCategorical( |
1664 | Telemetry::LABELS_ENCODING_OVERRIDE_SITUATION_HTML::UnlabeledAscii); |
1665 | break; |
1666 | case kCharsetFromInitialAutoDetectionWouldNotHaveBeenUTF8Generic: |
1667 | case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8Generic: |
1668 | case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8GenericInitialWasASCII: |
1669 | case kCharsetFromInitialAutoDetectionWouldNotHaveBeenUTF8Content: |
1670 | case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8Content: |
1671 | case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8ContentInitialWasASCII: |
1672 | 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); |
1673 | Telemetry::AccumulateCategorical( |
1674 | Telemetry::LABELS_ENCODING_OVERRIDE_SITUATION_HTML:: |
1675 | UnlabeledNonUtf8); |
1676 | break; |
1677 | case kCharsetFromInitialAutoDetectionWouldNotHaveBeenUTF8DependedOnTLD: |
1678 | case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8DependedOnTLD: |
1679 | case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8DependedOnTLDInitialWasASCII: |
1680 | 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); |
1681 | Telemetry::AccumulateCategorical( |
1682 | Telemetry::LABELS_ENCODING_OVERRIDE_SITUATION_HTML:: |
1683 | UnlabeledNonUtf8TLD); |
1684 | break; |
1685 | case kCharsetFromInitialAutoDetectionWouldHaveBeenUTF8: |
1686 | case kCharsetFromFinalAutoDetectionWouldHaveBeenUTF8InitialWasASCII: |
1687 | 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); |
1688 | Telemetry::AccumulateCategorical( |
1689 | Telemetry::LABELS_ENCODING_OVERRIDE_SITUATION_HTML::UnlabeledUtf8); |
1690 | break; |
1691 | case kCharsetFromChannel: |
1692 | if (encoding == UTF_8_ENCODING) { |
1693 | 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); |
1694 | Telemetry::AccumulateCategorical( |
1695 | Telemetry::LABELS_ENCODING_OVERRIDE_SITUATION_HTML::ChannelUtf8); |
1696 | } else { |
1697 | LOGCHARSETMENU(("HTML:ChannelNonUtf8"))do { const ::mozilla::LogModule* moz_real_module = gCharsetMenuLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print (moz_real_module, mozilla::LogLevel::Debug, "HTML:ChannelNonUtf8" ); } } while (0); |
1698 | Telemetry::AccumulateCategorical( |
1699 | Telemetry::LABELS_ENCODING_OVERRIDE_SITUATION_HTML:: |
1700 | ChannelNonUtf8); |
1701 | } |
1702 | break; |
1703 | case kCharsetFromXmlDeclaration: |
1704 | case kCharsetFromMetaTag: |
1705 | if (isFileURL) { |
1706 | 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); |
1707 | Telemetry::AccumulateCategorical( |
1708 | Telemetry::LABELS_ENCODING_OVERRIDE_SITUATION_HTML::LocalLabeled); |
1709 | } else if (encoding == UTF_8_ENCODING) { |
1710 | 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); |
1711 | Telemetry::AccumulateCategorical( |
1712 | Telemetry::LABELS_ENCODING_OVERRIDE_SITUATION_HTML::InternalUtf8); |
1713 | } else { |
1714 | 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); |
1715 | Telemetry::AccumulateCategorical( |
1716 | Telemetry::LABELS_ENCODING_OVERRIDE_SITUATION_HTML:: |
1717 | InternalNonUtf8); |
1718 | } |
1719 | break; |
1720 | default: |
1721 | 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); |
1722 | Telemetry::AccumulateCategorical( |
1723 | Telemetry::LABELS_ENCODING_OVERRIDE_SITUATION_HTML::Bug); |
1724 | break; |
1725 | } |
1726 | } |
1727 | return NS_OK; |
1728 | } |
1729 | |
1730 | void nsDocShell::SetParentCharset(const Encoding*& aCharset, |
1731 | int32_t aCharsetSource, |
1732 | nsIPrincipal* aPrincipal) { |
1733 | mParentCharset = aCharset; |
1734 | mParentCharsetSource = aCharsetSource; |
1735 | mParentCharsetPrincipal = aPrincipal; |
1736 | } |
1737 | |
1738 | void nsDocShell::GetParentCharset(const Encoding*& aCharset, |
1739 | int32_t* aCharsetSource, |
1740 | nsIPrincipal** aPrincipal) { |
1741 | aCharset = mParentCharset; |
1742 | *aCharsetSource = mParentCharsetSource; |
1743 | NS_IF_ADDREF(*aPrincipal = mParentCharsetPrincipal)ns_if_addref(*aPrincipal = mParentCharsetPrincipal); |
1744 | } |
1745 | |
1746 | NS_IMETHODIMPnsresult |
1747 | nsDocShell::GetHasTrackingContentBlocked(Promise** aPromise) { |
1748 | 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" , 1748); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPromise" ")" ); do { *((volatile int*)__null) = 1748; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1749 | |
1750 | ErrorResult rv; |
1751 | RefPtr<Document> doc(GetDocument()); |
1752 | RefPtr<Promise> retPromise = Promise::Create(doc->GetOwnerGlobal(), rv); |
1753 | 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" , 1753)) { |
1754 | return rv.StealNSResult(); |
1755 | } |
1756 | |
1757 | // Retrieve the document's content blocking events from the parent process. |
1758 | RefPtr<Document::GetContentBlockingEventsPromise> promise = |
1759 | doc->GetContentBlockingEvents(); |
1760 | if (promise) { |
1761 | promise->Then( |
1762 | GetCurrentSerialEventTarget(), __func__, |
1763 | [retPromise](const Document::GetContentBlockingEventsPromise:: |
1764 | ResolveOrRejectValue& aValue) { |
1765 | if (aValue.IsResolve()) { |
1766 | bool has = aValue.ResolveValue() & |
1767 | nsIWebProgressListener::STATE_BLOCKED_TRACKING_CONTENT; |
1768 | retPromise->MaybeResolve(has); |
1769 | } else { |
1770 | retPromise->MaybeResolve(false); |
1771 | } |
1772 | }); |
1773 | } else { |
1774 | retPromise->MaybeResolve(false); |
1775 | } |
1776 | |
1777 | retPromise.forget(aPromise); |
1778 | return NS_OK; |
1779 | } |
1780 | |
1781 | NS_IMETHODIMPnsresult |
1782 | nsDocShell::GetAllowPlugins(bool* aAllowPlugins) { |
1783 | NS_ENSURE_ARG_POINTER(aAllowPlugins)do { if ((__builtin_expect(!!(!(aAllowPlugins)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aAllowPlugins" ") failed" , nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 1783); return NS_ERROR_INVALID_POINTER; } } while (false); |
1784 | |
1785 | *aAllowPlugins = mBrowsingContext->GetAllowPlugins(); |
1786 | return NS_OK; |
1787 | } |
1788 | |
1789 | NS_IMETHODIMPnsresult |
1790 | nsDocShell::SetAllowPlugins(bool aAllowPlugins) { |
1791 | // XXX should enable or disable a plugin host |
1792 | return mBrowsingContext->SetAllowPlugins(aAllowPlugins); |
1793 | } |
1794 | |
1795 | NS_IMETHODIMPnsresult |
1796 | nsDocShell::GetCssErrorReportingEnabled(bool* aEnabled) { |
1797 | 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" , 1797); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aEnabled" ")" ); do { *((volatile int*)__null) = 1797; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1798 | *aEnabled = mCSSErrorReportingEnabled; |
1799 | return NS_OK; |
1800 | } |
1801 | |
1802 | NS_IMETHODIMPnsresult |
1803 | nsDocShell::SetCssErrorReportingEnabled(bool aEnabled) { |
1804 | mCSSErrorReportingEnabled = aEnabled; |
1805 | return NS_OK; |
1806 | } |
1807 | |
1808 | NS_IMETHODIMPnsresult |
1809 | nsDocShell::GetUsePrivateBrowsing(bool* aUsePrivateBrowsing) { |
1810 | 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" , 1810); return NS_ERROR_INVALID_POINTER; } } while (false); |
1811 | return mBrowsingContext->GetUsePrivateBrowsing(aUsePrivateBrowsing); |
1812 | } |
1813 | |
1814 | void nsDocShell::NotifyPrivateBrowsingChanged() { |
1815 | 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" , 1815); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mIsBeingDestroyed" ")"); do { *((volatile int*)__null) = 1815; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1816 | |
1817 | nsTObserverArray<nsWeakPtr>::ForwardIterator iter(mPrivacyObservers); |
1818 | while (iter.HasMore()) { |
1819 | nsWeakPtr ref = iter.GetNext(); |
1820 | nsCOMPtr<nsIPrivacyTransitionObserver> obs = do_QueryReferent(ref); |
1821 | if (!obs) { |
1822 | iter.Remove(); |
1823 | } else { |
1824 | obs->PrivateModeChanged(UsePrivateBrowsing()); |
1825 | } |
1826 | } |
1827 | } |
1828 | |
1829 | NS_IMETHODIMPnsresult |
1830 | nsDocShell::SetUsePrivateBrowsing(bool aUsePrivateBrowsing) { |
1831 | return mBrowsingContext->SetUsePrivateBrowsing(aUsePrivateBrowsing); |
1832 | } |
1833 | |
1834 | NS_IMETHODIMPnsresult |
1835 | nsDocShell::SetPrivateBrowsing(bool aUsePrivateBrowsing) { |
1836 | return mBrowsingContext->SetPrivateBrowsing(aUsePrivateBrowsing); |
1837 | } |
1838 | |
1839 | NS_IMETHODIMPnsresult |
1840 | nsDocShell::GetHasLoadedNonBlankURI(bool* aResult) { |
1841 | 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" , 1841); return NS_ERROR_INVALID_POINTER; } } while (false); |
1842 | |
1843 | *aResult = mHasLoadedNonBlankURI; |
1844 | return NS_OK; |
1845 | } |
1846 | |
1847 | NS_IMETHODIMPnsresult |
1848 | nsDocShell::GetUseRemoteTabs(bool* aUseRemoteTabs) { |
1849 | 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" , 1849); return NS_ERROR_INVALID_POINTER; } } while (false); |
1850 | return mBrowsingContext->GetUseRemoteTabs(aUseRemoteTabs); |
1851 | } |
1852 | |
1853 | NS_IMETHODIMPnsresult |
1854 | nsDocShell::SetRemoteTabs(bool aUseRemoteTabs) { |
1855 | return mBrowsingContext->SetRemoteTabs(aUseRemoteTabs); |
1856 | } |
1857 | |
1858 | NS_IMETHODIMPnsresult |
1859 | nsDocShell::GetUseRemoteSubframes(bool* aUseRemoteSubframes) { |
1860 | 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" , 1860); return NS_ERROR_INVALID_POINTER; } } while (false); |
1861 | return mBrowsingContext->GetUseRemoteSubframes(aUseRemoteSubframes); |
1862 | } |
1863 | |
1864 | NS_IMETHODIMPnsresult |
1865 | nsDocShell::SetRemoteSubframes(bool aUseRemoteSubframes) { |
1866 | return mBrowsingContext->SetRemoteSubframes(aUseRemoteSubframes); |
1867 | } |
1868 | |
1869 | NS_IMETHODIMPnsresult |
1870 | nsDocShell::AddWeakPrivacyTransitionObserver( |
1871 | nsIPrivacyTransitionObserver* aObserver) { |
1872 | nsWeakPtr weakObs = do_GetWeakReference(aObserver); |
1873 | if (!weakObs) { |
1874 | return NS_ERROR_NOT_AVAILABLE; |
1875 | } |
1876 | mPrivacyObservers.AppendElement(weakObs); |
1877 | return NS_OK; |
1878 | } |
1879 | |
1880 | NS_IMETHODIMPnsresult |
1881 | nsDocShell::AddWeakReflowObserver(nsIReflowObserver* aObserver) { |
1882 | nsWeakPtr weakObs = do_GetWeakReference(aObserver); |
1883 | if (!weakObs) { |
1884 | return NS_ERROR_FAILURE; |
1885 | } |
1886 | mReflowObservers.AppendElement(weakObs); |
1887 | return NS_OK; |
1888 | } |
1889 | |
1890 | NS_IMETHODIMPnsresult |
1891 | nsDocShell::RemoveWeakReflowObserver(nsIReflowObserver* aObserver) { |
1892 | nsWeakPtr obs = do_GetWeakReference(aObserver); |
1893 | return mReflowObservers.RemoveElement(obs) ? NS_OK : NS_ERROR_FAILURE; |
1894 | } |
1895 | |
1896 | NS_IMETHODIMPnsresult |
1897 | nsDocShell::NotifyReflowObservers(bool aInterruptible, |
1898 | DOMHighResTimeStamp aStart, |
1899 | DOMHighResTimeStamp aEnd) { |
1900 | nsTObserverArray<nsWeakPtr>::ForwardIterator iter(mReflowObservers); |
1901 | while (iter.HasMore()) { |
1902 | nsWeakPtr ref = iter.GetNext(); |
1903 | nsCOMPtr<nsIReflowObserver> obs = do_QueryReferent(ref); |
1904 | if (!obs) { |
1905 | iter.Remove(); |
1906 | } else if (aInterruptible) { |
1907 | obs->ReflowInterruptible(aStart, aEnd); |
1908 | } else { |
1909 | obs->Reflow(aStart, aEnd); |
1910 | } |
1911 | } |
1912 | return NS_OK; |
1913 | } |
1914 | |
1915 | NS_IMETHODIMPnsresult |
1916 | nsDocShell::GetAllowMetaRedirects(bool* aReturn) { |
1917 | 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" , 1917); return NS_ERROR_INVALID_POINTER; } } while (false); |
1918 | |
1919 | *aReturn = mAllowMetaRedirects; |
1920 | return NS_OK; |
1921 | } |
1922 | |
1923 | NS_IMETHODIMPnsresult |
1924 | nsDocShell::SetAllowMetaRedirects(bool aValue) { |
1925 | mAllowMetaRedirects = aValue; |
1926 | return NS_OK; |
1927 | } |
1928 | |
1929 | NS_IMETHODIMPnsresult |
1930 | nsDocShell::GetAllowSubframes(bool* aAllowSubframes) { |
1931 | 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" , 1931); return NS_ERROR_INVALID_POINTER; } } while (false); |
1932 | |
1933 | *aAllowSubframes = mAllowSubframes; |
1934 | return NS_OK; |
1935 | } |
1936 | |
1937 | NS_IMETHODIMPnsresult |
1938 | nsDocShell::SetAllowSubframes(bool aAllowSubframes) { |
1939 | mAllowSubframes = aAllowSubframes; |
1940 | return NS_OK; |
1941 | } |
1942 | |
1943 | NS_IMETHODIMPnsresult |
1944 | nsDocShell::GetAllowImages(bool* aAllowImages) { |
1945 | 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" , 1945); return NS_ERROR_INVALID_POINTER; } } while (false); |
1946 | |
1947 | *aAllowImages = mAllowImages; |
1948 | return NS_OK; |
1949 | } |
1950 | |
1951 | NS_IMETHODIMPnsresult |
1952 | nsDocShell::SetAllowImages(bool aAllowImages) { |
1953 | mAllowImages = aAllowImages; |
1954 | return NS_OK; |
1955 | } |
1956 | |
1957 | NS_IMETHODIMPnsresult |
1958 | nsDocShell::GetAllowMedia(bool* aAllowMedia) { |
1959 | *aAllowMedia = mAllowMedia; |
1960 | return NS_OK; |
1961 | } |
1962 | |
1963 | NS_IMETHODIMPnsresult |
1964 | nsDocShell::SetAllowMedia(bool aAllowMedia) { |
1965 | mAllowMedia = aAllowMedia; |
1966 | |
1967 | // Mute or unmute audio contexts attached to the inner window. |
1968 | if (mScriptGlobal) { |
1969 | if (nsPIDOMWindowInner* innerWin = mScriptGlobal->GetCurrentInnerWindow()) { |
1970 | if (aAllowMedia) { |
1971 | innerWin->UnmuteAudioContexts(); |
1972 | } else { |
1973 | innerWin->MuteAudioContexts(); |
1974 | } |
1975 | } |
1976 | } |
1977 | |
1978 | return NS_OK; |
1979 | } |
1980 | |
1981 | NS_IMETHODIMPnsresult |
1982 | nsDocShell::GetAllowDNSPrefetch(bool* aAllowDNSPrefetch) { |
1983 | *aAllowDNSPrefetch = mAllowDNSPrefetch; |
1984 | return NS_OK; |
1985 | } |
1986 | |
1987 | NS_IMETHODIMPnsresult |
1988 | nsDocShell::SetAllowDNSPrefetch(bool aAllowDNSPrefetch) { |
1989 | mAllowDNSPrefetch = aAllowDNSPrefetch; |
1990 | return NS_OK; |
1991 | } |
1992 | |
1993 | NS_IMETHODIMPnsresult |
1994 | nsDocShell::GetAllowWindowControl(bool* aAllowWindowControl) { |
1995 | *aAllowWindowControl = mAllowWindowControl; |
1996 | return NS_OK; |
1997 | } |
1998 | |
1999 | NS_IMETHODIMPnsresult |
2000 | nsDocShell::SetAllowWindowControl(bool aAllowWindowControl) { |
2001 | mAllowWindowControl = aAllowWindowControl; |
2002 | return NS_OK; |
2003 | } |
2004 | |
2005 | NS_IMETHODIMPnsresult |
2006 | nsDocShell::GetAllowContentRetargeting(bool* aAllowContentRetargeting) { |
2007 | *aAllowContentRetargeting = mBrowsingContext->GetAllowContentRetargeting(); |
2008 | return NS_OK; |
2009 | } |
2010 | |
2011 | NS_IMETHODIMPnsresult |
2012 | nsDocShell::SetAllowContentRetargeting(bool aAllowContentRetargeting) { |
2013 | BrowsingContext::Transaction txn; |
2014 | txn.SetAllowContentRetargeting(aAllowContentRetargeting); |
2015 | txn.SetAllowContentRetargetingOnChildren(aAllowContentRetargeting); |
2016 | return txn.Commit(mBrowsingContext); |
2017 | } |
2018 | |
2019 | NS_IMETHODIMPnsresult |
2020 | nsDocShell::GetAllowContentRetargetingOnChildren( |
2021 | bool* aAllowContentRetargetingOnChildren) { |
2022 | *aAllowContentRetargetingOnChildren = |
2023 | mBrowsingContext->GetAllowContentRetargetingOnChildren(); |
2024 | return NS_OK; |
2025 | } |
2026 | |
2027 | NS_IMETHODIMPnsresult |
2028 | nsDocShell::SetAllowContentRetargetingOnChildren( |
2029 | bool aAllowContentRetargetingOnChildren) { |
2030 | return mBrowsingContext->SetAllowContentRetargetingOnChildren( |
2031 | aAllowContentRetargetingOnChildren); |
2032 | } |
2033 | |
2034 | NS_IMETHODIMPnsresult |
2035 | nsDocShell::GetMayEnableCharacterEncodingMenu( |
2036 | bool* aMayEnableCharacterEncodingMenu) { |
2037 | *aMayEnableCharacterEncodingMenu = false; |
2038 | if (!mDocumentViewer) { |
2039 | return NS_OK; |
2040 | } |
2041 | Document* doc = mDocumentViewer->GetDocument(); |
2042 | if (!doc) { |
2043 | return NS_OK; |
2044 | } |
2045 | if (doc->WillIgnoreCharsetOverride()) { |
2046 | return NS_OK; |
2047 | } |
2048 | |
2049 | *aMayEnableCharacterEncodingMenu = true; |
2050 | return NS_OK; |
2051 | } |
2052 | |
2053 | NS_IMETHODIMPnsresult |
2054 | nsDocShell::GetAllDocShellsInSubtree(int32_t aItemType, |
2055 | DocShellEnumeratorDirection aDirection, |
2056 | nsTArray<RefPtr<nsIDocShell>>& aResult) { |
2057 | aResult.Clear(); |
2058 | |
2059 | nsDocShellEnumerator docShellEnum( |
2060 | (aDirection == ENUMERATE_FORWARDS) |
2061 | ? nsDocShellEnumerator::EnumerationDirection::Forwards |
2062 | : nsDocShellEnumerator::EnumerationDirection::Backwards, |
2063 | aItemType, *this); |
2064 | |
2065 | nsresult rv = docShellEnum.BuildDocShellArray(aResult); |
2066 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
2067 | return rv; |
2068 | } |
2069 | |
2070 | return NS_OK; |
2071 | } |
2072 | |
2073 | NS_IMETHODIMPnsresult |
2074 | nsDocShell::GetAppType(AppType* aAppType) { |
2075 | *aAppType = mAppType; |
2076 | return NS_OK; |
2077 | } |
2078 | |
2079 | NS_IMETHODIMPnsresult |
2080 | nsDocShell::SetAppType(AppType aAppType) { |
2081 | mAppType = aAppType; |
2082 | return NS_OK; |
2083 | } |
2084 | |
2085 | NS_IMETHODIMPnsresult |
2086 | nsDocShell::GetAllowAuth(bool* aAllowAuth) { |
2087 | *aAllowAuth = mAllowAuth; |
2088 | return NS_OK; |
2089 | } |
2090 | |
2091 | NS_IMETHODIMPnsresult |
2092 | nsDocShell::SetAllowAuth(bool aAllowAuth) { |
2093 | mAllowAuth = aAllowAuth; |
2094 | return NS_OK; |
2095 | } |
2096 | |
2097 | NS_IMETHODIMPnsresult |
2098 | nsDocShell::GetZoom(float* aZoom) { |
2099 | 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" , 2099); return NS_ERROR_INVALID_POINTER; } } while (false); |
2100 | *aZoom = 1.0f; |
2101 | return NS_OK; |
2102 | } |
2103 | |
2104 | NS_IMETHODIMPnsresult |
2105 | nsDocShell::SetZoom(float aZoom) { return NS_ERROR_NOT_IMPLEMENTED; } |
2106 | |
2107 | NS_IMETHODIMPnsresult |
2108 | nsDocShell::GetBusyFlags(BusyFlags* aBusyFlags) { |
2109 | 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" , 2109); return NS_ERROR_INVALID_POINTER; } } while (false); |
2110 | |
2111 | *aBusyFlags = mBusyFlags; |
2112 | return NS_OK; |
2113 | } |
2114 | |
2115 | NS_IMETHODIMPnsresult |
2116 | nsDocShell::TabToTreeOwner(bool aForward, bool aForDocumentNavigation, |
2117 | bool* aTookFocus) { |
2118 | NS_ENSURE_ARG_POINTER(aTookFocus)do { if ((__builtin_expect(!!(!(aTookFocus)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aTookFocus" ") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 2118); return NS_ERROR_INVALID_POINTER; } } while (false); |
2119 | |
2120 | nsCOMPtr<nsIWebBrowserChromeFocus> chromeFocus = do_GetInterface(mTreeOwner); |
2121 | if (chromeFocus) { |
2122 | if (aForward) { |
2123 | *aTookFocus = |
2124 | NS_SUCCEEDED(chromeFocus->FocusNextElement(aForDocumentNavigation))((bool)(__builtin_expect(!!(!NS_FAILED_impl(chromeFocus->FocusNextElement (aForDocumentNavigation))), 1))); |
2125 | } else { |
2126 | *aTookFocus = |
2127 | NS_SUCCEEDED(chromeFocus->FocusPrevElement(aForDocumentNavigation))((bool)(__builtin_expect(!!(!NS_FAILED_impl(chromeFocus->FocusPrevElement (aForDocumentNavigation))), 1))); |
2128 | } |
2129 | } else { |
2130 | *aTookFocus = false; |
2131 | } |
2132 | |
2133 | return NS_OK; |
2134 | } |
2135 | |
2136 | NS_IMETHODIMPnsresult |
2137 | nsDocShell::GetLoadURIDelegate(nsILoadURIDelegate** aLoadURIDelegate) { |
2138 | nsCOMPtr<nsILoadURIDelegate> delegate = GetLoadURIDelegate(); |
2139 | delegate.forget(aLoadURIDelegate); |
2140 | return NS_OK; |
2141 | } |
2142 | |
2143 | already_AddRefed<nsILoadURIDelegate> nsDocShell::GetLoadURIDelegate() { |
2144 | if (nsCOMPtr<nsILoadURIDelegate> result = |
2145 | do_QueryActor("LoadURIDelegate", GetDocument())) { |
2146 | return result.forget(); |
2147 | } |
2148 | |
2149 | return nullptr; |
2150 | } |
2151 | |
2152 | NS_IMETHODIMPnsresult |
2153 | nsDocShell::GetUseErrorPages(bool* aUseErrorPages) { |
2154 | *aUseErrorPages = mBrowsingContext->GetUseErrorPages(); |
2155 | return NS_OK; |
2156 | } |
2157 | |
2158 | NS_IMETHODIMPnsresult |
2159 | nsDocShell::SetUseErrorPages(bool aUseErrorPages) { |
2160 | return mBrowsingContext->SetUseErrorPages(aUseErrorPages); |
2161 | } |
2162 | |
2163 | NS_IMETHODIMPnsresult |
2164 | nsDocShell::GetPreviousEntryIndex(int32_t* aPreviousEntryIndex) { |
2165 | *aPreviousEntryIndex = mPreviousEntryIndex; |
2166 | return NS_OK; |
2167 | } |
2168 | |
2169 | NS_IMETHODIMPnsresult |
2170 | nsDocShell::GetLoadedEntryIndex(int32_t* aLoadedEntryIndex) { |
2171 | *aLoadedEntryIndex = mLoadedEntryIndex; |
2172 | return NS_OK; |
2173 | } |
2174 | |
2175 | NS_IMETHODIMPnsresult |
2176 | nsDocShell::HistoryPurged(int32_t aNumEntries) { |
2177 | // These indices are used for fastback cache eviction, to determine |
2178 | // which session history entries are candidates for content viewer |
2179 | // eviction. We need to adjust by the number of entries that we |
2180 | // just purged from history, so that we look at the right session history |
2181 | // entries during eviction. |
2182 | mPreviousEntryIndex = std::max(-1, mPreviousEntryIndex - aNumEntries); |
2183 | mLoadedEntryIndex = std::max(0, mLoadedEntryIndex - aNumEntries); |
2184 | |
2185 | for (auto* child : mChildList.ForwardRange()) { |
2186 | nsCOMPtr<nsIDocShell> shell = do_QueryObject(child); |
2187 | if (shell) { |
2188 | shell->HistoryPurged(aNumEntries); |
2189 | } |
2190 | } |
2191 | |
2192 | return NS_OK; |
2193 | } |
2194 | |
2195 | void nsDocShell::TriggerParentCheckDocShellIsEmpty() { |
2196 | if (RefPtr<nsDocShell> parent = GetInProcessParentDocshell()) { |
2197 | parent->DocLoaderIsEmpty(true); |
2198 | } |
2199 | if (GetBrowsingContext()->IsContentSubframe() && |
2200 | !GetBrowsingContext()->GetParent()->IsInProcess()) { |
2201 | if (BrowserChild* browserChild = BrowserChild::GetFrom(this)) { |
2202 | mozilla::Unused << browserChild->SendMaybeFireEmbedderLoadEvents( |
2203 | EmbedderElementEventType::NoEvent); |
2204 | } |
2205 | } |
2206 | } |
2207 | |
2208 | nsresult nsDocShell::HistoryEntryRemoved(int32_t aIndex) { |
2209 | // These indices are used for fastback cache eviction, to determine |
2210 | // which session history entries are candidates for content viewer |
2211 | // eviction. We need to adjust by the number of entries that we |
2212 | // just purged from history, so that we look at the right session history |
2213 | // entries during eviction. |
2214 | if (aIndex == mPreviousEntryIndex) { |
2215 | mPreviousEntryIndex = -1; |
2216 | } else if (aIndex < mPreviousEntryIndex) { |
2217 | --mPreviousEntryIndex; |
2218 | } |
2219 | if (mLoadedEntryIndex == aIndex) { |
2220 | mLoadedEntryIndex = 0; |
2221 | } else if (aIndex < mLoadedEntryIndex) { |
2222 | --mLoadedEntryIndex; |
2223 | } |
2224 | |
2225 | for (auto* child : mChildList.ForwardRange()) { |
2226 | nsCOMPtr<nsIDocShell> shell = do_QueryObject(child); |
2227 | if (shell) { |
2228 | static_cast<nsDocShell*>(shell.get())->HistoryEntryRemoved(aIndex); |
2229 | } |
2230 | } |
2231 | |
2232 | return NS_OK; |
2233 | } |
2234 | |
2235 | nsresult nsDocShell::Now(DOMHighResTimeStamp* aWhen) { |
2236 | *aWhen = (TimeStamp::Now() - TimeStamp::ProcessCreation()).ToMilliseconds(); |
2237 | return NS_OK; |
2238 | } |
2239 | |
2240 | NS_IMETHODIMPnsresult |
2241 | nsDocShell::SetWindowDraggingAllowed(bool aValue) { |
2242 | RefPtr<nsDocShell> parent = GetInProcessParentDocshell(); |
2243 | if (!aValue && mItemType == typeChrome && !parent) { |
2244 | // Window dragging is always allowed for top level |
2245 | // chrome docshells. |
2246 | return NS_ERROR_FAILURE; |
2247 | } |
2248 | mWindowDraggingAllowed = aValue; |
2249 | return NS_OK; |
2250 | } |
2251 | |
2252 | NS_IMETHODIMPnsresult |
2253 | nsDocShell::GetWindowDraggingAllowed(bool* aValue) { |
2254 | // window dragging regions in CSS (-moz-window-drag:drag) |
2255 | // can be slow. Default behavior is to only allow it for |
2256 | // chrome top level windows. |
2257 | RefPtr<nsDocShell> parent = GetInProcessParentDocshell(); |
2258 | if (mItemType == typeChrome && !parent) { |
2259 | // Top level chrome window |
2260 | *aValue = true; |
2261 | } else { |
2262 | *aValue = mWindowDraggingAllowed; |
2263 | } |
2264 | return NS_OK; |
2265 | } |
2266 | |
2267 | NS_IMETHODIMPnsresult |
2268 | nsDocShell::GetCurrentDocumentChannel(nsIChannel** aResult) { |
2269 | NS_IF_ADDREF(*aResult = GetCurrentDocChannel())ns_if_addref(*aResult = GetCurrentDocChannel()); |
2270 | return NS_OK; |
2271 | } |
2272 | |
2273 | nsIChannel* nsDocShell::GetCurrentDocChannel() { |
2274 | if (mDocumentViewer) { |
2275 | Document* doc = mDocumentViewer->GetDocument(); |
2276 | if (doc) { |
2277 | return doc->GetChannel(); |
2278 | } |
2279 | } |
2280 | return nullptr; |
2281 | } |
2282 | |
2283 | NS_IMETHODIMPnsresult |
2284 | nsDocShell::AddWeakScrollObserver(nsIScrollObserver* aObserver) { |
2285 | nsWeakPtr weakObs = do_GetWeakReference(aObserver); |
2286 | if (!weakObs) { |
2287 | return NS_ERROR_FAILURE; |
2288 | } |
2289 | mScrollObservers.AppendElement(weakObs); |
2290 | return NS_OK; |
2291 | } |
2292 | |
2293 | NS_IMETHODIMPnsresult |
2294 | nsDocShell::RemoveWeakScrollObserver(nsIScrollObserver* aObserver) { |
2295 | nsWeakPtr obs = do_GetWeakReference(aObserver); |
2296 | return mScrollObservers.RemoveElement(obs) ? NS_OK : NS_ERROR_FAILURE; |
2297 | } |
2298 | |
2299 | void nsDocShell::NotifyAsyncPanZoomStarted() { |
2300 | nsTObserverArray<nsWeakPtr>::ForwardIterator iter(mScrollObservers); |
2301 | while (iter.HasMore()) { |
2302 | nsWeakPtr ref = iter.GetNext(); |
2303 | nsCOMPtr<nsIScrollObserver> obs = do_QueryReferent(ref); |
2304 | if (obs) { |
2305 | obs->AsyncPanZoomStarted(); |
2306 | } else { |
2307 | iter.Remove(); |
2308 | } |
2309 | } |
2310 | } |
2311 | |
2312 | void nsDocShell::NotifyAsyncPanZoomStopped() { |
2313 | nsTObserverArray<nsWeakPtr>::ForwardIterator iter(mScrollObservers); |
2314 | while (iter.HasMore()) { |
2315 | nsWeakPtr ref = iter.GetNext(); |
2316 | nsCOMPtr<nsIScrollObserver> obs = do_QueryReferent(ref); |
2317 | if (obs) { |
2318 | obs->AsyncPanZoomStopped(); |
2319 | } else { |
2320 | iter.Remove(); |
2321 | } |
2322 | } |
2323 | } |
2324 | |
2325 | NS_IMETHODIMPnsresult |
2326 | nsDocShell::NotifyScrollObservers() { |
2327 | nsTObserverArray<nsWeakPtr>::ForwardIterator iter(mScrollObservers); |
2328 | while (iter.HasMore()) { |
2329 | nsWeakPtr ref = iter.GetNext(); |
2330 | nsCOMPtr<nsIScrollObserver> obs = do_QueryReferent(ref); |
2331 | if (obs) { |
2332 | obs->ScrollPositionChanged(); |
2333 | } else { |
2334 | iter.Remove(); |
2335 | } |
2336 | } |
2337 | return NS_OK; |
2338 | } |
2339 | |
2340 | //***************************************************************************** |
2341 | // nsDocShell::nsIDocShellTreeItem |
2342 | //***************************************************************************** |
2343 | |
2344 | NS_IMETHODIMPnsresult |
2345 | nsDocShell::GetName(nsAString& aName) { |
2346 | aName = mBrowsingContext->Name(); |
2347 | return NS_OK; |
2348 | } |
2349 | |
2350 | NS_IMETHODIMPnsresult |
2351 | nsDocShell::SetName(const nsAString& aName) { |
2352 | return mBrowsingContext->SetName(aName); |
2353 | } |
2354 | |
2355 | NS_IMETHODIMPnsresult |
2356 | nsDocShell::NameEquals(const nsAString& aName, bool* aResult) { |
2357 | 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" , 2357); return NS_ERROR_INVALID_POINTER; } } while (false); |
2358 | *aResult = mBrowsingContext->NameEquals(aName); |
2359 | return NS_OK; |
2360 | } |
2361 | |
2362 | NS_IMETHODIMPnsresult |
2363 | nsDocShell::GetCustomUserAgent(nsAString& aCustomUserAgent) { |
2364 | mBrowsingContext->GetCustomUserAgent(aCustomUserAgent); |
2365 | return NS_OK; |
2366 | } |
2367 | |
2368 | NS_IMETHODIMPnsresult |
2369 | nsDocShell::SetCustomUserAgent(const nsAString& aCustomUserAgent) { |
2370 | if (mWillChangeProcess) { |
2371 | 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" , 2371); |
2372 | return NS_ERROR_FAILURE; |
2373 | } |
2374 | |
2375 | return mBrowsingContext->SetCustomUserAgent(aCustomUserAgent); |
2376 | } |
2377 | |
2378 | NS_IMETHODIMPnsresult |
2379 | nsDocShell::ClearCachedPlatform() { |
2380 | nsCOMPtr<nsPIDOMWindowInner> win = |
2381 | mScriptGlobal ? mScriptGlobal->GetCurrentInnerWindow() : nullptr; |
2382 | if (win) { |
2383 | Navigator* navigator = win->Navigator(); |
2384 | if (navigator) { |
2385 | navigator->ClearPlatformCache(); |
2386 | } |
2387 | } |
2388 | |
2389 | return NS_OK; |
2390 | } |
2391 | |
2392 | NS_IMETHODIMPnsresult |
2393 | nsDocShell::ClearCachedUserAgent() { |
2394 | nsCOMPtr<nsPIDOMWindowInner> win = |
2395 | mScriptGlobal ? mScriptGlobal->GetCurrentInnerWindow() : nullptr; |
2396 | if (win) { |
2397 | Navigator* navigator = win->Navigator(); |
2398 | if (navigator) { |
2399 | navigator->ClearUserAgentCache(); |
2400 | } |
2401 | } |
2402 | |
2403 | return NS_OK; |
2404 | } |
2405 | |
2406 | NS_IMETHODIMPnsresult |
2407 | nsDocShell::GetMetaViewportOverride( |
2408 | MetaViewportOverride* aMetaViewportOverride) { |
2409 | NS_ENSURE_ARG_POINTER(aMetaViewportOverride)do { if ((__builtin_expect(!!(!(aMetaViewportOverride)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aMetaViewportOverride" ") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 2409); return NS_ERROR_INVALID_POINTER; } } while (false); |
2410 | |
2411 | *aMetaViewportOverride = mMetaViewportOverride; |
2412 | return NS_OK; |
2413 | } |
2414 | |
2415 | NS_IMETHODIMPnsresult |
2416 | nsDocShell::SetMetaViewportOverride( |
2417 | MetaViewportOverride aMetaViewportOverride) { |
2418 | // We don't have a way to verify this coming from Javascript, so this check is |
2419 | // still needed. |
2420 | if (!(aMetaViewportOverride == META_VIEWPORT_OVERRIDE_NONE || |
2421 | aMetaViewportOverride == META_VIEWPORT_OVERRIDE_ENABLED || |
2422 | aMetaViewportOverride == META_VIEWPORT_OVERRIDE_DISABLED)) { |
2423 | return NS_ERROR_INVALID_ARG; |
2424 | } |
2425 | |
2426 | mMetaViewportOverride = aMetaViewportOverride; |
2427 | |
2428 | // Inform our presShell that it needs to re-check its need for a viewport |
2429 | // override. |
2430 | if (RefPtr<PresShell> presShell = GetPresShell()) { |
2431 | presShell->MaybeRecreateMobileViewportManager(true); |
2432 | } |
2433 | |
2434 | return NS_OK; |
2435 | } |
2436 | |
2437 | /* virtual */ |
2438 | int32_t nsDocShell::ItemType() { return mItemType; } |
2439 | |
2440 | NS_IMETHODIMPnsresult |
2441 | nsDocShell::GetItemType(int32_t* aItemType) { |
2442 | 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" , 2442); return NS_ERROR_INVALID_POINTER; } } while (false); |
2443 | |
2444 | 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" , 2445); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "(mBrowsingContext->IsContent() ? typeContent : typeChrome) == mItemType" ")"); do { *((volatile int*)__null) = 2445; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
2445 | (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" , 2445); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "(mBrowsingContext->IsContent() ? typeContent : typeChrome) == mItemType" ")"); do { *((volatile int*)__null) = 2445; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2446 | *aItemType = mItemType; |
2447 | return NS_OK; |
2448 | } |
2449 | |
2450 | NS_IMETHODIMPnsresult |
2451 | nsDocShell::GetInProcessParent(nsIDocShellTreeItem** aParent) { |
2452 | if (!mParent) { |
2453 | *aParent = nullptr; |
2454 | } else { |
2455 | CallQueryInterface(mParent, aParent); |
2456 | } |
2457 | // Note that in the case when the parent is not an nsIDocShellTreeItem we |
2458 | // don't want to throw; we just want to return null. |
2459 | return NS_OK; |
2460 | } |
2461 | |
2462 | // With Fission, related nsDocShell objects may exist in a different process. In |
2463 | // that case, this method will return `nullptr`, despite a parent nsDocShell |
2464 | // object existing. |
2465 | // |
2466 | // Prefer using `BrowsingContext::Parent()`, which will succeed even if the |
2467 | // parent entry is not in the current process, and handle the case where the |
2468 | // parent nsDocShell is inaccessible. |
2469 | already_AddRefed<nsDocShell> nsDocShell::GetInProcessParentDocshell() { |
2470 | nsCOMPtr<nsIDocShell> docshell = do_QueryInterface(GetAsSupports(mParent)); |
2471 | return docshell.forget().downcast<nsDocShell>(); |
2472 | } |
2473 | |
2474 | void nsDocShell::MaybeCreateInitialClientSource(nsIPrincipal* aPrincipal) { |
2475 | 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" , 2475); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mIsBeingDestroyed" ")"); do { *((volatile int*)__null) = 2475; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2476 | |
2477 | // If there is an existing document then there is no need to create |
2478 | // a client for a future initial about:blank document. |
2479 | if (mScriptGlobal && mScriptGlobal->GetCurrentInnerWindow() && |
2480 | mScriptGlobal->GetCurrentInnerWindow()->GetExtantDoc()) { |
2481 | 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" , 2482); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "mScriptGlobal->GetCurrentInnerWindow()->GetClientInfo().isSome()" ")"); do { *((volatile int*)__null) = 2482; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
2482 | 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" , 2482); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "mScriptGlobal->GetCurrentInnerWindow()->GetClientInfo().isSome()" ")"); do { *((volatile int*)__null) = 2482; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2483 | 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" , 2483); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "!mInitialClientSource" ")"); do { *((volatile int*)__null) = 2483; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2484 | return; |
2485 | } |
2486 | |
2487 | // Don't recreate the initial client source. We call this multiple times |
2488 | // when DoChannelLoad() is called before CreateAboutBlankDocumentViewer. |
2489 | if (mInitialClientSource) { |
2490 | return; |
2491 | } |
2492 | |
2493 | // Don't pre-allocate the client when we are sandboxed. The inherited |
2494 | // principal does not take sandboxing into account. |
2495 | // TODO: Refactor sandboxing principal code out so we can use it here. |
2496 | if (!aPrincipal && mBrowsingContext->GetSandboxFlags()) { |
2497 | return; |
2498 | } |
2499 | |
2500 | // We cannot get inherited foreign partitioned principal here. Instead, we |
2501 | // directly check which principal we want to inherit for the service worker. |
2502 | nsIPrincipal* principal = |
2503 | aPrincipal |
2504 | ? aPrincipal |
2505 | : GetInheritedPrincipal( |
2506 | false, StoragePrincipalHelper:: |
2507 | ShouldUsePartitionPrincipalForServiceWorker(this)); |
2508 | |
2509 | // Sometimes there is no principal available when we are called from |
2510 | // CreateAboutBlankDocumentViewer. For example, sometimes the principal |
2511 | // is only extracted from the load context after the document is created |
2512 | // in Document::ResetToURI(). Ideally we would do something similar |
2513 | // here, but for now lets just avoid the issue by not preallocating the |
2514 | // client. |
2515 | if (!principal) { |
2516 | return; |
2517 | } |
2518 | |
2519 | nsCOMPtr<nsPIDOMWindowOuter> win = GetWindow(); |
2520 | if (!win) { |
2521 | return; |
2522 | } |
2523 | |
2524 | mInitialClientSource = ClientManager::CreateSource( |
2525 | ClientType::Window, GetMainThreadSerialEventTarget(), principal); |
2526 | 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" , 2526); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "mInitialClientSource" ")"); do { *((volatile int*)__null) = 2526; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2527 | |
2528 | // Mark the initial client as execution ready, but owned by the docshell. |
2529 | // If the client is actually used this will cause ClientSource to force |
2530 | // the creation of the initial about:blank by calling |
2531 | // nsDocShell::GetDocument(). |
2532 | mInitialClientSource->DocShellExecutionReady(this); |
2533 | |
2534 | // Next, check to see if the parent is controlled. |
2535 | nsCOMPtr<nsIDocShell> parent = GetInProcessParentDocshell(); |
2536 | nsPIDOMWindowOuter* parentOuter = parent ? parent->GetWindow() : nullptr; |
2537 | nsPIDOMWindowInner* parentInner = |
2538 | parentOuter ? parentOuter->GetCurrentInnerWindow() : nullptr; |
2539 | if (!parentInner) { |
2540 | return; |
2541 | } |
2542 | |
2543 | nsCOMPtr<nsIURI> uri; |
2544 | 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" , 2544); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false" ") (" "NS_SUCCEEDED(NS_NewURI(getter_AddRefs(uri), \"about:blank\"_ns))" ")"); do { *((volatile int*)__null) = 2544; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); |
2545 | |
2546 | // We're done if there is no parent controller or if this docshell |
2547 | // is not permitted to control for some reason. |
2548 | Maybe<ServiceWorkerDescriptor> controller(parentInner->GetController()); |
2549 | if (controller.isNothing() || |
2550 | !ServiceWorkerAllowedToControlWindow(principal, uri)) { |
2551 | return; |
2552 | } |
2553 | |
2554 | mInitialClientSource->InheritController(controller.ref()); |
2555 | } |
2556 | |
2557 | Maybe<ClientInfo> nsDocShell::GetInitialClientInfo() const { |
2558 | if (mInitialClientSource) { |
2559 | Maybe<ClientInfo> result; |
2560 | result.emplace(mInitialClientSource->Info()); |
2561 | return result; |
2562 | } |
2563 | |
2564 | nsPIDOMWindowInner* innerWindow = |
2565 | mScriptGlobal ? mScriptGlobal->GetCurrentInnerWindow() : nullptr; |
2566 | Document* doc = innerWindow ? innerWindow->GetExtantDoc() : nullptr; |
2567 | |
2568 | if (!doc || !doc->IsInitialDocument()) { |
2569 | return Maybe<ClientInfo>(); |
2570 | } |
2571 | |
2572 | return innerWindow->GetClientInfo(); |
2573 | } |
2574 | |
2575 | nsresult nsDocShell::SetDocLoaderParent(nsDocLoader* aParent) { |
2576 | bool wasFrame = IsSubframe(); |
2577 | |
2578 | nsresult rv = nsDocLoader::SetDocLoaderParent(aParent); |
2579 | 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" , 2579); return rv; } } while (false); |
2580 | |
2581 | nsCOMPtr<nsISupportsPriority> priorityGroup = do_QueryInterface(mLoadGroup); |
2582 | if (wasFrame != IsSubframe() && priorityGroup) { |
2583 | priorityGroup->AdjustPriority(wasFrame ? -1 : 1); |
2584 | } |
2585 | |
2586 | // Curse ambiguous nsISupports inheritance! |
2587 | nsISupports* parent = GetAsSupports(aParent); |
2588 | |
2589 | // If parent is another docshell, we inherit all their flags for |
2590 | // allowing plugins, scripting etc. |
2591 | bool value; |
2592 | nsCOMPtr<nsIDocShell> parentAsDocShell(do_QueryInterface(parent)); |
2593 | |
2594 | if (parentAsDocShell) { |
2595 | if (mAllowMetaRedirects && |
2596 | NS_SUCCEEDED(parentAsDocShell->GetAllowMetaRedirects(&value))((bool)(__builtin_expect(!!(!NS_FAILED_impl(parentAsDocShell-> GetAllowMetaRedirects(&value))), 1)))) { |
2597 | SetAllowMetaRedirects(value); |
2598 | } |
2599 | if (mAllowSubframes && |
2600 | NS_SUCCEEDED(parentAsDocShell->GetAllowSubframes(&value))((bool)(__builtin_expect(!!(!NS_FAILED_impl(parentAsDocShell-> GetAllowSubframes(&value))), 1)))) { |
2601 | SetAllowSubframes(value); |
2602 | } |
2603 | if (mAllowImages && |
2604 | NS_SUCCEEDED(parentAsDocShell->GetAllowImages(&value))((bool)(__builtin_expect(!!(!NS_FAILED_impl(parentAsDocShell-> GetAllowImages(&value))), 1)))) { |
2605 | SetAllowImages(value); |
2606 | } |
2607 | SetAllowMedia(parentAsDocShell->GetAllowMedia() && mAllowMedia); |
2608 | if (mAllowWindowControl && |
2609 | NS_SUCCEEDED(parentAsDocShell->GetAllowWindowControl(&value))((bool)(__builtin_expect(!!(!NS_FAILED_impl(parentAsDocShell-> GetAllowWindowControl(&value))), 1)))) { |
2610 | SetAllowWindowControl(value); |
2611 | } |
2612 | if (NS_FAILED(parentAsDocShell->GetAllowDNSPrefetch(&value))((bool)(__builtin_expect(!!(NS_FAILED_impl(parentAsDocShell-> GetAllowDNSPrefetch(&value))), 0)))) { |
2613 | value = false; |
2614 | } |
2615 | SetAllowDNSPrefetch(mAllowDNSPrefetch && value); |
2616 | |
2617 | // We don't need to inherit metaViewportOverride, because the viewport |
2618 | // is only relevant for the outermost nsDocShell, not for any iframes |
2619 | // like this that might be embedded within it. |
2620 | } |
2621 | |
2622 | nsCOMPtr<nsIURIContentListener> parentURIListener(do_GetInterface(parent)); |
2623 | if (parentURIListener) { |
2624 | mContentListener->SetParentContentListener(parentURIListener); |
2625 | } |
2626 | |
2627 | return NS_OK; |
2628 | } |
2629 | |
2630 | void nsDocShell::MaybeRestoreWindowName() { |
2631 | if (!StaticPrefs::privacy_window_name_update_enabled()) { |
2632 | return; |
2633 | } |
2634 | |
2635 | // We only restore window.name for the top-level content. |
2636 | if (!mBrowsingContext->IsTopContent()) { |
2637 | return; |
2638 | } |
2639 | |
2640 | nsAutoString name; |
2641 | |
2642 | // Following implements https://html.spec.whatwg.org/#history-traversal: |
2643 | // Step 4.4. Check if the loading entry has a name. |
2644 | |
2645 | if (mLSHE) { |
2646 | mLSHE->GetName(name); |
2647 | } |
2648 | |
2649 | if (mLoadingEntry) { |
2650 | name = mLoadingEntry->mInfo.GetName(); |
2651 | } |
2652 | |
2653 | if (name.IsEmpty()) { |
2654 | return; |
2655 | } |
2656 | |
2657 | // Step 4.4.1. Set the name to the browsing context. |
2658 | Unused << mBrowsingContext->SetName(name); |
2659 | |
2660 | // Step 4.4.2. Clear the name of all entries that are contiguous and |
2661 | // same-origin with the loading entry. |
2662 | if (mLSHE) { |
2663 | nsSHistory::WalkContiguousEntries( |
2664 | mLSHE, [](nsISHEntry* aEntry) { aEntry->SetName(EmptyString()); }); |
2665 | } |
2666 | |
2667 | if (mLoadingEntry) { |
2668 | // Clear the name of the session entry in the child side. For parent side, |
2669 | // the clearing will be done when we commit the history to the parent. |
2670 | mLoadingEntry->mInfo.SetName(EmptyString()); |
2671 | } |
2672 | } |
2673 | |
2674 | void nsDocShell::StoreWindowNameToSHEntries() { |
2675 | 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" , 2675); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mBrowsingContext->IsTopContent()" ")"); do { *((volatile int*)__null) = 2675; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2676 | |
2677 | nsAutoString name; |
2678 | mBrowsingContext->GetName(name); |
2679 | |
2680 | if (mOSHE) { |
2681 | nsSHistory::WalkContiguousEntries( |
2682 | mOSHE, [&](nsISHEntry* aEntry) { aEntry->SetName(name); }); |
2683 | } |
2684 | |
2685 | if (mozilla::SessionHistoryInParent()) { |
2686 | if (XRE_IsParentProcess()) { |
2687 | SessionHistoryEntry* entry = |
2688 | mBrowsingContext->Canonical()->GetActiveSessionHistoryEntry(); |
2689 | if (entry) { |
2690 | nsSHistory::WalkContiguousEntries( |
2691 | entry, [&](nsISHEntry* aEntry) { aEntry->SetName(name); }); |
2692 | } |
2693 | } else { |
2694 | // Ask parent process to store the name in entries. |
2695 | mozilla::Unused |
2696 | << ContentChild::GetSingleton() |
2697 | ->SendSessionHistoryEntryStoreWindowNameInContiguousEntries( |
2698 | mBrowsingContext, name); |
2699 | } |
2700 | } |
2701 | } |
2702 | |
2703 | NS_IMETHODIMPnsresult |
2704 | nsDocShell::GetInProcessSameTypeParent(nsIDocShellTreeItem** aParent) { |
2705 | if (BrowsingContext* parentBC = mBrowsingContext->GetParent()) { |
2706 | *aParent = do_AddRef(parentBC->GetDocShell()).take(); |
2707 | } |
2708 | return NS_OK; |
2709 | } |
2710 | |
2711 | NS_IMETHODIMPnsresult |
2712 | nsDocShell::GetInProcessRootTreeItem(nsIDocShellTreeItem** aRootTreeItem) { |
2713 | 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" , 2713); return NS_ERROR_INVALID_POINTER; } } while (false); |
2714 | |
2715 | RefPtr<nsDocShell> root = this; |
2716 | RefPtr<nsDocShell> parent = root->GetInProcessParentDocshell(); |
2717 | while (parent) { |
2718 | root = parent; |
2719 | parent = root->GetInProcessParentDocshell(); |
2720 | } |
2721 | |
2722 | root.forget(aRootTreeItem); |
2723 | return NS_OK; |
2724 | } |
2725 | |
2726 | NS_IMETHODIMPnsresult |
2727 | nsDocShell::GetInProcessSameTypeRootTreeItem( |
2728 | nsIDocShellTreeItem** aRootTreeItem) { |
2729 | 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" , 2729); return NS_ERROR_INVALID_POINTER; } } while (false); |
2730 | *aRootTreeItem = static_cast<nsIDocShellTreeItem*>(this); |
2731 | |
2732 | nsCOMPtr<nsIDocShellTreeItem> parent; |
2733 | 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" , 2734); return NS_ERROR_FAILURE; } } while (false) |
2734 | 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" , 2734); return NS_ERROR_FAILURE; } } while (false); |
2735 | while (parent) { |
2736 | *aRootTreeItem = parent; |
2737 | 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" , 2739); return NS_ERROR_FAILURE; } } while (false) |
2738 | (*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" , 2739); return NS_ERROR_FAILURE; } } while (false) |
2739 | 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" , 2739); return NS_ERROR_FAILURE; } } while (false); |
2740 | } |
2741 | NS_ADDREF(*aRootTreeItem)(*aRootTreeItem)->AddRef(); |
2742 | return NS_OK; |
2743 | } |
2744 | |
2745 | NS_IMETHODIMPnsresult |
2746 | nsDocShell::GetTreeOwner(nsIDocShellTreeOwner** aTreeOwner) { |
2747 | 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" , 2747); return NS_ERROR_INVALID_POINTER; } } while (false); |
2748 | |
2749 | *aTreeOwner = mTreeOwner; |
2750 | NS_IF_ADDREF(*aTreeOwner)ns_if_addref(*aTreeOwner); |
2751 | return NS_OK; |
2752 | } |
2753 | |
2754 | NS_IMETHODIMPnsresult |
2755 | nsDocShell::SetTreeOwner(nsIDocShellTreeOwner* aTreeOwner) { |
2756 | if (mIsBeingDestroyed && aTreeOwner) { |
2757 | return NS_ERROR_FAILURE; |
2758 | } |
2759 | |
2760 | // Don't automatically set the progress based on the tree owner for frames |
2761 | if (!IsSubframe()) { |
2762 | nsCOMPtr<nsIWebProgress> webProgress = |
2763 | do_QueryInterface(GetAsSupports(this)); |
2764 | |
2765 | if (webProgress) { |
2766 | nsCOMPtr<nsIWebProgressListener> oldListener = |
2767 | do_QueryInterface(mTreeOwner); |
2768 | nsCOMPtr<nsIWebProgressListener> newListener = |
2769 | do_QueryInterface(aTreeOwner); |
2770 | |
2771 | if (oldListener) { |
2772 | webProgress->RemoveProgressListener(oldListener); |
2773 | } |
2774 | |
2775 | if (newListener) { |
2776 | webProgress->AddProgressListener(newListener, |
2777 | nsIWebProgress::NOTIFY_ALL); |
2778 | } |
2779 | } |
2780 | } |
2781 | |
2782 | mTreeOwner = aTreeOwner; // Weak reference per API |
2783 | |
2784 | for (auto* childDocLoader : mChildList.ForwardRange()) { |
2785 | nsCOMPtr<nsIDocShellTreeItem> child = do_QueryObject(childDocLoader); |
2786 | 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" , 2786); return NS_ERROR_FAILURE; } } while (false); |
2787 | |
2788 | if (child->ItemType() == mItemType) { |
2789 | child->SetTreeOwner(aTreeOwner); |
2790 | } |
2791 | } |
2792 | |
2793 | // If we're in the content process and have had a TreeOwner set on us, extract |
2794 | // our BrowserChild actor. If we've already had our BrowserChild set, assert |
2795 | // that it hasn't changed. |
2796 | if (mTreeOwner && XRE_IsContentProcess()) { |
2797 | nsCOMPtr<nsIBrowserChild> newBrowserChild = do_GetInterface(mTreeOwner); |
2798 | 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" , 2799); AnnotateMozCrashReason("MOZ_ASSERT" "(" "newBrowserChild" ") (" "No BrowserChild actor for tree owner in Content!" ")" ); do { *((volatile int*)__null) = 2799; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
2799 | "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" , 2799); AnnotateMozCrashReason("MOZ_ASSERT" "(" "newBrowserChild" ") (" "No BrowserChild actor for tree owner in Content!" ")" ); do { *((volatile int*)__null) = 2799; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2800 | |
2801 | if (mBrowserChild) { |
2802 | nsCOMPtr<nsIBrowserChild> oldBrowserChild = |
2803 | do_QueryReferent(mBrowserChild); |
2804 | 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" , 2806); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "oldBrowserChild == newBrowserChild" ") (" "Cannot change BrowserChild during nsDocShell lifetime!" ")"); do { *((volatile int*)__null) = 2806; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
2805 | 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" , 2806); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "oldBrowserChild == newBrowserChild" ") (" "Cannot change BrowserChild during nsDocShell lifetime!" ")"); do { *((volatile int*)__null) = 2806; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
2806 | "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" , 2806); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "oldBrowserChild == newBrowserChild" ") (" "Cannot change BrowserChild during nsDocShell lifetime!" ")"); do { *((volatile int*)__null) = 2806; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2807 | } else { |
2808 | mBrowserChild = do_GetWeakReference(newBrowserChild); |
2809 | } |
2810 | } |
2811 | |
2812 | return NS_OK; |
2813 | } |
2814 | |
2815 | NS_IMETHODIMPnsresult |
2816 | nsDocShell::GetHistoryID(nsID& aID) { |
2817 | aID = mBrowsingContext->GetHistoryID(); |
2818 | return NS_OK; |
2819 | } |
2820 | |
2821 | const nsID& nsDocShell::HistoryID() { return mBrowsingContext->GetHistoryID(); } |
2822 | |
2823 | NS_IMETHODIMPnsresult |
2824 | nsDocShell::GetIsInUnload(bool* aIsInUnload) { |
2825 | *aIsInUnload = mFiredUnloadEvent; |
2826 | return NS_OK; |
2827 | } |
2828 | |
2829 | NS_IMETHODIMPnsresult |
2830 | nsDocShell::GetInProcessChildCount(int32_t* aChildCount) { |
2831 | 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" , 2831); return NS_ERROR_INVALID_POINTER; } } while (false); |
2832 | *aChildCount = mChildList.Length(); |
2833 | return NS_OK; |
2834 | } |
2835 | |
2836 | NS_IMETHODIMPnsresult |
2837 | nsDocShell::AddChild(nsIDocShellTreeItem* aChild) { |
2838 | 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" , 2838); return NS_ERROR_INVALID_POINTER; } } while (false); |
2839 | |
2840 | RefPtr<nsDocLoader> childAsDocLoader = GetAsDocLoader(aChild); |
2841 | 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" , 2841); return NS_ERROR_UNEXPECTED; } } while (false); |
2842 | |
2843 | // Make sure we're not creating a loop in the docshell tree |
2844 | nsDocLoader* ancestor = this; |
2845 | do { |
2846 | if (childAsDocLoader == ancestor) { |
2847 | return NS_ERROR_ILLEGAL_VALUE; |
2848 | } |
2849 | ancestor = ancestor->GetParent(); |
2850 | } while (ancestor); |
2851 | |
2852 | // Make sure to remove the child from its current parent. |
2853 | nsDocLoader* childsParent = childAsDocLoader->GetParent(); |
2854 | if (childsParent) { |
2855 | nsresult rv = childsParent->RemoveChildLoader(childAsDocLoader); |
2856 | 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" , 2856); return rv; } } while (false); |
2857 | } |
2858 | |
2859 | // Make sure to clear the treeowner in case this child is a different type |
2860 | // from us. |
2861 | aChild->SetTreeOwner(nullptr); |
2862 | |
2863 | nsresult res = AddChildLoader(childAsDocLoader); |
2864 | 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" , 2864); return res; } } while (false); |
2865 | 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" , 2866); MOZ_PretendNoReturn(); } } while (0) |
2866 | "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" , 2866); MOZ_PretendNoReturn(); } } while (0); |
2867 | |
2868 | /* Set the child's global history if the parent has one */ |
2869 | if (mBrowsingContext->GetUseGlobalHistory()) { |
2870 | // childDocShell->SetUseGlobalHistory(true); |
2871 | // this should be set through BC inherit |
2872 | 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" , 2872); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aChild->GetBrowsingContext()->GetUseGlobalHistory()" ")"); do { *((volatile int*)__null) = 2872; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2873 | } |
2874 | |
2875 | if (aChild->ItemType() != mItemType) { |
2876 | return NS_OK; |
2877 | } |
2878 | |
2879 | aChild->SetTreeOwner(mTreeOwner); |
2880 | |
2881 | nsCOMPtr<nsIDocShell> childAsDocShell(do_QueryInterface(aChild)); |
2882 | if (!childAsDocShell) { |
2883 | return NS_OK; |
2884 | } |
2885 | |
2886 | // charset, style-disabling, and zoom will be inherited in SetupNewViewer() |
2887 | |
2888 | // Now take this document's charset and set the child's parentCharset field |
2889 | // to it. We'll later use that field, in the loading process, for the |
2890 | // charset choosing algorithm. |
2891 | // If we fail, at any point, we just return NS_OK. |
2892 | // This code has some performance impact. But this will be reduced when |
2893 | // the current charset will finally be stored as an Atom, avoiding the |
2894 | // alias resolution extra look-up. |
2895 | |
2896 | // we are NOT going to propagate the charset is this Chrome's docshell |
2897 | if (mItemType == nsIDocShellTreeItem::typeChrome) { |
2898 | return NS_OK; |
2899 | } |
2900 | |
2901 | // get the parent's current charset |
2902 | if (!mDocumentViewer) { |
2903 | return NS_OK; |
2904 | } |
2905 | Document* doc = mDocumentViewer->GetDocument(); |
2906 | if (!doc) { |
2907 | return NS_OK; |
2908 | } |
2909 | |
2910 | const Encoding* parentCS = doc->GetDocumentCharacterSet(); |
2911 | int32_t charsetSource = doc->GetDocumentCharacterSetSource(); |
2912 | // set the child's parentCharset |
2913 | childAsDocShell->SetParentCharset(parentCS, charsetSource, |
2914 | doc->NodePrincipal()); |
2915 | |
2916 | // printf("### 1 >>> Adding child. Parent CS = %s. ItemType = %d.\n", |
2917 | // NS_LossyConvertUTF16toASCII(parentCS).get(), mItemType); |
2918 | |
2919 | return NS_OK; |
2920 | } |
2921 | |
2922 | NS_IMETHODIMPnsresult |
2923 | nsDocShell::RemoveChild(nsIDocShellTreeItem* aChild) { |
2924 | 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" , 2924); return NS_ERROR_INVALID_POINTER; } } while (false); |
2925 | |
2926 | RefPtr<nsDocLoader> childAsDocLoader = GetAsDocLoader(aChild); |
2927 | 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" , 2927); return NS_ERROR_UNEXPECTED; } } while (false); |
2928 | |
2929 | nsresult rv = RemoveChildLoader(childAsDocLoader); |
2930 | 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" , 2930); return rv; } } while (false); |
2931 | |
2932 | aChild->SetTreeOwner(nullptr); |
2933 | |
2934 | return nsDocLoader::AddDocLoaderAsChildOfRoot(childAsDocLoader); |
2935 | } |
2936 | |
2937 | NS_IMETHODIMPnsresult |
2938 | nsDocShell::GetInProcessChildAt(int32_t aIndex, nsIDocShellTreeItem** aChild) { |
2939 | 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" , 2939); return NS_ERROR_INVALID_POINTER; } } while (false); |
2940 | |
2941 | RefPtr<nsDocShell> child = GetInProcessChildAt(aIndex); |
2942 | 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" , 2942); return NS_ERROR_UNEXPECTED; } } while (false); |
2943 | |
2944 | child.forget(aChild); |
2945 | |
2946 | return NS_OK; |
2947 | } |
2948 | |
2949 | nsDocShell* nsDocShell::GetInProcessChildAt(int32_t aIndex) { |
2950 | #ifdef DEBUG1 |
2951 | if (aIndex < 0) { |
2952 | 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" , 2952); |
2953 | } else if (static_cast<uint32_t>(aIndex) >= mChildList.Length()) { |
2954 | 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" , 2954); |
2955 | } |
2956 | #endif |
2957 | |
2958 | nsIDocumentLoader* child = ChildAt(aIndex); |
2959 | |
2960 | // child may be nullptr here. |
2961 | return static_cast<nsDocShell*>(child); |
2962 | } |
2963 | |
2964 | nsresult nsDocShell::AddChildSHEntry(nsISHEntry* aCloneRef, |
2965 | nsISHEntry* aNewEntry, |
2966 | int32_t aChildOffset, uint32_t aLoadType, |
2967 | bool aCloneChildren) { |
2968 | 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" , 2968); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()" ")"); do { *((volatile int*)__null) = 2968; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2969 | nsresult rv = NS_OK; |
2970 | |
2971 | if (mLSHE && aLoadType != LOAD_PUSHSTATE) { |
2972 | /* You get here if you are currently building a |
2973 | * hierarchy ie.,you just visited a frameset page |
2974 | */ |
2975 | if (NS_FAILED(mLSHE->ReplaceChild(aNewEntry))((bool)(__builtin_expect(!!(NS_FAILED_impl(mLSHE->ReplaceChild (aNewEntry))), 0)))) { |
2976 | rv = mLSHE->AddChild(aNewEntry, aChildOffset); |
2977 | } |
2978 | } else if (!aCloneRef) { |
2979 | /* This is an initial load in some subframe. Just append it if we can */ |
2980 | if (mOSHE) { |
2981 | rv = mOSHE->AddChild(aNewEntry, aChildOffset, UseRemoteSubframes()); |
2982 | } |
2983 | } else { |
2984 | RefPtr<ChildSHistory> shistory = GetRootSessionHistory(); |
2985 | if (shistory) { |
2986 | rv = shistory->LegacySHistory()->AddChildSHEntryHelper( |
2987 | aCloneRef, aNewEntry, mBrowsingContext->Top(), aCloneChildren); |
2988 | } |
2989 | } |
2990 | return rv; |
2991 | } |
2992 | |
2993 | nsresult nsDocShell::AddChildSHEntryToParent(nsISHEntry* aNewEntry, |
2994 | int32_t aChildOffset, |
2995 | bool aCloneChildren) { |
2996 | 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" , 2996); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()" ")"); do { *((volatile int*)__null) = 2996; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2997 | /* You will get here when you are in a subframe and |
2998 | * a new url has been loaded on you. |
2999 | * The mOSHE in this subframe will be the previous url's |
3000 | * mOSHE. This mOSHE will be used as the identification |
3001 | * for this subframe in the CloneAndReplace function. |
3002 | */ |
3003 | |
3004 | // In this case, we will end up calling AddEntry, which increases the |
3005 | // current index by 1 |
3006 | RefPtr<ChildSHistory> rootSH = GetRootSessionHistory(); |
3007 | if (rootSH) { |
3008 | mPreviousEntryIndex = rootSH->Index(); |
3009 | } |
3010 | |
3011 | nsresult rv; |
3012 | // XXX(farre): this is not Fission safe, expect errors. This never |
3013 | // get's executed once session history in the parent is enabled. |
3014 | nsCOMPtr<nsIDocShell> parent = do_QueryInterface(GetAsSupports(mParent), &rv); |
3015 | 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" , 3018); } } while (false) |
3016 | 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" , 3018); } } while (false) |
3017 | "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" , 3018); } } while (false) |
3018 | "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" , 3018); } } while (false); |
3019 | if (parent) { |
3020 | rv = nsDocShell::Cast(parent)->AddChildSHEntry( |
3021 | mOSHE, aNewEntry, aChildOffset, mLoadType, aCloneChildren); |
3022 | } |
3023 | |
3024 | if (rootSH) { |
3025 | mLoadedEntryIndex = rootSH->Index(); |
3026 | |
3027 | if (MOZ_UNLIKELY(MOZ_LOG_TEST(gPageCacheLog, LogLevel::Verbose))(__builtin_expect(!!((__builtin_expect(!!(mozilla::detail::log_test (gPageCacheLog, LogLevel::Verbose)), 0))), 0))) { |
3028 | 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) |
3029 | ("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) |
3030 | 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); |
3031 | } |
3032 | } |
3033 | |
3034 | return rv; |
3035 | } |
3036 | |
3037 | NS_IMETHODIMPnsresult |
3038 | nsDocShell::GetCurrentSHEntry(nsISHEntry** aEntry, bool* aOSHE) { |
3039 | *aOSHE = false; |
3040 | *aEntry = nullptr; |
3041 | if (mLSHE) { |
3042 | NS_ADDREF(*aEntry = mLSHE)(*aEntry = mLSHE)->AddRef(); |
3043 | } else if (mOSHE) { |
3044 | NS_ADDREF(*aEntry = mOSHE)(*aEntry = mOSHE)->AddRef(); |
3045 | *aOSHE = true; |
3046 | } |
3047 | return NS_OK; |
3048 | } |
3049 | |
3050 | NS_IMETHODIMPnsresult nsDocShell::SynchronizeLayoutHistoryState() { |
3051 | if (mActiveEntry && mActiveEntry->GetLayoutHistoryState() && |
3052 | mBrowsingContext) { |
3053 | if (XRE_IsContentProcess()) { |
3054 | dom::ContentChild* contentChild = dom::ContentChild::GetSingleton(); |
3055 | if (contentChild) { |
3056 | contentChild->SendSynchronizeLayoutHistoryState( |
3057 | mBrowsingContext, mActiveEntry->GetLayoutHistoryState()); |
3058 | } |
3059 | } else { |
3060 | SessionHistoryEntry* entry = |
3061 | mBrowsingContext->Canonical()->GetActiveSessionHistoryEntry(); |
3062 | if (entry) { |
3063 | entry->SetLayoutHistoryState(mActiveEntry->GetLayoutHistoryState()); |
3064 | } |
3065 | } |
3066 | if (mLoadingEntry && |
3067 | mLoadingEntry->mInfo.SharedId() == mActiveEntry->SharedId()) { |
3068 | mLoadingEntry->mInfo.SetLayoutHistoryState( |
3069 | mActiveEntry->GetLayoutHistoryState()); |
3070 | } |
3071 | } |
3072 | |
3073 | return NS_OK; |
3074 | } |
3075 | |
3076 | void nsDocShell::SetLoadGroupDefaultLoadFlags(nsLoadFlags aLoadFlags) { |
3077 | if (mLoadGroup) { |
3078 | mLoadGroup->SetDefaultLoadFlags(aLoadFlags); |
3079 | } else { |
3080 | 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" , 3082) |
3081 | "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" , 3082) |
3082 | "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" , 3082); |
3083 | } |
3084 | } |
3085 | |
3086 | nsIScriptGlobalObject* nsDocShell::GetScriptGlobalObject() { |
3087 | 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" , 3087); return nullptr; } } while (false); |
3088 | return mScriptGlobal; |
3089 | } |
3090 | |
3091 | Document* nsDocShell::GetDocument() { |
3092 | 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" , 3092); return nullptr; } } while (false); |
3093 | return mDocumentViewer->GetDocument(); |
3094 | } |
3095 | |
3096 | Document* nsDocShell::GetExtantDocument() { |
3097 | return mDocumentViewer ? mDocumentViewer->GetDocument() : nullptr; |
3098 | } |
3099 | |
3100 | nsPIDOMWindowOuter* nsDocShell::GetWindow() { |
3101 | if (NS_FAILED(EnsureScriptEnvironment())((bool)(__builtin_expect(!!(NS_FAILED_impl(EnsureScriptEnvironment ())), 0)))) { |
3102 | return nullptr; |
3103 | } |
3104 | return mScriptGlobal; |
3105 | } |
3106 | |
3107 | NS_IMETHODIMPnsresult |
3108 | nsDocShell::GetDomWindow(mozIDOMWindowProxy** aWindow) { |
3109 | 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" , 3109); return NS_ERROR_INVALID_POINTER; } } while (false); |
3110 | |
3111 | nsresult rv = EnsureScriptEnvironment(); |
3112 | 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" , 3112); return rv; } } while (false); |
3113 | |
3114 | RefPtr<nsGlobalWindowOuter> window = mScriptGlobal; |
3115 | window.forget(aWindow); |
3116 | return NS_OK; |
3117 | } |
3118 | |
3119 | NS_IMETHODIMPnsresult |
3120 | nsDocShell::GetMessageManager(ContentFrameMessageManager** aMessageManager) { |
3121 | RefPtr<ContentFrameMessageManager> mm; |
3122 | if (RefPtr<BrowserChild> browserChild = BrowserChild::GetFrom(this)) { |
3123 | mm = browserChild->GetMessageManager(); |
3124 | } else if (nsPIDOMWindowOuter* win = GetWindow()) { |
3125 | mm = win->GetMessageManager(); |
3126 | } |
3127 | mm.forget(aMessageManager); |
3128 | return NS_OK; |
3129 | } |
3130 | |
3131 | NS_IMETHODIMPnsresult |
3132 | nsDocShell::GetIsNavigating(bool* aOut) { |
3133 | *aOut = mIsNavigating; |
3134 | return NS_OK; |
3135 | } |
3136 | |
3137 | void nsDocShell::ClearFrameHistory(nsISHEntry* aEntry) { |
3138 | 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" , 3138); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()" ")"); do { *((volatile int*)__null) = 3138; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3139 | RefPtr<ChildSHistory> rootSH = GetRootSessionHistory(); |
3140 | if (!rootSH || !aEntry) { |
3141 | return; |
3142 | } |
3143 | |
3144 | rootSH->LegacySHistory()->RemoveFrameEntries(aEntry); |
3145 | } |
3146 | |
3147 | //------------------------------------- |
3148 | //-- Helper Method for Print discovery |
3149 | //------------------------------------- |
3150 | bool nsDocShell::NavigationBlockedByPrinting(bool aDisplayErrorDialog) { |
3151 | if (!mBrowsingContext->Top()->GetIsPrinting()) { |
3152 | return false; |
3153 | } |
3154 | if (aDisplayErrorDialog) { |
3155 | DisplayLoadError(NS_ERROR_DOCUMENT_IS_PRINTMODE, nullptr, nullptr, nullptr); |
3156 | } |
3157 | return true; |
3158 | } |
3159 | |
3160 | bool nsDocShell::IsNavigationAllowed(bool aDisplayPrintErrorDialog, |
3161 | bool aCheckIfUnloadFired) { |
3162 | bool isAllowed = !NavigationBlockedByPrinting(aDisplayPrintErrorDialog) && |
3163 | (!aCheckIfUnloadFired || !mFiredUnloadEvent); |
3164 | if (!isAllowed) { |
3165 | return false; |
3166 | } |
3167 | if (!mDocumentViewer) { |
3168 | return true; |
3169 | } |
3170 | bool firingBeforeUnload; |
3171 | mDocumentViewer->GetBeforeUnloadFiring(&firingBeforeUnload); |
3172 | return !firingBeforeUnload; |
3173 | } |
3174 | |
3175 | //***************************************************************************** |
3176 | // nsDocShell::nsIWebNavigation |
3177 | //***************************************************************************** |
3178 | |
3179 | NS_IMETHODIMPnsresult |
3180 | nsDocShell::GetCanGoBack(bool* aCanGoBack) { |
3181 | *aCanGoBack = false; |
3182 | if (!IsNavigationAllowed(false)) { |
3183 | return NS_OK; // JS may not handle returning of an error code |
3184 | } |
3185 | RefPtr<ChildSHistory> rootSH = GetRootSessionHistory(); |
3186 | if (rootSH) { |
3187 | *aCanGoBack = rootSH->CanGo(-1); |
3188 | 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) |
3189 | ("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); |
3190 | |
3191 | return NS_OK; |
3192 | } |
3193 | return NS_ERROR_FAILURE; |
3194 | } |
3195 | |
3196 | NS_IMETHODIMPnsresult |
3197 | nsDocShell::GetCanGoForward(bool* aCanGoForward) { |
3198 | *aCanGoForward = false; |
3199 | if (!IsNavigationAllowed(false)) { |
3200 | return NS_OK; // JS may not handle returning of an error code |
3201 | } |
3202 | RefPtr<ChildSHistory> rootSH = GetRootSessionHistory(); |
3203 | if (rootSH) { |
3204 | *aCanGoForward = rootSH->CanGo(1); |
3205 | 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) |
3206 | ("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); |
3207 | return NS_OK; |
3208 | } |
3209 | return NS_ERROR_FAILURE; |
3210 | } |
3211 | |
3212 | NS_IMETHODIMPnsresult |
3213 | nsDocShell::GoBack(bool aRequireUserInteraction, bool aUserActivation) { |
3214 | if (!IsNavigationAllowed()) { |
3215 | return NS_OK; // JS may not handle returning of an error code |
3216 | } |
3217 | |
3218 | auto cleanupIsNavigating = MakeScopeExit([&]() { mIsNavigating = false; }); |
3219 | mIsNavigating = true; |
3220 | |
3221 | RefPtr<ChildSHistory> rootSH = GetRootSessionHistory(); |
3222 | 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" , 3222); return NS_ERROR_FAILURE; } } while (false); |
3223 | ErrorResult rv; |
3224 | rootSH->Go(-1, aRequireUserInteraction, aUserActivation, rv); |
3225 | return rv.StealNSResult(); |
3226 | } |
3227 | |
3228 | NS_IMETHODIMPnsresult |
3229 | nsDocShell::GoForward(bool aRequireUserInteraction, bool aUserActivation) { |
3230 | if (!IsNavigationAllowed()) { |
3231 | return NS_OK; // JS may not handle returning of an error code |
3232 | } |
3233 | |
3234 | auto cleanupIsNavigating = MakeScopeExit([&]() { mIsNavigating = false; }); |
3235 | mIsNavigating = true; |
3236 | |
3237 | RefPtr<ChildSHistory> rootSH = GetRootSessionHistory(); |
3238 | 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" , 3238); return NS_ERROR_FAILURE; } } while (false); |
3239 | ErrorResult rv; |
3240 | rootSH->Go(1, aRequireUserInteraction, aUserActivation, rv); |
3241 | return rv.StealNSResult(); |
3242 | } |
3243 | |
3244 | // XXX(nika): We may want to stop exposing this API in the child process? Going |
3245 | // to a specific index from multiple different processes could definitely race. |
3246 | NS_IMETHODIMPnsresult |
3247 | nsDocShell::GotoIndex(int32_t aIndex, bool aUserActivation) { |
3248 | if (!IsNavigationAllowed()) { |
3249 | return NS_OK; // JS may not handle returning of an error code |
3250 | } |
3251 | |
3252 | auto cleanupIsNavigating = MakeScopeExit([&]() { mIsNavigating = false; }); |
3253 | mIsNavigating = true; |
3254 | |
3255 | RefPtr<ChildSHistory> rootSH = GetRootSessionHistory(); |
3256 | 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" , 3256); return NS_ERROR_FAILURE; } } while (false); |
3257 | |
3258 | ErrorResult rv; |
3259 | rootSH->GotoIndex(aIndex, aIndex - rootSH->Index(), false, aUserActivation, |
3260 | rv); |
3261 | return rv.StealNSResult(); |
3262 | } |
3263 | |
3264 | nsresult nsDocShell::LoadURI(nsIURI* aURI, |
3265 | const LoadURIOptions& aLoadURIOptions) { |
3266 | if (!IsNavigationAllowed()) { |
3267 | return NS_OK; // JS may not handle returning of an error code |
3268 | } |
3269 | RefPtr<nsDocShellLoadState> loadState; |
3270 | nsresult rv = nsDocShellLoadState::CreateFromLoadURIOptions( |
3271 | mBrowsingContext, aURI, aLoadURIOptions, getter_AddRefs(loadState)); |
3272 | 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" , 3272); AnnotateMozCrashReason("MOZ_ASSERT" "(" "rv != NS_ERROR_MALFORMED_URI" ")"); do { *((volatile int*)__null) = 3272; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3273 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || !loadState) { |
3274 | return NS_ERROR_FAILURE; |
3275 | } |
3276 | |
3277 | return LoadURI(loadState, true); |
3278 | } |
3279 | |
3280 | NS_IMETHODIMPnsresult |
3281 | nsDocShell::LoadURIFromScript(nsIURI* aURI, |
3282 | JS::Handle<JS::Value> aLoadURIOptions, |
3283 | JSContext* aCx) { |
3284 | // generate dictionary for aLoadURIOptions and forward call |
3285 | LoadURIOptions loadURIOptions; |
3286 | if (!loadURIOptions.Init(aCx, aLoadURIOptions)) { |
3287 | return NS_ERROR_INVALID_ARG; |
3288 | } |
3289 | return LoadURI(aURI, loadURIOptions); |
3290 | } |
3291 | |
3292 | nsresult nsDocShell::FixupAndLoadURIString( |
3293 | const nsAString& aURIString, const LoadURIOptions& aLoadURIOptions) { |
3294 | if (!IsNavigationAllowed()) { |
3295 | return NS_OK; // JS may not handle returning of an error code |
3296 | } |
3297 | |
3298 | RefPtr<nsDocShellLoadState> loadState; |
3299 | nsresult rv = nsDocShellLoadState::CreateFromLoadURIOptions( |
3300 | mBrowsingContext, aURIString, aLoadURIOptions, getter_AddRefs(loadState)); |
3301 | |
3302 | uint32_t loadFlags = aLoadURIOptions.mLoadFlags; |
3303 | if (NS_ERROR_MALFORMED_URI == rv) { |
3304 | 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) |
3305 | ("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) |
3306 | "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) |
3307 | 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); |
3308 | |
3309 | // We need to store a session history entry. We don't have a valid URI, so |
3310 | // we use about:blank instead. |
3311 | nsCOMPtr<nsIURI> uri; |
3312 | 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" , 3312); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false" ") (" "NS_SUCCEEDED(NS_NewURI(getter_AddRefs(uri), \"about:blank\"_ns))" ")"); do { *((volatile int*)__null) = 3312; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); |
3313 | nsCOMPtr<nsIPrincipal> triggeringPrincipal; |
3314 | if (aLoadURIOptions.mTriggeringPrincipal) { |
3315 | triggeringPrincipal = aLoadURIOptions.mTriggeringPrincipal; |
3316 | } else { |
3317 | triggeringPrincipal = nsContentUtils::GetSystemPrincipal(); |
3318 | } |
3319 | if (mozilla::SessionHistoryInParent()) { |
3320 | mActiveEntry = MakeUnique<SessionHistoryInfo>( |
3321 | uri, triggeringPrincipal, nullptr, nullptr, nullptr, |
3322 | nsLiteralCString("text/html")); |
3323 | mBrowsingContext->SetActiveSessionHistoryEntry( |
3324 | Nothing(), mActiveEntry.get(), MAKE_LOAD_TYPE(LOAD_NORMAL, loadFlags)((LOAD_NORMAL) | ((loadFlags) << 16)), |
3325 | /* aUpdatedCacheKey = */ 0); |
3326 | } |
3327 | if (DisplayLoadError(rv, nullptr, PromiseFlatStringTPromiseFlatString<char16_t>(aURIString).get(), |
3328 | nullptr) && |
3329 | (loadFlags & LOAD_FLAGS_ERROR_LOAD_CHANGES_RV) != 0) { |
3330 | return NS_ERROR_LOAD_SHOWED_ERRORPAGE; |
3331 | } |
3332 | } |
3333 | |
3334 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || !loadState) { |
3335 | return NS_ERROR_FAILURE; |
3336 | } |
3337 | |
3338 | return LoadURI(loadState, true); |
3339 | } |
3340 | |
3341 | NS_IMETHODIMPnsresult |
3342 | nsDocShell::FixupAndLoadURIStringFromScript( |
3343 | const nsAString& aURIString, JS::Handle<JS::Value> aLoadURIOptions, |
3344 | JSContext* aCx) { |
3345 | // generate dictionary for aLoadURIOptions and forward call |
3346 | LoadURIOptions loadURIOptions; |
3347 | if (!loadURIOptions.Init(aCx, aLoadURIOptions)) { |
3348 | return NS_ERROR_INVALID_ARG; |
3349 | } |
3350 | return FixupAndLoadURIString(aURIString, loadURIOptions); |
3351 | } |
3352 | |
3353 | void nsDocShell::UnblockEmbedderLoadEventForFailure(bool aFireFrameErrorEvent) { |
3354 | // If we're not in a content frame, or are at a BrowsingContext tree boundary, |
3355 | // such as the content-chrome boundary, don't fire the error event. |
3356 | if (mBrowsingContext->IsTopContent() || mBrowsingContext->IsChrome()) { |
3357 | return; |
3358 | } |
3359 | |
3360 | // If embedder is same-process, then unblocking the load event is already |
3361 | // handled by nsDocLoader. Fire the error event on our embedder element if |
3362 | // requested. |
3363 | // |
3364 | // XXX: Bug 1440212 is looking into potentially changing this behaviour to act |
3365 | // more like the remote case when in-process. |
3366 | RefPtr<Element> element = mBrowsingContext->GetEmbedderElement(); |
3367 | if (element) { |
3368 | if (aFireFrameErrorEvent) { |
3369 | if (RefPtr<nsFrameLoaderOwner> flo = do_QueryObject(element)) { |
3370 | if (RefPtr<nsFrameLoader> fl = flo->GetFrameLoader()) { |
3371 | fl->FireErrorEvent(); |
3372 | } |
3373 | } |
3374 | } |
3375 | return; |
3376 | } |
3377 | |
3378 | // If we have a cross-process parent document, we must notify it that we no |
3379 | // longer block its load event. This is necessary for OOP sub-documents |
3380 | // because error documents do not result in a call to |
3381 | // SendMaybeFireEmbedderLoadEvents via any of the normal call paths. |
3382 | // (Obviously, we must do this before any of the returns below.) |
3383 | RefPtr<BrowserChild> browserChild = BrowserChild::GetFrom(this); |
3384 | if (browserChild) { |
3385 | mozilla::Unused << browserChild->SendMaybeFireEmbedderLoadEvents( |
3386 | aFireFrameErrorEvent ? EmbedderElementEventType::ErrorEvent |
3387 | : EmbedderElementEventType::NoEvent); |
3388 | } |
3389 | } |
3390 | |
3391 | NS_IMETHODIMPnsresult |
3392 | nsDocShell::DisplayLoadError(nsresult aError, nsIURI* aURI, |
3393 | const char16_t* aURL, nsIChannel* aFailedChannel, |
3394 | bool* aDisplayedErrorPage) { |
3395 | 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 ) |
3396 | ("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 ) |
3397 | 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 ); |
3398 | |
3399 | *aDisplayedErrorPage = false; |
3400 | // Get prompt and string bundle services |
3401 | nsCOMPtr<nsIPrompt> prompter; |
3402 | nsCOMPtr<nsIStringBundle> stringBundle; |
3403 | GetPromptAndStringBundle(getter_AddRefs(prompter), |
3404 | getter_AddRefs(stringBundle)); |
3405 | |
3406 | 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" , 3406); return NS_ERROR_FAILURE; } } while (false); |
3407 | 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" , 3407); return NS_ERROR_FAILURE; } } while (false); |
3408 | |
3409 | const char* error = nullptr; |
3410 | // The key used to select the appropriate error message from the properties |
3411 | // file. |
3412 | const char* errorDescriptionID = nullptr; |
3413 | AutoTArray<nsString, 3> formatStrs; |
3414 | bool addHostPort = false; |
3415 | bool isBadStsCertError = false; |
3416 | nsresult rv = NS_OK; |
3417 | nsAutoString messageStr; |
3418 | nsAutoCString cssClass; |
3419 | nsAutoCString errorPage; |
3420 | |
3421 | errorPage.AssignLiteral("neterror"); |
3422 | |
3423 | // Turn the error code into a human readable error message. |
3424 | if (NS_ERROR_UNKNOWN_PROTOCOL == aError) { |
3425 | 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" , 3425); return NS_ERROR_INVALID_POINTER; } } while (false); |
3426 | |
3427 | // Extract the schemes into a comma delimited list. |
3428 | nsAutoCString scheme; |
3429 | aURI->GetScheme(scheme); |
3430 | CopyASCIItoUTF16(scheme, *formatStrs.AppendElement()); |
3431 | nsCOMPtr<nsINestedURI> nestedURI = do_QueryInterface(aURI); |
3432 | while (nestedURI) { |
3433 | nsCOMPtr<nsIURI> tempURI; |
3434 | nsresult rv2; |
3435 | rv2 = nestedURI->GetInnerURI(getter_AddRefs(tempURI)); |
3436 | if (NS_SUCCEEDED(rv2)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv2)), 1))) && tempURI) { |
3437 | tempURI->GetScheme(scheme); |
3438 | formatStrs[0].AppendLiteral(", "); |
3439 | AppendASCIItoUTF16(scheme, formatStrs[0]); |
3440 | } |
3441 | nestedURI = do_QueryInterface(tempURI); |
3442 | } |
3443 | error = "unknownProtocolFound"; |
3444 | } else if (NS_ERROR_FILE_NOT_FOUND == aError) { |
3445 | 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" , 3445); return NS_ERROR_INVALID_POINTER; } } while (false); |
3446 | error = "fileNotFound"; |
3447 | } else if (NS_ERROR_FILE_ACCESS_DENIED == aError) { |
3448 | 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" , 3448); return NS_ERROR_INVALID_POINTER; } } while (false); |
3449 | error = "fileAccessDenied"; |
3450 | } else if (NS_ERROR_UNKNOWN_HOST == aError) { |
3451 | 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" , 3451); return NS_ERROR_INVALID_POINTER; } } while (false); |
3452 | // Get the host |
3453 | nsAutoCString host; |
3454 | nsCOMPtr<nsIURI> innermostURI = NS_GetInnermostURI(aURI); |
3455 | innermostURI->GetHost(host); |
3456 | CopyUTF8toUTF16(host, *formatStrs.AppendElement()); |
3457 | errorDescriptionID = "dnsNotFound2"; |
3458 | error = "dnsNotFound"; |
3459 | } else if (NS_ERROR_CONNECTION_REFUSED == aError || |
3460 | NS_ERROR_PROXY_BAD_GATEWAY == aError) { |
3461 | 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" , 3461); return NS_ERROR_INVALID_POINTER; } } while (false); |
3462 | addHostPort = true; |
3463 | error = "connectionFailure"; |
3464 | } else if (NS_ERROR_NET_INTERRUPT == aError) { |
3465 | 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" , 3465); return NS_ERROR_INVALID_POINTER; } } while (false); |
3466 | addHostPort = true; |
3467 | error = "netInterrupt"; |
3468 | } else if (NS_ERROR_NET_TIMEOUT == aError || |
3469 | NS_ERROR_PROXY_GATEWAY_TIMEOUT == aError || |
3470 | NS_ERROR_NET_TIMEOUT_EXTERNAL == aError) { |
3471 | 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" , 3471); return NS_ERROR_INVALID_POINTER; } } while (false); |
3472 | // Get the host |
3473 | nsAutoCString host; |
3474 | aURI->GetHost(host); |
3475 | CopyUTF8toUTF16(host, *formatStrs.AppendElement()); |
3476 | error = "netTimeout"; |
3477 | } else if (NS_ERROR_CSP_FRAME_ANCESTOR_VIOLATION == aError || |
3478 | NS_ERROR_CSP_FORM_ACTION_VIOLATION == aError || |
3479 | NS_ERROR_CSP_NAVIGATE_TO_VIOLATION == aError) { |
3480 | // CSP error |
3481 | cssClass.AssignLiteral("neterror"); |
3482 | error = "cspBlocked"; |
3483 | } else if (NS_ERROR_XFO_VIOLATION == aError) { |
3484 | // XFO error |
3485 | cssClass.AssignLiteral("neterror"); |
3486 | error = "xfoBlocked"; |
3487 | } else if (NS_ERROR_GET_MODULE(aError) == NS_ERROR_MODULE_SECURITY21) { |
3488 | nsCOMPtr<nsINSSErrorsService> nsserr = |
3489 | do_GetService(NS_NSS_ERRORS_SERVICE_CONTRACTID"@mozilla.org/nss_errors_service;1"); |
3490 | |
3491 | uint32_t errorClass; |
3492 | if (!nsserr || NS_FAILED(nsserr->GetErrorClass(aError, &errorClass))((bool)(__builtin_expect(!!(NS_FAILED_impl(nsserr->GetErrorClass (aError, &errorClass))), 0)))) { |
3493 | errorClass = nsINSSErrorsService::ERROR_CLASS_SSL_PROTOCOL; |
3494 | } |
3495 | |
3496 | nsCOMPtr<nsITransportSecurityInfo> tsi; |
3497 | if (aFailedChannel) { |
3498 | aFailedChannel->GetSecurityInfo(getter_AddRefs(tsi)); |
3499 | } |
3500 | if (tsi) { |
3501 | uint32_t securityState; |
3502 | tsi->GetSecurityState(&securityState); |
3503 | if (securityState & nsIWebProgressListener::STATE_USES_SSL_3) { |
3504 | error = "sslv3Used"; |
Value stored to 'error' is never read | |
3505 | addHostPort = true; |
3506 | } else if (securityState & |
3507 | nsIWebProgressListener::STATE_USES_WEAK_CRYPTO) { |
3508 | error = "weakCryptoUsed"; |
3509 | addHostPort = true; |
3510 | } |
3511 | } else { |
3512 | // No channel, let's obtain the generic error message |
3513 | if (nsserr) { |
3514 | nsserr->GetErrorMessage(aError, messageStr); |
3515 | } |
3516 | } |
3517 | // We don't have a message string here anymore but DisplayLoadError |
3518 | // requires a non-empty messageStr. |
3519 | messageStr.Truncate(); |
3520 | messageStr.AssignLiteral(u" "); |
3521 | if (errorClass == nsINSSErrorsService::ERROR_CLASS_BAD_CERT) { |
3522 | error = "nssBadCert"; |
3523 | |
3524 | // If this is an HTTP Strict Transport Security host or a pinned host |
3525 | // and the certificate is bad, don't allow overrides (RFC 6797 section |
3526 | // 12.1). |
3527 | bool isStsHost = false; |
3528 | bool isPinnedHost = false; |
3529 | OriginAttributes attrsForHSTS; |
3530 | if (aFailedChannel) { |
3531 | StoragePrincipalHelper::GetOriginAttributesForHSTS(aFailedChannel, |
3532 | attrsForHSTS); |
3533 | } else { |
3534 | attrsForHSTS = GetOriginAttributes(); |
3535 | } |
3536 | |
3537 | if (XRE_IsParentProcess()) { |
3538 | nsCOMPtr<nsISiteSecurityService> sss = |
3539 | do_GetService(NS_SSSERVICE_CONTRACTID"@mozilla.org/ssservice;1", &rv); |
3540 | 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" , 3540); return rv; } } while (false); |
3541 | rv = sss->IsSecureURI(aURI, attrsForHSTS, &isStsHost); |
3542 | 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" , 3542); return rv; } } while (false); |
3543 | } else { |
3544 | mozilla::dom::ContentChild* cc = |
3545 | mozilla::dom::ContentChild::GetSingleton(); |
3546 | cc->SendIsSecureURI(aURI, attrsForHSTS, &isStsHost); |
3547 | } |
3548 | nsCOMPtr<nsIPublicKeyPinningService> pkps = |
3549 | do_GetService(NS_PKPSERVICE_CONTRACTID"@mozilla.org/security/publickeypinningservice;1", &rv); |
3550 | 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" , 3550); return rv; } } while (false); |
3551 | rv = pkps->HostHasPins(aURI, &isPinnedHost); |
3552 | |
3553 | if (Preferences::GetBool("browser.xul.error_pages.expert_bad_cert", |
3554 | false)) { |
3555 | cssClass.AssignLiteral("expertBadCert"); |
3556 | } |
3557 | |
3558 | // HSTS/pinning takes precedence over the expert bad cert pref. We |
3559 | // never want to show the "Add Exception" button for these sites. |
3560 | // In the future we should differentiate between an HSTS host and a |
3561 | // pinned host and display a more informative message to the user. |
3562 | if (isStsHost || isPinnedHost) { |
3563 | isBadStsCertError = true; |
3564 | cssClass.AssignLiteral("badStsCert"); |
3565 | } |
3566 | |
3567 | errorPage.Assign("certerror"); |
3568 | } else { |
3569 | error = "nssFailure2"; |
3570 | } |
3571 | } else if (NS_ERROR_PHISHING_URI == aError || |
3572 | NS_ERROR_MALWARE_URI == aError || |
3573 | NS_ERROR_UNWANTED_URI == aError || |
3574 | NS_ERROR_HARMFUL_URI == aError) { |
3575 | nsAutoCString host; |
3576 | aURI->GetHost(host); |
3577 | CopyUTF8toUTF16(host, *formatStrs.AppendElement()); |
3578 | |
3579 | // Malware and phishing detectors may want to use an alternate error |
3580 | // page, but if the pref's not set, we'll fall back on the standard page |
3581 | nsAutoCString alternateErrorPage; |
3582 | nsresult rv = Preferences::GetCString("urlclassifier.alternate_error_page", |
3583 | alternateErrorPage); |
3584 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) { |
3585 | errorPage.Assign(alternateErrorPage); |
3586 | } |
3587 | |
3588 | if (NS_ERROR_PHISHING_URI == aError) { |
3589 | error = "deceptiveBlocked"; |
3590 | } else if (NS_ERROR_MALWARE_URI == aError) { |
3591 | error = "malwareBlocked"; |
3592 | } else if (NS_ERROR_UNWANTED_URI == aError) { |
3593 | error = "unwantedBlocked"; |
3594 | } else if (NS_ERROR_HARMFUL_URI == aError) { |
3595 | error = "harmfulBlocked"; |
3596 | } |
3597 | |
3598 | cssClass.AssignLiteral("blacklist"); |
3599 | } else if (NS_ERROR_CONTENT_CRASHED == aError) { |
3600 | errorPage.AssignLiteral("tabcrashed"); |
3601 | error = "tabcrashed"; |
3602 | |
3603 | RefPtr<EventTarget> handler = mChromeEventHandler; |
3604 | if (handler) { |
3605 | nsCOMPtr<Element> element = do_QueryInterface(handler); |
3606 | element->GetAttribute(u"crashedPageTitle"_ns, messageStr); |
3607 | } |
3608 | |
3609 | // DisplayLoadError requires a non-empty messageStr to proceed and call |
3610 | // LoadErrorPage. If the page doesn't have a title, we will use a blank |
3611 | // space which will be trimmed and thus treated as empty by the front-end. |
3612 | if (messageStr.IsEmpty()) { |
3613 | messageStr.AssignLiteral(u" "); |
3614 | } |
3615 | } else if (NS_ERROR_FRAME_CRASHED == aError) { |
3616 | errorPage.AssignLiteral("framecrashed"); |
3617 | error = "framecrashed"; |
3618 | messageStr.AssignLiteral(u" "); |
3619 | } else if (NS_ERROR_BUILDID_MISMATCH == aError) { |
3620 | errorPage.AssignLiteral("restartrequired"); |
3621 | error = "restartrequired"; |
3622 | |
3623 | // DisplayLoadError requires a non-empty messageStr to proceed and call |
3624 | // LoadErrorPage. If the page doesn't have a title, we will use a blank |
3625 | // space which will be trimmed and thus treated as empty by the front-end. |
3626 | if (messageStr.IsEmpty()) { |
3627 | messageStr.AssignLiteral(u" "); |
3628 | } |
3629 | } else { |
3630 | // Errors requiring simple formatting |
3631 | switch (aError) { |
3632 | case NS_ERROR_MALFORMED_URI: |
3633 | // URI is malformed |
3634 | error = "malformedURI"; |
3635 | errorDescriptionID = "malformedURI2"; |
3636 | break; |
3637 | case NS_ERROR_REDIRECT_LOOP: |
3638 | // Doc failed to load because the server generated too many redirects |
3639 | error = "redirectLoop"; |
3640 | break; |
3641 | case NS_ERROR_UNKNOWN_SOCKET_TYPE: |
3642 | // Doc failed to load because PSM is not installed |
3643 | error = "unknownSocketType"; |
3644 | break; |
3645 | case NS_ERROR_NET_RESET: |
3646 | // Doc failed to load because the server kept reseting the connection |
3647 | // before we could read any data from it |
3648 | error = "netReset"; |
3649 | break; |
3650 | case NS_ERROR_DOCUMENT_NOT_CACHED: |
3651 | // Doc failed to load because the cache does not contain a copy of |
3652 | // the document. |
3653 | error = "notCached"; |
3654 | break; |
3655 | case NS_ERROR_OFFLINE: |
3656 | // Doc failed to load because we are offline. |
3657 | error = "netOffline"; |
3658 | break; |
3659 | case NS_ERROR_DOCUMENT_IS_PRINTMODE: |
3660 | // Doc navigation attempted while Printing or Print Preview |
3661 | error = "isprinting"; |
3662 | break; |
3663 | case NS_ERROR_PORT_ACCESS_NOT_ALLOWED: |
3664 | // Port blocked for security reasons |
3665 | addHostPort = true; |
3666 | error = "deniedPortAccess"; |
3667 | break; |
3668 | case NS_ERROR_UNKNOWN_PROXY_HOST: |
3669 | // Proxy hostname could not be resolved. |
3670 | error = "proxyResolveFailure"; |
3671 | break; |
3672 | case NS_ERROR_PROXY_CONNECTION_REFUSED: |
3673 | case NS_ERROR_PROXY_FORBIDDEN: |
3674 | case NS_ERROR_PROXY_NOT_IMPLEMENTED: |
3675 | case NS_ERROR_PROXY_AUTHENTICATION_FAILED: |
3676 | case NS_ERROR_PROXY_TOO_MANY_REQUESTS: |
3677 | // Proxy connection was refused. |
3678 | error = "proxyConnectFailure"; |
3679 | break; |
3680 | case NS_ERROR_INVALID_CONTENT_ENCODING: |
3681 | // Bad Content Encoding. |
3682 | error = "contentEncodingError"; |
3683 | break; |
3684 | case NS_ERROR_UNSAFE_CONTENT_TYPE: |
3685 | // Channel refused to load from an unrecognized content type. |
3686 | error = "unsafeContentType"; |
3687 | break; |
3688 | case NS_ERROR_CORRUPTED_CONTENT: |
3689 | // Broken Content Detected. e.g. Content-MD5 check failure. |
3690 | error = "corruptedContentErrorv2"; |
3691 | break; |
3692 | case NS_ERROR_INTERCEPTION_FAILED: |
3693 | // ServiceWorker intercepted request, but something went wrong. |
3694 | error = "corruptedContentErrorv2"; |
3695 | break; |
3696 | case NS_ERROR_NET_INADEQUATE_SECURITY: |
3697 | // Server negotiated bad TLS for HTTP/2. |
3698 | error = "inadequateSecurityError"; |
3699 | addHostPort = true; |
3700 | break; |
3701 | case NS_ERROR_BLOCKED_BY_POLICY: |
3702 | case NS_ERROR_DOM_COOP_FAILED: |
3703 | case NS_ERROR_DOM_COEP_FAILED: |
3704 | // Page blocked by policy |
3705 | error = "blockedByPolicy"; |
3706 | break; |
3707 | case NS_ERROR_NET_HTTP2_SENT_GOAWAY: |
3708 | case NS_ERROR_NET_HTTP3_PROTOCOL_ERROR: |
3709 | // HTTP/2 or HTTP/3 stack detected a protocol error |
3710 | error = "networkProtocolError"; |
3711 | break; |
3712 | |
3713 | default: |
3714 | break; |
3715 | } |
3716 | } |
3717 | |
3718 | nsresult delegateErrorCode = aError; |
3719 | // If the HTTPS-Only Mode upgraded this request and the upgrade might have |
3720 | // caused this error, we replace the error-page with about:httpsonlyerror |
3721 | if (nsHTTPSOnlyUtils::CouldBeHttpsOnlyError(aFailedChannel, aError)) { |
3722 | errorPage.AssignLiteral("httpsonlyerror"); |
3723 | delegateErrorCode = NS_ERROR_HTTPS_ONLY; |
3724 | } else if (isBadStsCertError) { |
3725 | delegateErrorCode = NS_ERROR_BAD_HSTS_CERT; |
3726 | } |
3727 | |
3728 | if (nsCOMPtr<nsILoadURIDelegate> loadURIDelegate = GetLoadURIDelegate()) { |
3729 | nsCOMPtr<nsIURI> errorPageURI; |
3730 | rv = loadURIDelegate->HandleLoadError( |
3731 | aURI, delegateErrorCode, NS_ERROR_GET_MODULE(delegateErrorCode), |
3732 | getter_AddRefs(errorPageURI)); |
3733 | // If the docshell is going away there's no point in showing an error page. |
3734 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || mIsBeingDestroyed) { |
3735 | *aDisplayedErrorPage = false; |
3736 | return NS_OK; |
3737 | } |
3738 | |
3739 | if (errorPageURI) { |
3740 | *aDisplayedErrorPage = |
3741 | NS_SUCCEEDED(LoadErrorPage(errorPageURI, aURI, aFailedChannel))((bool)(__builtin_expect(!!(!NS_FAILED_impl(LoadErrorPage(errorPageURI , aURI, aFailedChannel))), 1))); |
3742 | return NS_OK; |
3743 | } |
3744 | } |
3745 | |
3746 | // Test if the error should be displayed |
3747 | if (!error) { |
3748 | return NS_OK; |
3749 | } |
3750 | |
3751 | if (!errorDescriptionID) { |
3752 | errorDescriptionID = error; |
3753 | } |
3754 | |
3755 | Telemetry::AccumulateCategoricalKeyed( |
3756 | IsSubframe() ? "frame"_ns : "top"_ns, |
3757 | mozilla::dom::LoadErrorToTelemetryLabel(aError)); |
3758 | |
3759 | // Test if the error needs to be formatted |
3760 | if (!messageStr.IsEmpty()) { |
3761 | // already obtained message |
3762 | } else { |
3763 | if (addHostPort) { |
3764 | // Build up the host:port string. |
3765 | nsAutoCString hostport; |
3766 | if (aURI) { |
3767 | aURI->GetHostPort(hostport); |
3768 | } else { |
3769 | hostport.Assign('?'); |
3770 | } |
3771 | CopyUTF8toUTF16(hostport, *formatStrs.AppendElement()); |
3772 | } |
3773 | |
3774 | nsAutoCString spec; |
3775 | rv = NS_ERROR_NOT_AVAILABLE; |
3776 | auto& nextFormatStr = *formatStrs.AppendElement(); |
3777 | if (aURI) { |
3778 | // displaying "file://" is aesthetically unpleasing and could even be |
3779 | // confusing to the user |
3780 | if (SchemeIsFile(aURI)) { |
3781 | aURI->GetPathQueryRef(spec); |
3782 | } else { |
3783 | aURI->GetSpec(spec); |
3784 | } |
3785 | |
3786 | nsCOMPtr<nsITextToSubURI> textToSubURI( |
3787 | do_GetService(NS_ITEXTTOSUBURI_CONTRACTID"@mozilla.org/intl/texttosuburi;1", &rv)); |
3788 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) { |
3789 | rv = textToSubURI->UnEscapeURIForUI(spec, nextFormatStr); |
3790 | } |
3791 | } else { |
3792 | spec.Assign('?'); |
3793 | } |
3794 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
3795 | CopyUTF8toUTF16(spec, nextFormatStr); |
3796 | } |
3797 | rv = NS_OK; |
3798 | |
3799 | nsAutoString str; |
3800 | rv = |
3801 | stringBundle->FormatStringFromName(errorDescriptionID, formatStrs, str); |
3802 | 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" , 3802); return rv; } } while (false); |
3803 | messageStr.Assign(str); |
3804 | } |
3805 | |
3806 | // Display the error as a page or an alert prompt |
3807 | 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" , 3807); return NS_ERROR_FAILURE; } } while (false); |
3808 | |
3809 | if ((NS_ERROR_NET_INTERRUPT == aError || NS_ERROR_NET_RESET == aError) && |
3810 | SchemeIsHTTPS(aURI)) { |
3811 | // Maybe TLS intolerant. Treat this as an SSL error. |
3812 | error = "nssFailure2"; |
3813 | } |
3814 | |
3815 | if (mBrowsingContext->GetUseErrorPages()) { |
3816 | // Display an error page |
3817 | nsresult loadedPage = |
3818 | LoadErrorPage(aURI, aURL, errorPage.get(), error, messageStr.get(), |
3819 | cssClass.get(), aFailedChannel); |
3820 | *aDisplayedErrorPage = NS_SUCCEEDED(loadedPage)((bool)(__builtin_expect(!!(!NS_FAILED_impl(loadedPage)), 1)) ); |
3821 | } else { |
3822 | // The prompter reqires that our private window has a document (or it |
3823 | // asserts). Satisfy that assertion now since GetDoc will force |
3824 | // creation of one if it hasn't already been created. |
3825 | if (mScriptGlobal) { |
3826 | Unused << mScriptGlobal->GetDoc(); |
3827 | } |
3828 | |
3829 | // Display a message box |
3830 | prompter->Alert(nullptr, messageStr.get()); |
3831 | } |
3832 | |
3833 | return NS_OK; |
3834 | } |
3835 | |
3836 | #define PREF_SAFEBROWSING_ALLOWOVERRIDE"browser.safebrowsing.allowOverride" "browser.safebrowsing.allowOverride" |
3837 | |
3838 | nsresult nsDocShell::LoadErrorPage(nsIURI* aURI, const char16_t* aURL, |
3839 | const char* aErrorPage, |
3840 | const char* aErrorType, |
3841 | const char16_t* aDescription, |
3842 | const char* aCSSClass, |
3843 | nsIChannel* aFailedChannel) { |
3844 | if (mIsBeingDestroyed) { |
3845 | return NS_ERROR_NOT_AVAILABLE; |
3846 | } |
3847 | |
3848 | #if defined(DEBUG1) |
3849 | if (MOZ_LOG_TEST(gDocShellLog, LogLevel::Debug)(__builtin_expect(!!(mozilla::detail::log_test(gDocShellLog, LogLevel ::Debug)), 0))) { |
3850 | nsAutoCString chanName; |
3851 | if (aFailedChannel) { |
3852 | aFailedChannel->GetName(chanName); |
3853 | } else { |
3854 | chanName.AssignLiteral("<no channel>"); |
3855 | } |
3856 | |
3857 | 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) |
3858 | ("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) |
3859 | 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) |
3860 | 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); |
3861 | } |
3862 | #endif |
3863 | |
3864 | nsAutoCString url; |
3865 | if (aURI) { |
3866 | nsresult rv = aURI->GetSpec(url); |
3867 | 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" , 3867); return rv; } } while (false); |
3868 | } else if (aURL) { |
3869 | CopyUTF16toUTF8(MakeStringSpan(aURL), url); |
3870 | } else { |
3871 | return NS_ERROR_INVALID_POINTER; |
3872 | } |
3873 | |
3874 | // Create a URL to pass all the error information through to the page. |
3875 | |
3876 | #undef SAFE_ESCAPE |
3877 | #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" , 3877)) { return NS_ERROR_OUT_OF_MEMORY; } \ |
3878 | 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" , 3878)) { \ |
3879 | return NS_ERROR_OUT_OF_MEMORY; \ |
3880 | } |
3881 | |
3882 | nsCString escapedUrl, escapedError, escapedDescription, escapedCSSClass; |
3883 | 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" , 3883)) { return NS_ERROR_OUT_OF_MEMORY; }; |
3884 | 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" , 3884)) { return NS_ERROR_OUT_OF_MEMORY; }; |
3885 | 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" , 3886)) { return NS_ERROR_OUT_OF_MEMORY; } |
3886 | 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" , 3886)) { return NS_ERROR_OUT_OF_MEMORY; }; |
3887 | if (aCSSClass) { |
3888 | nsCString cssClass(aCSSClass); |
3889 | 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" , 3889)) { return NS_ERROR_OUT_OF_MEMORY; }; |
3890 | } |
3891 | nsCString errorPageUrl("about:"); |
3892 | errorPageUrl.AppendASCII(aErrorPage); |
3893 | errorPageUrl.AppendLiteral("?e="); |
3894 | |
3895 | errorPageUrl.AppendASCII(escapedError.get()); |
3896 | errorPageUrl.AppendLiteral("&u="); |
3897 | errorPageUrl.AppendASCII(escapedUrl.get()); |
3898 | if ((strcmp(aErrorPage, "blocked") == 0) && |
3899 | Preferences::GetBool(PREF_SAFEBROWSING_ALLOWOVERRIDE"browser.safebrowsing.allowOverride", true)) { |
3900 | errorPageUrl.AppendLiteral("&o=1"); |
3901 | } |
3902 | if (!escapedCSSClass.IsEmpty()) { |
3903 | errorPageUrl.AppendLiteral("&s="); |
3904 | errorPageUrl.AppendASCII(escapedCSSClass.get()); |
3905 | } |
3906 | errorPageUrl.AppendLiteral("&c=UTF-8"); |
3907 | |
3908 | nsCOMPtr<nsICaptivePortalService> cps = do_GetService(NS_CAPTIVEPORTAL_CID{ 0xbdbe0555, 0xfc3d, 0x4f7b, { 0x92, 0x05, 0xc3, 0x09, 0xce, 0xb2, 0xd6, 0x41 } }); |
3909 | int32_t cpsState; |
3910 | if (cps && NS_SUCCEEDED(cps->GetState(&cpsState))((bool)(__builtin_expect(!!(!NS_FAILED_impl(cps->GetState( &cpsState))), 1))) && |
3911 | cpsState == nsICaptivePortalService::LOCKED_PORTAL) { |
3912 | errorPageUrl.AppendLiteral("&captive=true"); |
3913 | } |
3914 | |
3915 | errorPageUrl.AppendLiteral("&d="); |
3916 | errorPageUrl.AppendASCII(escapedDescription.get()); |
3917 | |
3918 | nsCOMPtr<nsIURI> errorPageURI; |
3919 | nsresult rv = NS_NewURI(getter_AddRefs(errorPageURI), errorPageUrl); |
3920 | 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" , 3920); return rv; } } while (false); |
3921 | |
3922 | return LoadErrorPage(errorPageURI, aURI, aFailedChannel); |
3923 | } |
3924 | |
3925 | nsresult nsDocShell::LoadErrorPage(nsIURI* aErrorURI, nsIURI* aFailedURI, |
3926 | nsIChannel* aFailedChannel) { |
3927 | mFailedChannel = aFailedChannel; |
3928 | mFailedURI = aFailedURI; |
3929 | mFailedLoadType = mLoadType; |
3930 | |
3931 | if (mLSHE) { |
3932 | // Abandon mLSHE's BFCache entry and create a new one. This way, if |
3933 | // we go back or forward to another SHEntry with the same doc |
3934 | // identifier, the error page won't persist. |
3935 | mLSHE->AbandonBFCacheEntry(); |
3936 | } |
3937 | |
3938 | RefPtr<nsDocShellLoadState> loadState = new nsDocShellLoadState(aErrorURI); |
3939 | loadState->SetTriggeringPrincipal(nsContentUtils::GetSystemPrincipal()); |
3940 | if (mBrowsingContext) { |
3941 | loadState->SetTriggeringSandboxFlags(mBrowsingContext->GetSandboxFlags()); |
3942 | loadState->SetTriggeringWindowId( |
3943 | mBrowsingContext->GetCurrentInnerWindowId()); |
3944 | nsPIDOMWindowInner* innerWin = mScriptGlobal->GetCurrentInnerWindow(); |
3945 | if (innerWin) { |
3946 | loadState->SetTriggeringStorageAccess(innerWin->UsingStorageAccess()); |
3947 | } |
3948 | } |
3949 | loadState->SetLoadType(LOAD_ERROR_PAGE); |
3950 | loadState->SetFirstParty(true); |
3951 | loadState->SetSourceBrowsingContext(mBrowsingContext); |
3952 | if (mozilla::SessionHistoryInParent() && mLoadingEntry) { |
3953 | // We keep the loading entry for the load that failed here. If the user |
3954 | // reloads we want to try to reload the original load, not the error page. |
3955 | loadState->SetLoadingSessionHistoryInfo( |
3956 | MakeUnique<LoadingSessionHistoryInfo>(*mLoadingEntry)); |
3957 | } |
3958 | return InternalLoad(loadState); |
3959 | } |
3960 | |
3961 | NS_IMETHODIMPnsresult |
3962 | nsDocShell::Reload(uint32_t aReloadFlags) { |
3963 | if (!IsNavigationAllowed()) { |
3964 | return NS_OK; // JS may not handle returning of an error code |
3965 | } |
3966 | |
3967 | 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" , 3968); MOZ_PretendNoReturn(); } } while (0) |
3968 | "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" , 3968); MOZ_PretendNoReturn(); } } while (0); |
3969 | 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" , 3970); MOZ_PretendNoReturn(); } } while (0) |
3970 | "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" , 3970); MOZ_PretendNoReturn(); } } while (0); |
3971 | |
3972 | uint32_t loadType = MAKE_LOAD_TYPE(LOAD_RELOAD_NORMAL, aReloadFlags)((LOAD_RELOAD_NORMAL) | ((aReloadFlags) << 16)); |
3973 | 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" , 3973); return NS_ERROR_INVALID_ARG; } } while (false); |
3974 | |
3975 | // Send notifications to the HistoryListener if any, about the impending |
3976 | // reload |
3977 | RefPtr<ChildSHistory> rootSH = GetRootSessionHistory(); |
3978 | if (mozilla::SessionHistoryInParent()) { |
3979 | 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); |
3980 | bool forceReload = IsForceReloadType(loadType); |
3981 | if (!XRE_IsParentProcess()) { |
3982 | ++mPendingReloadCount; |
3983 | RefPtr<nsDocShell> docShell(this); |
3984 | nsCOMPtr<nsIDocumentViewer> viewer(mDocumentViewer); |
3985 | 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" , 3985); return NS_ERROR_UNEXPECTED; } } while (false); |
3986 | |
3987 | bool okToUnload = true; |
3988 | MOZ_TRY(viewer->PermitUnload(&okToUnload))do { auto mozTryTempResult_ = ::mozilla::ToResult(viewer-> PermitUnload(&okToUnload)); if ((__builtin_expect(!!(mozTryTempResult_ .isErr()), 0))) { return mozTryTempResult_.propagateErr(); } } while (0); |
3989 | if (!okToUnload) { |
3990 | return NS_OK; |
3991 | } |
3992 | |
3993 | RefPtr<Document> doc(GetDocument()); |
3994 | RefPtr<BrowsingContext> browsingContext(mBrowsingContext); |
3995 | nsCOMPtr<nsIURI> currentURI(mCurrentURI); |
3996 | nsCOMPtr<nsIReferrerInfo> referrerInfo(mReferrerInfo); |
3997 | RefPtr<StopDetector> stopDetector = new StopDetector(); |
3998 | nsCOMPtr<nsILoadGroup> loadGroup; |
3999 | GetLoadGroup(getter_AddRefs(loadGroup)); |
4000 | if (loadGroup) { |
4001 | // loadGroup may be null in theory. In that case stopDetector just |
4002 | // doesn't do anything. |
4003 | loadGroup->AddRequest(stopDetector, nullptr); |
4004 | } |
4005 | |
4006 | ContentChild::GetSingleton()->SendNotifyOnHistoryReload( |
4007 | mBrowsingContext, forceReload, |
4008 | [docShell, doc, loadType, browsingContext, currentURI, referrerInfo, |
4009 | loadGroup, stopDetector]( |
4010 | std::tuple<bool, Maybe<NotNull<RefPtr<nsDocShellLoadState>>>, |
4011 | Maybe<bool>>&& aResult) { |
4012 | auto scopeExit = MakeScopeExit([loadGroup, stopDetector]() { |
4013 | if (loadGroup) { |
4014 | loadGroup->RemoveRequest(stopDetector, nullptr, NS_OK); |
4015 | } |
4016 | }); |
4017 | |
4018 | // Decrease mPendingReloadCount before any other early returns! |
4019 | if (--(docShell->mPendingReloadCount) > 0) { |
4020 | return; |
4021 | } |
4022 | |
4023 | if (stopDetector->Canceled()) { |
4024 | return; |
4025 | } |
4026 | bool canReload; |
4027 | Maybe<NotNull<RefPtr<nsDocShellLoadState>>> loadState; |
4028 | Maybe<bool> reloadingActiveEntry; |
4029 | |
4030 | std::tie(canReload, loadState, reloadingActiveEntry) = aResult; |
4031 | |
4032 | if (!canReload) { |
4033 | return; |
4034 | } |
4035 | |
4036 | if (loadState.isSome()) { |
4037 | 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) |
4038 | 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) |
4039 | ("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); |
4040 | loadState.ref()->SetNotifiedBeforeUnloadListeners(true); |
4041 | docShell->LoadHistoryEntry(loadState.ref(), loadType, |
4042 | reloadingActiveEntry.ref()); |
4043 | } else { |
4044 | 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) |
4045 | ("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); |
4046 | ReloadDocument(docShell, doc, loadType, browsingContext, |
4047 | currentURI, referrerInfo, |
4048 | /* aNotifiedBeforeUnloadListeners */ true); |
4049 | } |
4050 | }, |
4051 | [](mozilla::ipc::ResponseRejectReason) {}); |
4052 | } else { |
4053 | // Parent process |
4054 | bool canReload = false; |
4055 | Maybe<NotNull<RefPtr<nsDocShellLoadState>>> loadState; |
4056 | Maybe<bool> reloadingActiveEntry; |
4057 | if (!mBrowsingContext->IsDiscarded()) { |
4058 | mBrowsingContext->Canonical()->NotifyOnHistoryReload( |
4059 | forceReload, canReload, loadState, reloadingActiveEntry); |
4060 | } |
4061 | if (canReload) { |
4062 | if (loadState.isSome()) { |
4063 | 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) |
4064 | ("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); |
4065 | LoadHistoryEntry(loadState.ref(), loadType, |
4066 | reloadingActiveEntry.ref()); |
4067 | } else { |
4068 | MOZ_LOG(gSHLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gSHLog; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "nsDocShell %p ReloadDocument", this); } } while (0) |
4069 | ("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); |
4070 | RefPtr<Document> doc = GetDocument(); |
4071 | RefPtr<BrowsingContext> bc = mBrowsingContext; |
4072 | nsCOMPtr<nsIURI> currentURI = mCurrentURI; |
4073 | nsCOMPtr<nsIReferrerInfo> referrerInfo = mReferrerInfo; |
4074 | ReloadDocument(this, doc, loadType, bc, currentURI, referrerInfo); |
4075 | } |
4076 | } |
4077 | } |
4078 | return NS_OK; |
4079 | } |
4080 | |
4081 | bool canReload = true; |
4082 | if (rootSH) { |
4083 | rootSH->LegacySHistory()->NotifyOnHistoryReload(&canReload); |
4084 | } |
4085 | |
4086 | if (!canReload) { |
4087 | return NS_OK; |
4088 | } |
4089 | |
4090 | /* If you change this part of code, make sure bug 45297 does not re-occur */ |
4091 | if (mOSHE) { |
4092 | nsCOMPtr<nsISHEntry> oshe = mOSHE; |
4093 | return LoadHistoryEntry( |
4094 | oshe, loadType, |
4095 | aReloadFlags & nsIWebNavigation::LOAD_FLAGS_USER_ACTIVATION); |
4096 | } |
4097 | |
4098 | if (mLSHE) { // In case a reload happened before the current load is done |
4099 | nsCOMPtr<nsISHEntry> lshe = mLSHE; |
4100 | return LoadHistoryEntry( |
4101 | lshe, loadType, |
4102 | aReloadFlags & nsIWebNavigation::LOAD_FLAGS_USER_ACTIVATION); |
4103 | } |
4104 | |
4105 | RefPtr<Document> doc = GetDocument(); |
4106 | RefPtr<BrowsingContext> bc = mBrowsingContext; |
4107 | nsCOMPtr<nsIURI> currentURI = mCurrentURI; |
4108 | nsCOMPtr<nsIReferrerInfo> referrerInfo = mReferrerInfo; |
4109 | return ReloadDocument(this, doc, loadType, bc, currentURI, referrerInfo); |
4110 | } |
4111 | |
4112 | /* static */ |
4113 | nsresult nsDocShell::ReloadDocument(nsDocShell* aDocShell, Document* aDocument, |
4114 | uint32_t aLoadType, |
4115 | BrowsingContext* aBrowsingContext, |
4116 | nsIURI* aCurrentURI, |
4117 | nsIReferrerInfo* aReferrerInfo, |
4118 | bool aNotifiedBeforeUnloadListeners) { |
4119 | if (!aDocument) { |
4120 | return NS_OK; |
4121 | } |
4122 | |
4123 | // Do not inherit owner from document |
4124 | uint32_t flags = INTERNAL_LOAD_FLAGS_NONE; |
4125 | nsAutoString srcdoc; |
4126 | nsIURI* baseURI = nullptr; |
4127 | nsCOMPtr<nsIURI> originalURI; |
4128 | nsCOMPtr<nsIURI> resultPrincipalURI; |
4129 | bool loadReplace = false; |
4130 | |
4131 | nsIPrincipal* triggeringPrincipal = aDocument->NodePrincipal(); |
4132 | nsCOMPtr<nsIContentSecurityPolicy> csp = aDocument->GetCsp(); |
4133 | uint32_t triggeringSandboxFlags = aDocument->GetSandboxFlags(); |
4134 | uint64_t triggeringWindowId = aDocument->InnerWindowID(); |
4135 | bool triggeringStorageAccess = aDocument->UsingStorageAccess(); |
4136 | |
4137 | nsAutoString contentTypeHint; |
4138 | aDocument->GetContentType(contentTypeHint); |
4139 | |
4140 | if (aDocument->IsSrcdocDocument()) { |
4141 | aDocument->GetSrcdocData(srcdoc); |
4142 | flags |= INTERNAL_LOAD_FLAGS_IS_SRCDOC; |
4143 | baseURI = aDocument->GetBaseURI(); |
4144 | } else { |
4145 | srcdoc = VoidString(); |
4146 | } |
4147 | nsCOMPtr<nsIChannel> chan = aDocument->GetChannel(); |
4148 | if (chan) { |
4149 | uint32_t loadFlags; |
4150 | chan->GetLoadFlags(&loadFlags); |
4151 | loadReplace = loadFlags & nsIChannel::LOAD_REPLACE; |
4152 | nsCOMPtr<nsIHttpChannel> httpChan(do_QueryInterface(chan)); |
4153 | if (httpChan) { |
4154 | httpChan->GetOriginalURI(getter_AddRefs(originalURI)); |
4155 | } |
4156 | |
4157 | nsCOMPtr<nsILoadInfo> loadInfo = chan->LoadInfo(); |
4158 | loadInfo->GetResultPrincipalURI(getter_AddRefs(resultPrincipalURI)); |
4159 | } |
4160 | |
4161 | if (!triggeringPrincipal) { |
4162 | 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" , 4162); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "Reload needs a valid triggeringPrincipal" ")"); do { *((volatile int*)__null) = 4162; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
4163 | return NS_ERROR_FAILURE; |
4164 | } |
4165 | |
4166 | // Stack variables to ensure changes to the member variables don't affect to |
4167 | // the call. |
4168 | nsCOMPtr<nsIURI> currentURI = aCurrentURI; |
4169 | |
4170 | // Reload always rewrites result principal URI. |
4171 | Maybe<nsCOMPtr<nsIURI>> emplacedResultPrincipalURI; |
4172 | emplacedResultPrincipalURI.emplace(std::move(resultPrincipalURI)); |
4173 | |
4174 | RefPtr<WindowContext> context = aBrowsingContext->GetCurrentWindowContext(); |
4175 | RefPtr<nsDocShellLoadState> loadState = new nsDocShellLoadState(currentURI); |
4176 | loadState->SetReferrerInfo(aReferrerInfo); |
4177 | loadState->SetOriginalURI(originalURI); |
4178 | loadState->SetMaybeResultPrincipalURI(emplacedResultPrincipalURI); |
4179 | loadState->SetLoadReplace(loadReplace); |
4180 | loadState->SetTriggeringPrincipal(triggeringPrincipal); |
4181 | loadState->SetTriggeringSandboxFlags(triggeringSandboxFlags); |
4182 | loadState->SetTriggeringWindowId(triggeringWindowId); |
4183 | loadState->SetTriggeringStorageAccess(triggeringStorageAccess); |
4184 | loadState->SetPrincipalToInherit(triggeringPrincipal); |
4185 | loadState->SetCsp(csp); |
4186 | loadState->SetInternalLoadFlags(flags); |
4187 | loadState->SetTypeHint(NS_ConvertUTF16toUTF8(contentTypeHint)); |
4188 | loadState->SetLoadType(aLoadType); |
4189 | loadState->SetFirstParty(true); |
4190 | loadState->SetSrcdocData(srcdoc); |
4191 | loadState->SetSourceBrowsingContext(aBrowsingContext); |
4192 | loadState->SetBaseURI(baseURI); |
4193 | loadState->SetHasValidUserGestureActivation( |
4194 | context && context->HasValidTransientUserGestureActivation()); |
4195 | loadState->SetNotifiedBeforeUnloadListeners(aNotifiedBeforeUnloadListeners); |
4196 | return aDocShell->InternalLoad(loadState); |
4197 | } |
4198 | |
4199 | NS_IMETHODIMPnsresult |
4200 | nsDocShell::Stop(uint32_t aStopFlags) { |
4201 | // Revoke any pending event related to content viewer restoration |
4202 | mRestorePresentationEvent.Revoke(); |
4203 | |
4204 | if (mLoadType == LOAD_ERROR_PAGE) { |
4205 | if (mLSHE) { |
4206 | // Since error page loads never unset mLSHE, do so now |
4207 | SetHistoryEntryAndUpdateBC(Some(nullptr), Some<nsISHEntry*>(mLSHE)); |
4208 | } |
4209 | mActiveEntryIsLoadingFromSessionHistory = false; |
4210 | |
4211 | mFailedChannel = nullptr; |
4212 | mFailedURI = nullptr; |
4213 | } |
4214 | |
4215 | if (nsIWebNavigation::STOP_CONTENT & aStopFlags) { |
4216 | // Stop the document loading and animations |
4217 | if (mDocumentViewer) { |
4218 | nsCOMPtr<nsIDocumentViewer> viewer = mDocumentViewer; |
4219 | viewer->Stop(); |
4220 | } |
4221 | } else if (nsIWebNavigation::STOP_NETWORK & aStopFlags) { |
4222 | // Stop the document loading only |
4223 | if (mDocumentViewer) { |
4224 | RefPtr<Document> doc = mDocumentViewer->GetDocument(); |
4225 | if (doc) { |
4226 | doc->StopDocumentLoad(); |
4227 | } |
4228 | } |
4229 | } |
4230 | |
4231 | if (nsIWebNavigation::STOP_NETWORK & aStopFlags) { |
4232 | // Suspend any timers that were set for this loader. We'll clear |
4233 | // them out for good in CreateDocumentViewer. |
4234 | if (mRefreshURIList) { |
4235 | SuspendRefreshURIs(); |
4236 | mSavedRefreshURIList.swap(mRefreshURIList); |
4237 | mRefreshURIList = nullptr; |
4238 | } |
4239 | |
4240 | // XXXbz We could also pass |this| to nsIURILoader::Stop. That will |
4241 | // just call Stop() on us as an nsIDocumentLoader... We need fewer |
4242 | // redundant apis! |
4243 | Stop(); |
4244 | |
4245 | // Clear out mChannelToDisconnectOnPageHide. This page won't go in the |
4246 | // BFCache now, and the Stop above will have removed the DocumentChannel |
4247 | // from the loadgroup. |
4248 | mChannelToDisconnectOnPageHide = 0; |
4249 | } |
4250 | |
4251 | for (auto* child : mChildList.ForwardRange()) { |
4252 | nsCOMPtr<nsIWebNavigation> shellAsNav(do_QueryObject(child)); |
4253 | if (shellAsNav) { |
4254 | shellAsNav->Stop(aStopFlags); |
4255 | } |
4256 | } |
4257 | |
4258 | return NS_OK; |
4259 | } |
4260 | |
4261 | NS_IMETHODIMPnsresult |
4262 | nsDocShell::GetDocument(Document** aDocument) { |
4263 | 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" , 4263); return NS_ERROR_INVALID_POINTER; } } while (false); |
4264 | 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" , 4264); return NS_ERROR_FAILURE; } } while (false); |
4265 | |
4266 | RefPtr<Document> doc = mDocumentViewer->GetDocument(); |
4267 | if (!doc) { |
4268 | return NS_ERROR_NOT_AVAILABLE; |
4269 | } |
4270 | |
4271 | doc.forget(aDocument); |
4272 | return NS_OK; |
4273 | } |
4274 | |
4275 | NS_IMETHODIMPnsresult |
4276 | nsDocShell::GetCurrentURI(nsIURI** aURI) { |
4277 | 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" , 4277); return NS_ERROR_INVALID_POINTER; } } while (false); |
4278 | |
4279 | nsCOMPtr<nsIURI> uri = mCurrentURI; |
4280 | uri.forget(aURI); |
4281 | return NS_OK; |
4282 | } |
4283 | |
4284 | NS_IMETHODIMPnsresult |
4285 | nsDocShell::GetSessionHistoryXPCOM(nsISupports** aSessionHistory) { |
4286 | 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" , 4286); return NS_ERROR_INVALID_POINTER; } } while (false); |
4287 | RefPtr<ChildSHistory> shistory = GetSessionHistory(); |
4288 | shistory.forget(aSessionHistory); |
4289 | return NS_OK; |
4290 | } |
4291 | |
4292 | //***************************************************************************** |
4293 | // nsDocShell::nsIWebPageDescriptor |
4294 | //***************************************************************************** |
4295 | |
4296 | NS_IMETHODIMPnsresult |
4297 | nsDocShell::LoadPageAsViewSource(nsIDocShell* aOtherDocShell, |
4298 | const nsAString& aURI) { |
4299 | if (!aOtherDocShell) { |
4300 | return NS_ERROR_INVALID_POINTER; |
4301 | } |
4302 | nsCOMPtr<nsIURI> newURI; |
4303 | nsresult rv = NS_NewURI(getter_AddRefs(newURI), aURI); |
4304 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
4305 | return rv; |
4306 | } |
4307 | |
4308 | RefPtr<nsDocShellLoadState> loadState; |
4309 | uint32_t cacheKey; |
4310 | auto* otherDocShell = nsDocShell::Cast(aOtherDocShell); |
4311 | if (mozilla::SessionHistoryInParent()) { |
4312 | loadState = new nsDocShellLoadState(newURI); |
4313 | if (!otherDocShell->FillLoadStateFromCurrentEntry(*loadState)) { |
4314 | return NS_ERROR_INVALID_POINTER; |
4315 | } |
4316 | cacheKey = otherDocShell->GetCacheKeyFromCurrentEntry().valueOr(0); |
4317 | } else { |
4318 | nsCOMPtr<nsISHEntry> entry; |
4319 | bool isOriginalSHE; |
4320 | otherDocShell->GetCurrentSHEntry(getter_AddRefs(entry), &isOriginalSHE); |
4321 | if (!entry) { |
4322 | return NS_ERROR_INVALID_POINTER; |
4323 | } |
4324 | rv = entry->CreateLoadInfo(getter_AddRefs(loadState)); |
4325 | 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" , 4325); return rv; } } while (false); |
4326 | entry->GetCacheKey(&cacheKey); |
4327 | loadState->SetURI(newURI); |
4328 | loadState->SetSHEntry(nullptr); |
4329 | } |
4330 | |
4331 | // We're doing a load of the page, via an API that |
4332 | // is only exposed to system code. The triggering principal for this load |
4333 | // should be the system principal. |
4334 | loadState->SetTriggeringPrincipal(nsContentUtils::GetSystemPrincipal()); |
4335 | loadState->SetOriginalURI(nullptr); |
4336 | loadState->SetResultPrincipalURI(nullptr); |
4337 | |
4338 | return InternalLoad(loadState, Some(cacheKey)); |
4339 | } |
4340 | |
4341 | NS_IMETHODIMPnsresult |
4342 | nsDocShell::GetCurrentDescriptor(nsISupports** aPageDescriptor) { |
4343 | 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" , 4343); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPageDescriptor" ") (" "Null out param?" ")"); do { *((volatile int*)__null) = 4343; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
4344 | |
4345 | *aPageDescriptor = nullptr; |
4346 | |
4347 | nsISHEntry* src = mOSHE ? mOSHE : mLSHE; |
4348 | if (src) { |
4349 | nsCOMPtr<nsISHEntry> dest; |
4350 | |
4351 | nsresult rv = src->Clone(getter_AddRefs(dest)); |
4352 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
4353 | return rv; |
4354 | } |
4355 | |
4356 | // null out inappropriate cloned attributes... |
4357 | dest->SetParent(nullptr); |
4358 | dest->SetIsSubFrame(false); |
4359 | |
4360 | return CallQueryInterface(dest, aPageDescriptor); |
4361 | } |
4362 | |
4363 | return NS_ERROR_NOT_AVAILABLE; |
4364 | } |
4365 | |
4366 | already_AddRefed<nsIInputStream> nsDocShell::GetPostDataFromCurrentEntry() |
4367 | const { |
4368 | nsCOMPtr<nsIInputStream> postData; |
4369 | if (mozilla::SessionHistoryInParent()) { |
4370 | if (mActiveEntry) { |
4371 | postData = mActiveEntry->GetPostData(); |
4372 | } else if (mLoadingEntry) { |
4373 | postData = mLoadingEntry->mInfo.GetPostData(); |
4374 | } |
4375 | } else { |
4376 | if (mOSHE) { |
4377 | postData = mOSHE->GetPostData(); |
4378 | } else if (mLSHE) { |
4379 | postData = mLSHE->GetPostData(); |
4380 | } |
4381 | } |
4382 | |
4383 | return postData.forget(); |
4384 | } |
4385 | |
4386 | Maybe<uint32_t> nsDocShell::GetCacheKeyFromCurrentEntry() const { |
4387 | if (mozilla::SessionHistoryInParent()) { |
4388 | if (mActiveEntry) { |
4389 | return Some(mActiveEntry->GetCacheKey()); |
4390 | } |
4391 | |
4392 | if (mLoadingEntry) { |
4393 | return Some(mLoadingEntry->mInfo.GetCacheKey()); |
4394 | } |
4395 | } else { |
4396 | if (mOSHE) { |
4397 | return Some(mOSHE->GetCacheKey()); |
4398 | } |
4399 | |
4400 | if (mLSHE) { |
4401 | return Some(mLSHE->GetCacheKey()); |
4402 | } |
4403 | } |
4404 | |
4405 | return Nothing(); |
4406 | } |
4407 | |
4408 | bool nsDocShell::FillLoadStateFromCurrentEntry( |
4409 | nsDocShellLoadState& aLoadState) { |
4410 | if (mLoadingEntry) { |
4411 | mLoadingEntry->mInfo.FillLoadInfo(aLoadState); |
4412 | return true; |
4413 | } |
4414 | if (mActiveEntry) { |
4415 | mActiveEntry->FillLoadInfo(aLoadState); |
4416 | return true; |
4417 | } |
4418 | return false; |
4419 | } |
4420 | |
4421 | //***************************************************************************** |
4422 | // nsDocShell::nsIBaseWindow |
4423 | //***************************************************************************** |
4424 | |
4425 | NS_IMETHODIMPnsresult |
4426 | nsDocShell::InitWindow(nativeWindow aParentNativeWindow, |
4427 | nsIWidget* aParentWidget, int32_t aX, int32_t aY, |
4428 | int32_t aWidth, int32_t aHeight) { |
4429 | SetParentWidget(aParentWidget); |
4430 | SetPositionAndSize(aX, aY, aWidth, aHeight, 0); |
4431 | 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" , 4431); return NS_ERROR_FAILURE; } } while (false); |
4432 | |
4433 | return NS_OK; |
4434 | } |
4435 | |
4436 | NS_IMETHODIMPnsresult |
4437 | nsDocShell::Destroy() { |
4438 | // XXX: We allow this function to be called just once. If you are going to |
4439 | // reset new variables in this function, please make sure the variables will |
4440 | // never be re-initialized. Adding assertions to check |mIsBeingDestroyed| |
4441 | // in the setter functions for the variables would be enough. |
4442 | if (mIsBeingDestroyed) { |
4443 | return NS_ERROR_DOCSHELL_DYING; |
4444 | } |
4445 | |
4446 | 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" , 4447); MOZ_PretendNoReturn(); } } while (0) |
4447 | "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" , 4447); MOZ_PretendNoReturn(); } } while (0); |
4448 | |
4449 | nsCOMPtr<nsIObserverService> serv = services::GetObserverService(); |
4450 | if (serv) { |
4451 | const char* msg = mItemType == typeContent |
4452 | ? NS_WEBNAVIGATION_DESTROY"webnavigation-destroy" |
4453 | : NS_CHROME_WEBNAVIGATION_DESTROY"chrome-webnavigation-destroy"; |
4454 | serv->NotifyObservers(GetAsSupports(this), msg, nullptr); |
4455 | } |
4456 | |
4457 | mIsBeingDestroyed = true; |
4458 | |
4459 | // Brak the cycle with the initial client, if present. |
4460 | mInitialClientSource.reset(); |
4461 | |
4462 | // Make sure to blow away our mLoadingURI just in case. No loads |
4463 | // from inside this pagehide. |
4464 | mLoadingURI = nullptr; |
4465 | |
4466 | // Fire unload event before we blow anything away. |
4467 | (void)FirePageHideNotification(true); |
4468 | |
4469 | // Clear pointers to any detached nsEditorData that's lying |
4470 | // around in shistory entries. Breaks cycle. See bug 430921. |
4471 | if (mOSHE) { |
4472 | mOSHE->SetEditorData(nullptr); |
4473 | } |
4474 | if (mLSHE) { |
4475 | mLSHE->SetEditorData(nullptr); |
4476 | } |
4477 | |
4478 | // Note: mContentListener can be null if Init() failed and we're being |
4479 | // called from the destructor. |
4480 | if (mContentListener) { |
4481 | mContentListener->DropDocShellReference(); |
4482 | mContentListener->SetParentContentListener(nullptr); |
4483 | // Note that we do NOT set mContentListener to null here; that |
4484 | // way if someone tries to do a load in us after this point |
4485 | // the nsDSURIContentListener will block it. All of which |
4486 | // means that we should do this before calling Stop(), of |
4487 | // course. |
4488 | } |
4489 | |
4490 | // Stop any URLs that are currently being loaded... |
4491 | Stop(nsIWebNavigation::STOP_ALL); |
4492 | |
4493 | mEditorData = nullptr; |
4494 | |
4495 | // Save the state of the current document, before destroying the window. |
4496 | // This is needed to capture the state of a frameset when the new document |
4497 | // causes the frameset to be destroyed... |
4498 | PersistLayoutHistoryState(); |
4499 | |
4500 | // Remove this docshell from its parent's child list |
4501 | nsCOMPtr<nsIDocShellTreeItem> docShellParentAsItem = |
4502 | do_QueryInterface(GetAsSupports(mParent)); |
4503 | if (docShellParentAsItem) { |
4504 | docShellParentAsItem->RemoveChild(this); |
4505 | } |
4506 | |
4507 | if (mDocumentViewer) { |
4508 | mDocumentViewer->Close(nullptr); |
4509 | mDocumentViewer->Destroy(); |
4510 | mDocumentViewer = nullptr; |
4511 | } |
4512 | |
4513 | nsDocLoader::Destroy(); |
4514 | |
4515 | mParentWidget = nullptr; |
4516 | SetCurrentURIInternal(nullptr); |
4517 | |
4518 | if (mScriptGlobal) { |
4519 | mScriptGlobal->DetachFromDocShell(!mWillChangeProcess); |
4520 | mScriptGlobal = nullptr; |
4521 | } |
4522 | |
4523 | if (GetSessionHistory()) { |
4524 | // We want to destroy these content viewers now rather than |
4525 | // letting their destruction wait for the session history |
4526 | // entries to get garbage collected. (Bug 488394) |
4527 | GetSessionHistory()->EvictLocalDocumentViewers(); |
4528 | } |
4529 | |
4530 | if (mWillChangeProcess && !mBrowsingContext->IsDiscarded()) { |
4531 | mBrowsingContext->PrepareForProcessChange(); |
4532 | } |
4533 | |
4534 | SetTreeOwner(nullptr); |
4535 | |
4536 | mBrowserChild = nullptr; |
4537 | |
4538 | mChromeEventHandler = nullptr; |
4539 | |
4540 | // Cancel any timers that were set for this docshell; this is needed |
4541 | // to break the cycle between us and the timers. |
4542 | CancelRefreshURITimers(); |
4543 | |
4544 | return NS_OK; |
4545 | } |
4546 | |
4547 | double nsDocShell::GetWidgetCSSToDeviceScale() { |
4548 | if (mParentWidget) { |
4549 | return mParentWidget->GetDefaultScale().scale; |
4550 | } |
4551 | if (nsCOMPtr<nsIBaseWindow> ownerWindow = do_QueryInterface(mTreeOwner)) { |
4552 | return ownerWindow->GetWidgetCSSToDeviceScale(); |
4553 | } |
4554 | return 1.0; |
4555 | } |
4556 | |
4557 | NS_IMETHODIMPnsresult |
4558 | nsDocShell::GetDevicePixelsPerDesktopPixel(double* aScale) { |
4559 | if (mParentWidget) { |
4560 | *aScale = mParentWidget->GetDesktopToDeviceScale().scale; |
4561 | return NS_OK; |
4562 | } |
4563 | |
4564 | nsCOMPtr<nsIBaseWindow> ownerWindow(do_QueryInterface(mTreeOwner)); |
4565 | if (ownerWindow) { |
4566 | return ownerWindow->GetDevicePixelsPerDesktopPixel(aScale); |
4567 | } |
4568 | |
4569 | *aScale = 1.0; |
4570 | return NS_OK; |
4571 | } |
4572 | |
4573 | NS_IMETHODIMPnsresult |
4574 | nsDocShell::SetPosition(int32_t aX, int32_t aY) { |
4575 | mBounds.MoveTo(aX, aY); |
4576 | |
4577 | if (mDocumentViewer) { |
4578 | 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" , 4578); return NS_ERROR_FAILURE; } } while (false); |
4579 | } |
4580 | |
4581 | return NS_OK; |
4582 | } |
4583 | |
4584 | NS_IMETHODIMPnsresult |
4585 | nsDocShell::SetPositionDesktopPix(int32_t aX, int32_t aY) { |
4586 | nsCOMPtr<nsIBaseWindow> ownerWindow(do_QueryInterface(mTreeOwner)); |
4587 | if (ownerWindow) { |
4588 | return ownerWindow->SetPositionDesktopPix(aX, aY); |
4589 | } |
4590 | |
4591 | double scale = 1.0; |
4592 | GetDevicePixelsPerDesktopPixel(&scale); |
4593 | return SetPosition(NSToIntRound(aX * scale), NSToIntRound(aY * scale)); |
4594 | } |
4595 | |
4596 | NS_IMETHODIMPnsresult |
4597 | nsDocShell::GetPosition(int32_t* aX, int32_t* aY) { |
4598 | return GetPositionAndSize(aX, aY, nullptr, nullptr); |
4599 | } |
4600 | |
4601 | NS_IMETHODIMPnsresult |
4602 | nsDocShell::SetSize(int32_t aWidth, int32_t aHeight, bool aRepaint) { |
4603 | int32_t x = 0, y = 0; |
4604 | GetPosition(&x, &y); |
4605 | return SetPositionAndSize(x, y, aWidth, aHeight, |
4606 | aRepaint ? nsIBaseWindow::eRepaint : 0); |
4607 | } |
4608 | |
4609 | NS_IMETHODIMPnsresult |
4610 | nsDocShell::GetSize(int32_t* aWidth, int32_t* aHeight) { |
4611 | return GetPositionAndSize(nullptr, nullptr, aWidth, aHeight); |
4612 | } |
4613 | |
4614 | NS_IMETHODIMPnsresult |
4615 | nsDocShell::SetPositionAndSize(int32_t aX, int32_t aY, int32_t aWidth, |
4616 | int32_t aHeight, uint32_t aFlags) { |
4617 | mBounds.SetRect(aX, aY, aWidth, aHeight); |
4618 | |
4619 | // Hold strong ref, since SetBounds can make us null out mDocumentViewer |
4620 | nsCOMPtr<nsIDocumentViewer> viewer = mDocumentViewer; |
4621 | if (viewer) { |
4622 | uint32_t cvflags = (aFlags & nsIBaseWindow::eDelayResize) |
4623 | ? nsIDocumentViewer::eDelayResize |
4624 | : 0; |
4625 | // XXX Border figured in here or is that handled elsewhere? |
4626 | nsresult rv = viewer->SetBoundsWithFlags(mBounds, cvflags); |
4627 | 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" , 4627); return NS_ERROR_FAILURE; } } while (false); |
4628 | } |
4629 | |
4630 | return NS_OK; |
4631 | } |
4632 | |
4633 | NS_IMETHODIMPnsresult |
4634 | nsDocShell::GetPositionAndSize(int32_t* aX, int32_t* aY, int32_t* aWidth, |
4635 | int32_t* aHeight) { |
4636 | if (mParentWidget) { |
4637 | // ensure size is up-to-date if window has changed resolution |
4638 | LayoutDeviceIntRect r = mParentWidget->GetClientBounds(); |
4639 | SetPositionAndSize(mBounds.X(), mBounds.Y(), r.Width(), r.Height(), 0); |
4640 | } |
4641 | |
4642 | // We should really consider just getting this information from |
4643 | // our window instead of duplicating the storage and code... |
4644 | if (aWidth || aHeight) { |
4645 | // Caller wants to know our size; make sure to give them up to |
4646 | // date information. |
4647 | RefPtr<Document> doc(do_GetInterface(GetAsSupports(mParent))); |
4648 | if (doc) { |
4649 | doc->FlushPendingNotifications(FlushType::Layout); |
4650 | } |
4651 | } |
4652 | |
4653 | DoGetPositionAndSize(aX, aY, aWidth, aHeight); |
4654 | return NS_OK; |
4655 | } |
4656 | |
4657 | void nsDocShell::DoGetPositionAndSize(int32_t* aX, int32_t* aY, int32_t* aWidth, |
4658 | int32_t* aHeight) { |
4659 | if (aX) { |
4660 | *aX = mBounds.X(); |
4661 | } |
4662 | if (aY) { |
4663 | *aY = mBounds.Y(); |
4664 | } |
4665 | if (aWidth) { |
4666 | *aWidth = mBounds.Width(); |
4667 | } |
4668 | if (aHeight) { |
4669 | *aHeight = mBounds.Height(); |
4670 | } |
4671 | } |
4672 | |
4673 | NS_IMETHODIMPnsresult |
4674 | nsDocShell::SetDimensions(DimensionRequest&& aRequest) { |
4675 | return NS_ERROR_NOT_IMPLEMENTED; |
4676 | } |
4677 | |
4678 | NS_IMETHODIMPnsresult |
4679 | nsDocShell::GetDimensions(DimensionKind aDimensionKind, int32_t* aX, |
4680 | int32_t* aY, int32_t* aCX, int32_t* aCY) { |
4681 | return NS_ERROR_NOT_IMPLEMENTED; |
4682 | } |
4683 | |
4684 | NS_IMETHODIMPnsresult |
4685 | nsDocShell::Repaint(bool aForce) { |
4686 | PresShell* presShell = GetPresShell(); |
4687 | 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" , 4687); return NS_ERROR_FAILURE; } } while (false); |
4688 | |
4689 | RefPtr<nsViewManager> viewManager = presShell->GetViewManager(); |
4690 | 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" , 4690); return NS_ERROR_FAILURE; } } while (false); |
4691 | |
4692 | viewManager->InvalidateAllViews(); |
4693 | return NS_OK; |
4694 | } |
4695 | |
4696 | NS_IMETHODIMPnsresult |
4697 | nsDocShell::GetParentWidget(nsIWidget** aParentWidget) { |
4698 | 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" , 4698); return NS_ERROR_INVALID_POINTER; } } while (false); |
4699 | |
4700 | *aParentWidget = mParentWidget; |
4701 | NS_IF_ADDREF(*aParentWidget)ns_if_addref(*aParentWidget); |
4702 | |
4703 | return NS_OK; |
4704 | } |
4705 | |
4706 | NS_IMETHODIMPnsresult |
4707 | nsDocShell::SetParentWidget(nsIWidget* aParentWidget) { |
4708 | 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" , 4708); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mIsBeingDestroyed" ")"); do { *((volatile int*)__null) = 4708; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
4709 | mParentWidget = aParentWidget; |
4710 | |
4711 | return NS_OK; |
4712 | } |
4713 | |
4714 | NS_IMETHODIMPnsresult |
4715 | nsDocShell::GetParentNativeWindow(nativeWindow* aParentNativeWindow) { |
4716 | 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" , 4716); return NS_ERROR_INVALID_POINTER; } } while (false); |
4717 | |
4718 | if (mParentWidget) { |
4719 | *aParentNativeWindow = mParentWidget->GetNativeData(NS_NATIVE_WIDGET3); |
4720 | } else { |
4721 | *aParentNativeWindow = nullptr; |
4722 | } |
4723 | |
4724 | return NS_OK; |
4725 | } |
4726 | |
4727 | NS_IMETHODIMPnsresult |
4728 | nsDocShell::SetParentNativeWindow(nativeWindow aParentNativeWindow) { |
4729 | return NS_ERROR_NOT_IMPLEMENTED; |
4730 | } |
4731 | |
4732 | NS_IMETHODIMPnsresult |
4733 | nsDocShell::GetNativeHandle(nsAString& aNativeHandle) { |
4734 | // the nativeHandle should be accessed from nsIAppWindow |
4735 | return NS_ERROR_NOT_IMPLEMENTED; |
4736 | } |
4737 | |
4738 | NS_IMETHODIMPnsresult |
4739 | nsDocShell::GetVisibility(bool* aVisibility) { |
4740 | 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" , 4740); return NS_ERROR_INVALID_POINTER; } } while (false); |
4741 | |
4742 | *aVisibility = false; |
4743 | |
4744 | if (!mDocumentViewer) { |
4745 | return NS_OK; |
4746 | } |
4747 | |
4748 | PresShell* presShell = GetPresShell(); |
4749 | if (!presShell) { |
4750 | return NS_OK; |
4751 | } |
4752 | |
4753 | // get the view manager |
4754 | nsViewManager* vm = presShell->GetViewManager(); |
4755 | 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" , 4755); return NS_ERROR_FAILURE; } } while (false); |
4756 | |
4757 | // get the root view |
4758 | nsView* view = vm->GetRootView(); // views are not ref counted |
4759 | 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" , 4759); return NS_ERROR_FAILURE; } } while (false); |
4760 | |
4761 | // if our root view is hidden, we are not visible |
4762 | if (view->GetVisibility() == ViewVisibility::Hide) { |
4763 | return NS_OK; |
4764 | } |
4765 | |
4766 | // otherwise, we must walk up the document and view trees checking |
4767 | // for a hidden view, unless we're an off screen browser, which |
4768 | // would make this test meaningless. |
4769 | |
4770 | RefPtr<nsDocShell> docShell = this; |
4771 | RefPtr<nsDocShell> parentItem = docShell->GetInProcessParentDocshell(); |
4772 | while (parentItem) { |
4773 | // Null-check for crash in bug 267804 |
4774 | if (!parentItem->GetPresShell()) { |
4775 | 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" , 4775); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: " "parent docshell has null pres shell" ")"); do { *((volatile int*)__null) = 4775; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
4776 | return NS_OK; |
4777 | } |
4778 | |
4779 | vm = docShell->GetPresShell()->GetViewManager(); |
4780 | if (vm) { |
4781 | view = vm->GetRootView(); |
4782 | } |
4783 | |
4784 | if (view) { |
4785 | view = view->GetParent(); // anonymous inner view |
4786 | if (view) { |
4787 | view = view->GetParent(); // subdocumentframe's view |
4788 | } |
4789 | } |
4790 | |
4791 | nsIFrame* frame = view ? view->GetFrame() : nullptr; |
4792 | if (frame && !frame->IsVisibleConsideringAncestors( |
4793 | nsIFrame::VISIBILITY_CROSS_CHROME_CONTENT_BOUNDARY)) { |
4794 | return NS_OK; |
4795 | } |
4796 | |
4797 | docShell = parentItem; |
4798 | parentItem = docShell->GetInProcessParentDocshell(); |
4799 | } |
4800 | |
4801 | nsCOMPtr<nsIBaseWindow> treeOwnerAsWin(do_QueryInterface(mTreeOwner)); |
4802 | if (!treeOwnerAsWin) { |
4803 | *aVisibility = true; |
4804 | return NS_OK; |
4805 | } |
4806 | |
4807 | // Check with the tree owner as well to give embedders a chance to |
4808 | // expose visibility as well. |
4809 | nsresult rv = treeOwnerAsWin->GetVisibility(aVisibility); |
4810 | if (rv == NS_ERROR_NOT_IMPLEMENTED) { |
4811 | // The tree owner had no opinion on our visibility. |
4812 | *aVisibility = true; |
4813 | return NS_OK; |
4814 | } |
4815 | return rv; |
4816 | } |
4817 | |
4818 | void nsDocShell::ActivenessMaybeChanged() { |
4819 | const bool isActive = mBrowsingContext->IsActive(); |
4820 | if (RefPtr<PresShell> presShell = GetPresShell()) { |
4821 | presShell->ActivenessMaybeChanged(); |
4822 | } |
4823 | |
4824 | // Tell the window about it |
4825 | if (mScriptGlobal) { |
4826 | mScriptGlobal->SetIsBackground(!isActive); |
4827 | if (RefPtr<Document> doc = mScriptGlobal->GetExtantDoc()) { |
4828 | // Update orientation when the top-level browsing context becomes active. |
4829 | if (isActive && mBrowsingContext->IsTop()) { |
4830 | // We only care about the top-level browsing context. |
4831 | auto orientation = mBrowsingContext->GetOrientationLock(); |
4832 | ScreenOrientation::UpdateActiveOrientationLock(orientation); |
4833 | } |
4834 | |
4835 | doc->PostVisibilityUpdateEvent(); |
4836 | } |
4837 | } |
4838 | |
4839 | // Tell the nsDOMNavigationTiming about it |
4840 | RefPtr<nsDOMNavigationTiming> timing = mTiming; |
4841 | if (!timing && mDocumentViewer) { |
4842 | if (Document* doc = mDocumentViewer->GetDocument()) { |
4843 | timing = doc->GetNavigationTiming(); |
4844 | } |
4845 | } |
4846 | if (timing) { |
4847 | timing->NotifyDocShellStateChanged( |
4848 | isActive ? nsDOMNavigationTiming::DocShellState::eActive |
4849 | : nsDOMNavigationTiming::DocShellState::eInactive); |
4850 | } |
4851 | |
4852 | // Restart or stop meta refresh timers if necessary |
4853 | if (mDisableMetaRefreshWhenInactive) { |
4854 | if (isActive) { |
4855 | ResumeRefreshURIs(); |
4856 | } else { |
4857 | SuspendRefreshURIs(); |
4858 | } |
4859 | } |
4860 | |
4861 | if (InputTaskManager::CanSuspendInputEvent()) { |
4862 | mBrowsingContext->Group()->UpdateInputTaskManagerIfNeeded(isActive); |
4863 | } |
4864 | } |
4865 | |
4866 | NS_IMETHODIMPnsresult |
4867 | nsDocShell::SetDefaultLoadFlags(uint32_t aDefaultLoadFlags) { |
4868 | if (!mWillChangeProcess) { |
4869 | // Intentionally ignoring handling discarded browsing contexts. |
4870 | Unused << mBrowsingContext->SetDefaultLoadFlags(aDefaultLoadFlags); |
4871 | } else { |
4872 | // Bug 1623565: DevTools tries to clean up defaultLoadFlags on |
4873 | // shutdown. Sorry DevTools, your DocShell is in another process. |
4874 | 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" , 4874); |
4875 | } |
4876 | return NS_OK; |
4877 | } |
4878 | |
4879 | NS_IMETHODIMPnsresult |
4880 | nsDocShell::GetDefaultLoadFlags(uint32_t* aDefaultLoadFlags) { |
4881 | *aDefaultLoadFlags = mBrowsingContext->GetDefaultLoadFlags(); |
4882 | return NS_OK; |
4883 | } |
4884 | |
4885 | NS_IMETHODIMPnsresult |
4886 | nsDocShell::GetFailedChannel(nsIChannel** aFailedChannel) { |
4887 | 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" , 4887); return NS_ERROR_INVALID_POINTER; } } while (false); |
4888 | Document* doc = GetDocument(); |
4889 | if (!doc) { |
4890 | *aFailedChannel = nullptr; |
4891 | return NS_OK; |
4892 | } |
4893 | NS_IF_ADDREF(*aFailedChannel = doc->GetFailedChannel())ns_if_addref(*aFailedChannel = doc->GetFailedChannel()); |
4894 | return NS_OK; |
4895 | } |
4896 | |
4897 | NS_IMETHODIMPnsresult |
4898 | nsDocShell::SetVisibility(bool aVisibility) { |
4899 | // Show()/Hide() may change mDocumentViewer. |
4900 | nsCOMPtr<nsIDocumentViewer> viewer = mDocumentViewer; |
4901 | if (!viewer) { |
4902 | return NS_OK; |
4903 | } |
4904 | if (aVisibility) { |
4905 | viewer->Show(); |
4906 | } else { |
4907 | viewer->Hide(); |
4908 | } |
4909 | |
4910 | return NS_OK; |
4911 | } |
4912 | |
4913 | NS_IMETHODIMPnsresult |
4914 | nsDocShell::GetEnabled(bool* aEnabled) { |
4915 | 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" , 4915); return NS_ERROR_INVALID_POINTER; } } while (false); |
4916 | *aEnabled = true; |
4917 | return NS_ERROR_NOT_IMPLEMENTED; |
4918 | } |
4919 | |
4920 | NS_IMETHODIMPnsresult |
4921 | nsDocShell::SetEnabled(bool aEnabled) { return NS_ERROR_NOT_IMPLEMENTED; } |
4922 | |
4923 | NS_IMETHODIMPnsresult |
4924 | nsDocShell::GetMainWidget(nsIWidget** aMainWidget) { |
4925 | // We don't create our own widget, so simply return the parent one. |
4926 | return GetParentWidget(aMainWidget); |
4927 | } |
4928 | |
4929 | NS_IMETHODIMPnsresult |
4930 | nsDocShell::GetTitle(nsAString& aTitle) { |
4931 | aTitle = mTitle; |
4932 | return NS_OK; |
4933 | } |
4934 | |
4935 | NS_IMETHODIMPnsresult |
4936 | nsDocShell::SetTitle(const nsAString& aTitle) { |
4937 | // Avoid unnecessary updates of the title if the URI and the title haven't |
4938 | // changed. |
4939 | if (mTitleValidForCurrentURI && mTitle == aTitle) { |
4940 | return NS_OK; |
4941 | } |
4942 | |
4943 | // Store local title |
4944 | mTitle = aTitle; |
4945 | mTitleValidForCurrentURI = true; |
4946 | |
4947 | // When title is set on the top object it should then be passed to the |
4948 | // tree owner. |
4949 | if (mBrowsingContext->IsTop()) { |
4950 | nsCOMPtr<nsIBaseWindow> treeOwnerAsWin(do_QueryInterface(mTreeOwner)); |
4951 | if (treeOwnerAsWin) { |
4952 | treeOwnerAsWin->SetTitle(aTitle); |
4953 | } |
4954 | } |
4955 | |
4956 | if (mCurrentURI && mLoadType != LOAD_ERROR_PAGE) { |
4957 | UpdateGlobalHistoryTitle(mCurrentURI); |
4958 | } |
4959 | |
4960 | // Update SessionHistory with the document's title. |
4961 | if (mLoadType != LOAD_BYPASS_HISTORY && mLoadType != LOAD_ERROR_PAGE) { |
4962 | SetTitleOnHistoryEntry(true); |
4963 | } |
4964 | |
4965 | return NS_OK; |
4966 | } |
4967 | |
4968 | void nsDocShell::SetTitleOnHistoryEntry(bool aUpdateEntryInSessionHistory) { |
4969 | if (mOSHE) { |
4970 | mOSHE->SetTitle(mTitle); |
4971 | } |
4972 | |
4973 | if (mActiveEntry && mBrowsingContext) { |
4974 | mActiveEntry->SetTitle(mTitle); |
4975 | if (aUpdateEntryInSessionHistory) { |
4976 | if (XRE_IsParentProcess()) { |
4977 | SessionHistoryEntry* entry = |
4978 | mBrowsingContext->Canonical()->GetActiveSessionHistoryEntry(); |
4979 | if (entry) { |
4980 | entry->SetTitle(mTitle); |
4981 | } |
4982 | } else { |
4983 | mozilla::Unused |
4984 | << ContentChild::GetSingleton()->SendSessionHistoryEntryTitle( |
4985 | mBrowsingContext, mTitle); |
4986 | } |
4987 | } |
4988 | } |
4989 | } |
4990 | |
4991 | nsPoint nsDocShell::GetCurScrollPos() { |
4992 | nsPoint scrollPos; |
4993 | if (nsIScrollableFrame* sf = GetRootScrollFrame()) { |
4994 | scrollPos = sf->GetVisualViewportOffset(); |
4995 | } |
4996 | return scrollPos; |
4997 | } |
4998 | |
4999 | nsresult nsDocShell::SetCurScrollPosEx(int32_t aCurHorizontalPos, |
5000 | int32_t aCurVerticalPos) { |
5001 | nsIScrollableFrame* sf = GetRootScrollFrame(); |
5002 | 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" , 5002); return NS_ERROR_FAILURE; } } while (false); |
5003 | |
5004 | ScrollMode scrollMode = |
5005 | sf->IsSmoothScroll() ? ScrollMode::SmoothMsd : ScrollMode::Instant; |
5006 | |
5007 | nsPoint targetPos(aCurHorizontalPos, aCurVerticalPos); |
5008 | sf->ScrollTo(targetPos, scrollMode); |
5009 | |
5010 | // Set the visual viewport offset as well. |
5011 | |
5012 | RefPtr<PresShell> presShell = GetPresShell(); |
5013 | 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" , 5013); return NS_ERROR_FAILURE; } } while (false); |
5014 | |
5015 | nsPresContext* presContext = presShell->GetPresContext(); |
5016 | 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" , 5016); return NS_ERROR_FAILURE; } } while (false); |
5017 | |
5018 | // Only the root content document can have a distinct visual viewport offset. |
5019 | if (!presContext->IsRootContentDocumentCrossProcess()) { |
5020 | return NS_OK; |
5021 | } |
5022 | |
5023 | // Not on a platform with a distinct visual viewport - don't bother setting |
5024 | // the visual viewport offset. |
5025 | if (!presShell->IsVisualViewportSizeSet()) { |
5026 | return NS_OK; |
5027 | } |
5028 | |
5029 | presShell->ScrollToVisual(targetPos, layers::FrameMetrics::eMainThread, |
5030 | scrollMode); |
5031 | |
5032 | return NS_OK; |
5033 | } |
5034 | |
5035 | void nsDocShell::SetScrollbarPreference(mozilla::ScrollbarPreference aPref) { |
5036 | if (mScrollbarPref == aPref) { |
5037 | return; |
5038 | } |
5039 | mScrollbarPref = aPref; |
5040 | auto* ps = GetPresShell(); |
5041 | if (!ps) { |
5042 | return; |
5043 | } |
5044 | nsIFrame* scrollFrame = ps->GetRootScrollFrame(); |
5045 | if (!scrollFrame) { |
5046 | return; |
5047 | } |
5048 | ps->FrameNeedsReflow(scrollFrame, |
5049 | IntrinsicDirty::FrameAncestorsAndDescendants, |
5050 | NS_FRAME_IS_DIRTY); |
5051 | } |
5052 | |
5053 | //***************************************************************************** |
5054 | // nsDocShell::nsIRefreshURI |
5055 | //***************************************************************************** |
5056 | |
5057 | NS_IMETHODIMPnsresult |
5058 | nsDocShell::RefreshURI(nsIURI* aURI, nsIPrincipal* aPrincipal, |
5059 | uint32_t aDelay) { |
5060 | 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" , 5060); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mIsBeingDestroyed" ")"); do { *((volatile int*)__null) = 5060; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
5061 | |
5062 | 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" , 5062); return NS_ERROR_INVALID_ARG; } } while (false); |
5063 | |
5064 | /* Check if Meta refresh/redirects are permitted. Some |
5065 | * embedded applications may not want to do this. |
5066 | * Must do this before sending out NOTIFY_REFRESH events |
5067 | * because listeners may have side effects (e.g. displaying a |
5068 | * button to manually trigger the refresh later). |
5069 | */ |
5070 | bool allowRedirects = true; |
5071 | GetAllowMetaRedirects(&allowRedirects); |
5072 | if (!allowRedirects) { |
5073 | return NS_OK; |
5074 | } |
5075 | |
5076 | // If any web progress listeners are listening for NOTIFY_REFRESH events, |
5077 | // give them a chance to block this refresh. |
5078 | bool sameURI; |
5079 | nsresult rv = aURI->Equals(mCurrentURI, &sameURI); |
5080 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
5081 | sameURI = false; |
5082 | } |
5083 | if (!RefreshAttempted(this, aURI, aDelay, sameURI)) { |
5084 | return NS_OK; |
5085 | } |
5086 | |
5087 | nsCOMPtr<nsITimerCallback> refreshTimer = |
5088 | new nsRefreshTimer(this, aURI, aPrincipal, aDelay); |
5089 | |
5090 | BusyFlags busyFlags = GetBusyFlags(); |
5091 | |
5092 | if (!mRefreshURIList) { |
5093 | mRefreshURIList = nsArray::Create(); |
5094 | } |
5095 | |
5096 | if (busyFlags & BUSY_FLAGS_BUSY || |
5097 | (!mBrowsingContext->IsActive() && mDisableMetaRefreshWhenInactive)) { |
5098 | // We don't want to create the timer right now. Instead queue up the |
5099 | // request and trigger the timer in EndPageLoad() or whenever we become |
5100 | // active. |
5101 | mRefreshURIList->AppendElement(refreshTimer); |
5102 | } else { |
5103 | // There is no page loading going on right now. Create the |
5104 | // timer and fire it right away. |
5105 | nsCOMPtr<nsPIDOMWindowOuter> win = GetWindow(); |
5106 | 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" , 5106); return NS_ERROR_FAILURE; } } while (false); |
5107 | |
5108 | nsCOMPtr<nsITimer> timer; |
5109 | 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) |
5110 | 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); |
5111 | |
5112 | mRefreshURIList->AppendElement(timer); // owning timer ref |
5113 | } |
5114 | return NS_OK; |
5115 | } |
5116 | |
5117 | nsresult nsDocShell::ForceRefreshURIFromTimer(nsIURI* aURI, |
5118 | nsIPrincipal* aPrincipal, |
5119 | uint32_t aDelay, |
5120 | nsITimer* aTimer) { |
5121 | 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" , 5121); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aTimer" ") (" "Must have a timer here" ")"); do { *((volatile int*)__null) = 5121; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
5122 | |
5123 | // Remove aTimer from mRefreshURIList if needed |
5124 | if (mRefreshURIList) { |
5125 | uint32_t n = 0; |
5126 | mRefreshURIList->GetLength(&n); |
5127 | |
5128 | for (uint32_t i = 0; i < n; ++i) { |
5129 | nsCOMPtr<nsITimer> timer = do_QueryElementAt(mRefreshURIList, i); |
5130 | if (timer == aTimer) { |
5131 | mRefreshURIList->RemoveElementAt(i); |
5132 | break; |
5133 | } |
5134 | } |
5135 | } |
5136 | |
5137 | return ForceRefreshURI(aURI, aPrincipal, aDelay); |
5138 | } |
5139 | |
5140 | NS_IMETHODIMPnsresult |
5141 | nsDocShell::ForceRefreshURI(nsIURI* aURI, nsIPrincipal* aPrincipal, |
5142 | uint32_t aDelay) { |
5143 | 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" , 5143); return NS_ERROR_INVALID_ARG; } } while (false); |
5144 | |
5145 | RefPtr<nsDocShellLoadState> loadState = new nsDocShellLoadState(aURI); |
5146 | loadState->SetOriginalURI(mCurrentURI); |
5147 | loadState->SetResultPrincipalURI(aURI); |
5148 | loadState->SetResultPrincipalURIIsSome(true); |
5149 | loadState->SetKeepResultPrincipalURIIfSet(true); |
5150 | loadState->SetIsMetaRefresh(true); |
5151 | |
5152 | // Set the triggering pricipal to aPrincipal if available, or current |
5153 | // document's principal otherwise. |
5154 | nsCOMPtr<nsIPrincipal> principal = aPrincipal; |
5155 | RefPtr<Document> doc = GetDocument(); |
5156 | if (!principal) { |
5157 | if (!doc) { |
5158 | return NS_ERROR_FAILURE; |
5159 | } |
5160 | principal = doc->NodePrincipal(); |
5161 | } |
5162 | loadState->SetTriggeringPrincipal(principal); |
5163 | if (doc) { |
5164 | loadState->SetCsp(doc->GetCsp()); |
5165 | loadState->SetHasValidUserGestureActivation( |
5166 | doc->HasValidTransientUserGestureActivation()); |
5167 | loadState->SetTriggeringSandboxFlags(doc->GetSandboxFlags()); |
5168 | loadState->SetTriggeringWindowId(doc->InnerWindowID()); |
5169 | loadState->SetTriggeringStorageAccess(doc->UsingStorageAccess()); |
5170 | } |
5171 | |
5172 | loadState->SetPrincipalIsExplicit(true); |
5173 | |
5174 | /* Check if this META refresh causes a redirection |
5175 | * to another site. |
5176 | */ |
5177 | bool equalUri = false; |
5178 | nsresult rv = aURI->Equals(mCurrentURI, &equalUri); |
5179 | |
5180 | nsCOMPtr<nsIReferrerInfo> referrerInfo; |
5181 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && !equalUri && aDelay <= REFRESH_REDIRECT_TIMER15000) { |
5182 | /* It is a META refresh based redirection within the threshold time |
5183 | * we have in mind (15000 ms as defined by REFRESH_REDIRECT_TIMER). |
5184 | * Pass a REPLACE flag to LoadURI(). |
5185 | */ |
5186 | loadState->SetLoadType(LOAD_REFRESH_REPLACE); |
5187 | |
5188 | /* For redirects we mimic HTTP, which passes the |
5189 | * original referrer. |
5190 | * We will pass in referrer but will not send to server |
5191 | */ |
5192 | if (mReferrerInfo) { |
5193 | referrerInfo = static_cast<ReferrerInfo*>(mReferrerInfo.get()) |
5194 | ->CloneWithNewSendReferrer(false); |
5195 | } |
5196 | } else { |
5197 | loadState->SetLoadType(LOAD_REFRESH); |
5198 | /* We do need to pass in a referrer, but we don't want it to |
5199 | * be sent to the server. |
5200 | * For most refreshes the current URI is an appropriate |
5201 | * internal referrer. |
5202 | */ |
5203 | referrerInfo = new ReferrerInfo(mCurrentURI, ReferrerPolicy::_empty, false); |
5204 | } |
5205 | |
5206 | loadState->SetReferrerInfo(referrerInfo); |
5207 | loadState->SetLoadFlags( |
5208 | nsIWebNavigation::LOAD_FLAGS_DISALLOW_INHERIT_PRINCIPAL); |
5209 | loadState->SetFirstParty(true); |
5210 | |
5211 | /* |
5212 | * LoadURI(...) will cancel all refresh timers... This causes the |
5213 | * Timer and its refreshData instance to be released... |
5214 | */ |
5215 | LoadURI(loadState, false); |
5216 | |
5217 | return NS_OK; |
5218 | } |
5219 | |
5220 | static const char16_t* SkipASCIIWhitespace(const char16_t* aStart, |
5221 | const char16_t* aEnd) { |
5222 | const char16_t* iter = aStart; |
5223 | while (iter != aEnd && mozilla::IsAsciiWhitespace(*iter)) { |
5224 | ++iter; |
5225 | } |
5226 | return iter; |
5227 | } |
5228 | |
5229 | static std::tuple<const char16_t*, const char16_t*> ExtractURLString( |
5230 | const char16_t* aPosition, const char16_t* aEnd) { |
5231 | 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" , 5231); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPosition != aEnd" ")"); do { *((volatile int*)__null) = 5231; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
5232 | |
5233 | // 1. Let urlString be the substring of input from the code point at |
5234 | // position to the end of the string. |
5235 | const char16_t* urlStart = aPosition; |
5236 | const char16_t* urlEnd = aEnd; |
5237 | |
5238 | // 2. If the code point in input pointed to by position is U+0055 (U) or |
5239 | // U+0075 (u), then advance position to the next code point. |
5240 | // Otherwise, jump to the step labeled skip quotes. |
5241 | if (*aPosition == 'U' || *aPosition == 'u') { |
5242 | ++aPosition; |
5243 | |
5244 | // 3. If the code point in input pointed to by position is U+0052 (R) or |
5245 | // U+0072 (r), then advance position to the next code point. |
5246 | // Otherwise, jump to the step labeled parse. |
5247 | if (aPosition == aEnd || (*aPosition != 'R' && *aPosition != 'r')) { |
5248 | return std::make_tuple(urlStart, urlEnd); |
5249 | } |
5250 | |
5251 | ++aPosition; |
5252 | |
5253 | // 4. If the code point in input pointed to by position is U+004C (L) or |
5254 | // U+006C (l), then advance position to the next code point. |
5255 | // Otherwise, jump to the step labeled parse. |
5256 | if (aPosition == aEnd || (*aPosition != 'L' && *aPosition != 'l')) { |
5257 | return std::make_tuple(urlStart, urlEnd); |
5258 | } |
5259 | |
5260 | ++aPosition; |
5261 | |
5262 | // 5. Skip ASCII whitespace within input given position. |
5263 | aPosition = SkipASCIIWhitespace(aPosition, aEnd); |
5264 | |
5265 | // 6. If the code point in input pointed to by position is U+003D (=), |
5266 | // then advance position to the next code point. Otherwise, jump to |
5267 | // the step labeled parse. |
5268 | if (aPosition == aEnd || *aPosition != '=') { |
5269 | return std::make_tuple(urlStart, urlEnd); |
5270 | } |
5271 | |
5272 | ++aPosition; |
5273 | |
5274 | // 7. Skip ASCII whitespace within input given position. |
5275 | aPosition = SkipASCIIWhitespace(aPosition, aEnd); |
5276 | } |
5277 | |
5278 | // 8. Skip quotes: If the code point in input pointed to by position is |
5279 | // U+0027 (') or U+0022 ("), then let quote be that code point, and |
5280 | // advance position to the next code point. Otherwise, let quote be |
5281 | // the empty string. |
5282 | Maybe<char> quote; |
5283 | if (aPosition != aEnd && (*aPosition == '\'' || *aPosition == '"')) { |
5284 | quote.emplace(*aPosition); |
5285 | ++aPosition; |
5286 | } |
5287 | |
5288 | // 9. Set urlString to the substring of input from the code point at |
5289 | // position to the end of the string. |
5290 | urlStart = aPosition; |
5291 | urlEnd = aEnd; |
5292 | |
5293 | // 10. If quote is not the empty string, and there is a code point in |
5294 | // urlString equal to quote, then truncate urlString at that code |
5295 | // point, so that it and all subsequent code points are removed. |
5296 | const char16_t* quotePos; |
5297 | if (quote.isSome() && |
5298 | (quotePos = nsCharTraits<char16_t>::find( |
5299 | urlStart, std::distance(urlStart, aEnd), quote.value()))) { |
5300 | urlEnd = quotePos; |
5301 | } |
5302 | |
5303 | return std::make_tuple(urlStart, urlEnd); |
5304 | } |
5305 | |
5306 | void nsDocShell::SetupRefreshURIFromHeader(Document* aDocument, |
5307 | const nsAString& aHeader) { |
5308 | if (mIsBeingDestroyed) { |
5309 | return; |
5310 | } |
5311 | |
5312 | const char16_t* position = aHeader.BeginReading(); |
5313 | const char16_t* end = aHeader.EndReading(); |
5314 | |
5315 | // See |
5316 | // https://html.spec.whatwg.org/#pragma-directives:shared-declarative-refresh-steps. |
5317 | |
5318 | // 3. Skip ASCII whitespace |
5319 | position = SkipASCIIWhitespace(position, end); |
5320 | |
5321 | // 4. Let time be 0. |
5322 | CheckedInt<uint32_t> milliSeconds; |
5323 | |
5324 | // 5. Collect a sequence of code points that are ASCII digits |
5325 | const char16_t* digitsStart = position; |
5326 | while (position != end && mozilla::IsAsciiDigit(*position)) { |
5327 | ++position; |
5328 | } |
5329 | |
5330 | if (position == digitsStart) { |
5331 | // 6. If timeString is the empty string, then: |
5332 | // 1. If the code point in input pointed to by position is not U+002E |
5333 | // (.), then return. |
5334 | if (position == end || *position != '.') { |
5335 | return; |
5336 | } |
5337 | } else { |
5338 | // 7. Otherwise, set time to the result of parsing timeString using the |
5339 | // rules for parsing non-negative integers. |
5340 | nsContentUtils::ParseHTMLIntegerResultFlags result; |
5341 | uint32_t seconds = |
5342 | nsContentUtils::ParseHTMLInteger(digitsStart, position, &result); |
5343 | 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" , 5343); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!(result & nsContentUtils::eParseHTMLInteger_Negative)" ")"); do { *((volatile int*)__null) = 5343; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
5344 | if (result & nsContentUtils::eParseHTMLInteger_Error) { |
5345 | // The spec assumes no errors here (since we only pass ASCII digits in), |
5346 | // but we can still overflow, so this block should deal with that (and |
5347 | // only that). |
5348 | 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" , 5348); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!(result & nsContentUtils::eParseHTMLInteger_ErrorOverflow)" ")"); do { *((volatile int*)__null) = 5348; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
5349 | return; |
5350 | } |
5351 | MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType< decltype(!(result & nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput ))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(!(result & nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("!(result & nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput)" , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 5352); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!(result & nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput)" ")"); do { *((volatile int*)__null) = 5352; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
5352 | !(result & nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput))do { static_assert( mozilla::detail::AssertionConditionType< decltype(!(result & nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput ))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(!(result & nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("!(result & nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput)" , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 5352); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!(result & nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput)" ")"); do { *((volatile int*)__null) = 5352; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
5353 | |
5354 | milliSeconds = seconds; |
5355 | milliSeconds *= 1000; |
5356 | if (!milliSeconds.isValid()) { |
5357 | return; |
5358 | } |
5359 | } |
5360 | |
5361 | // 8. Collect a sequence of code points that are ASCII digits and U+002E FULL |
5362 | // STOP characters (.) from input given position. Ignore any collected |
5363 | // characters. |
5364 | while (position != end && |
5365 | (mozilla::IsAsciiDigit(*position) || *position == '.')) { |
5366 | ++position; |
5367 | } |
5368 | |
5369 | // 9. Let urlRecord be document's URL. |
5370 | nsCOMPtr<nsIURI> urlRecord(aDocument->GetDocumentURI()); |
5371 | |
5372 | // 10. If position is not past the end of input |
5373 | if (position != end) { |
5374 | // 1. If the code point in input pointed to by position is not U+003B (;), |
5375 | // U+002C (,), or ASCII whitespace, then return. |
5376 | if (*position != ';' && *position != ',' && |
5377 | !mozilla::IsAsciiWhitespace(*position)) { |
5378 | return; |
5379 | } |
5380 | |
5381 | // 2. Skip ASCII whitespace within input given position. |
5382 | position = SkipASCIIWhitespace(position, end); |
5383 | |
5384 | // 3. If the code point in input pointed to by position is U+003B (;) or |
5385 | // U+002C (,), then advance position to the next code point. |
5386 | if (position != end && (*position == ';' || *position == ',')) { |
5387 | ++position; |
5388 | |
5389 | // 4. Skip ASCII whitespace within input given position. |
5390 | position = SkipASCIIWhitespace(position, end); |
5391 | } |
5392 | |
5393 | // 11. If position is not past the end of input, then: |
5394 | if (position != end) { |
5395 | const char16_t* urlStart; |
5396 | const char16_t* urlEnd; |
5397 | |
5398 | // 1-10. See ExtractURLString. |
5399 | std::tie(urlStart, urlEnd) = ExtractURLString(position, end); |
5400 | |
5401 | // 11. Parse: Parse urlString relative to document. If that fails, return. |
5402 | // Otherwise, set urlRecord to the resulting URL record. |
5403 | nsresult rv = |
5404 | NS_NewURI(getter_AddRefs(urlRecord), |
5405 | Substring(urlStart, std::distance(urlStart, urlEnd)), |
5406 | /* charset = */ nullptr, aDocument->GetDocBaseURI()); |
5407 | NS_ENSURE_SUCCESS_VOID(rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS_VOID(%s) failed with " "result 0x%" "X" "%s%s%s", "rv", static_cast<uint32_t> (__rv), name ? " (" : "", name ? name : "", name ? ")" : ""); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 5407); return; } } while (false); |
5408 | } |
5409 | } |
5410 | |
5411 | nsIPrincipal* principal = aDocument->NodePrincipal(); |
5412 | nsCOMPtr<nsIScriptSecurityManager> securityManager = |
5413 | nsContentUtils::GetSecurityManager(); |
5414 | nsresult rv = securityManager->CheckLoadURIWithPrincipal( |
5415 | principal, urlRecord, |
5416 | nsIScriptSecurityManager::LOAD_IS_AUTOMATIC_DOCUMENT_REPLACEMENT, |
5417 | aDocument->InnerWindowID()); |
5418 | NS_ENSURE_SUCCESS_VOID(rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS_VOID(%s) failed with " "result 0x%" "X" "%s%s%s", "rv", static_cast<uint32_t> (__rv), name ? " (" : "", name ? name : "", name ? ")" : ""); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 5418); return; } } while (false); |
5419 | |
5420 | bool isjs = true; |
5421 | rv = NS_URIChainHasFlags( |
5422 | urlRecord, nsIProtocolHandler::URI_OPENING_EXECUTES_SCRIPT, &isjs); |
5423 | NS_ENSURE_SUCCESS_VOID(rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS_VOID(%s) failed with " "result 0x%" "X" "%s%s%s", "rv", static_cast<uint32_t> (__rv), name ? " (" : "", name ? name : "", name ? ")" : ""); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 5423); return; } } while (false); |
5424 | |
5425 | if (isjs) { |
5426 | return; |
5427 | } |
5428 | |
5429 | RefreshURI(urlRecord, principal, milliSeconds.value()); |
5430 | } |
5431 | |
5432 | static void DoCancelRefreshURITimers(nsIMutableArray* aTimerList) { |
5433 | if (!aTimerList) { |
5434 | return; |
5435 | } |
5436 | |
5437 | uint32_t n = 0; |
5438 | aTimerList->GetLength(&n); |
5439 | |
5440 | while (n) { |
5441 | nsCOMPtr<nsITimer> timer(do_QueryElementAt(aTimerList, --n)); |
5442 | |
5443 | aTimerList->RemoveElementAt(n); // bye bye owning timer ref |
5444 | |
5445 | if (timer) { |
5446 | timer->Cancel(); |
5447 | } |
5448 | } |
5449 | } |
5450 | |
5451 | NS_IMETHODIMPnsresult |
5452 | nsDocShell::CancelRefreshURITimers() { |
5453 | DoCancelRefreshURITimers(mRefreshURIList); |
5454 | DoCancelRefreshURITimers(mSavedRefreshURIList); |
5455 | DoCancelRefreshURITimers(mBFCachedRefreshURIList); |
5456 | mRefreshURIList = nullptr; |
5457 | mSavedRefreshURIList = nullptr; |
5458 | mBFCachedRefreshURIList = nullptr; |
5459 | |
5460 | return NS_OK; |
5461 | } |
5462 | |
5463 | NS_IMETHODIMPnsresult |
5464 | nsDocShell::GetRefreshPending(bool* aResult) { |
5465 | if (!mRefreshURIList) { |
5466 | *aResult = false; |
5467 | return NS_OK; |
5468 | } |
5469 | |
5470 | uint32_t count; |
5471 | nsresult rv = mRefreshURIList->GetLength(&count); |
5472 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) { |
5473 | *aResult = (count != 0); |
5474 | } |
5475 | return rv; |
5476 | } |
5477 | |
5478 | void nsDocShell::RefreshURIToQueue() { |
5479 | if (mRefreshURIList) { |
5480 | uint32_t n = 0; |
5481 | mRefreshURIList->GetLength(&n); |
5482 | |
5483 | for (uint32_t i = 0; i < n; ++i) { |
5484 | nsCOMPtr<nsITimer> timer = do_QueryElementAt(mRefreshURIList, i); |
5485 | if (!timer) { |
5486 | continue; // this must be a nsRefreshURI already |
5487 | } |
5488 | |
5489 | // Replace this timer object with a nsRefreshTimer object. |
5490 | nsCOMPtr<nsITimerCallback> callback; |
5491 | timer->GetCallback(getter_AddRefs(callback)); |
5492 | |
5493 | timer->Cancel(); |
5494 | |
5495 | mRefreshURIList->ReplaceElementAt(callback, i); |
5496 | } |
5497 | } |
5498 | } |
5499 | |
5500 | NS_IMETHODIMPnsresult |
5501 | nsDocShell::SuspendRefreshURIs() { |
5502 | RefreshURIToQueue(); |
5503 | |
5504 | // Suspend refresh URIs for our child shells as well. |
5505 | for (auto* child : mChildList.ForwardRange()) { |
5506 | nsCOMPtr<nsIDocShell> shell = do_QueryObject(child); |
5507 | if (shell) { |
5508 | shell->SuspendRefreshURIs(); |
5509 | } |
5510 | } |
5511 | |
5512 | return NS_OK; |
5513 | } |
5514 | |
5515 | NS_IMETHODIMPnsresult |
5516 | nsDocShell::ResumeRefreshURIs() { |
5517 | RefreshURIFromQueue(); |
5518 | |
5519 | // Resume refresh URIs for our child shells as well. |
5520 | for (auto* child : mChildList.ForwardRange()) { |
5521 | nsCOMPtr<nsIDocShell> shell = do_QueryObject(child); |
5522 | if (shell) { |
5523 | shell->ResumeRefreshURIs(); |
5524 | } |
5525 | } |
5526 | |
5527 | return NS_OK; |
5528 | } |
5529 | |
5530 | nsresult nsDocShell::RefreshURIFromQueue() { |
5531 | if (!mRefreshURIList) { |
5532 | return NS_OK; |
5533 | } |
5534 | uint32_t n = 0; |
5535 | mRefreshURIList->GetLength(&n); |
5536 | |
5537 | while (n) { |
5538 | nsCOMPtr<nsITimerCallback> refreshInfo = |
5539 | do_QueryElementAt(mRefreshURIList, --n); |
5540 | |
5541 | if (refreshInfo) { |
5542 | // This is the nsRefreshTimer object, waiting to be |
5543 | // setup in a timer object and fired. |
5544 | // Create the timer and trigger it. |
5545 | uint32_t delay = static_cast<nsRefreshTimer*>( |
5546 | static_cast<nsITimerCallback*>(refreshInfo)) |
5547 | ->GetDelay(); |
5548 | nsCOMPtr<nsPIDOMWindowOuter> win = GetWindow(); |
5549 | if (win) { |
5550 | nsCOMPtr<nsITimer> timer; |
5551 | NS_NewTimerWithCallback(getter_AddRefs(timer), refreshInfo, delay, |
5552 | nsITimer::TYPE_ONE_SHOT); |
5553 | |
5554 | if (timer) { |
5555 | // Replace the nsRefreshTimer element in the queue with |
5556 | // its corresponding timer object, so that in case another |
5557 | // load comes through before the timer can go off, the timer will |
5558 | // get cancelled in CancelRefreshURITimer() |
5559 | mRefreshURIList->ReplaceElementAt(timer, n); |
5560 | } |
5561 | } |
5562 | } |
5563 | } |
5564 | |
5565 | return NS_OK; |
5566 | } |
5567 | |
5568 | static bool IsFollowupPartOfMultipart(nsIRequest* aRequest) { |
5569 | nsCOMPtr<nsIMultiPartChannel> multiPartChannel = do_QueryInterface(aRequest); |
5570 | bool firstPart = false; |
5571 | return multiPartChannel && |
5572 | NS_SUCCEEDED(multiPartChannel->GetIsFirstPart(&firstPart))((bool)(__builtin_expect(!!(!NS_FAILED_impl(multiPartChannel-> GetIsFirstPart(&firstPart))), 1))) && |
5573 | !firstPart; |
5574 | } |
5575 | |
5576 | nsresult nsDocShell::Embed(nsIDocumentViewer* aDocumentViewer, |
5577 | WindowGlobalChild* aWindowActor, |
5578 | bool aIsTransientAboutBlank, bool aPersist, |
5579 | nsIRequest* aRequest, nsIURI* aPreviousURI) { |
5580 | // Save the LayoutHistoryState of the previous document, before |
5581 | // setting up new document |
5582 | PersistLayoutHistoryState(); |
5583 | |
5584 | nsresult rv = SetupNewViewer(aDocumentViewer, aWindowActor); |
5585 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 5585); return rv; } } while (false); |
5586 | |
5587 | // XXX What if SetupNewViewer fails? |
5588 | if (mozilla::SessionHistoryInParent() ? !!mLoadingEntry : !!mLSHE) { |
5589 | // Set history.state |
5590 | SetDocCurrentStateObj(mLSHE, |
5591 | mLoadingEntry ? &mLoadingEntry->mInfo : nullptr); |
5592 | } |
5593 | |
5594 | if (mLSHE) { |
5595 | // Restore the editing state, if it's stored in session history. |
5596 | if (mLSHE->HasDetachedEditor()) { |
5597 | ReattachEditorToWindow(mLSHE); |
5598 | } |
5599 | |
5600 | SetHistoryEntryAndUpdateBC(Nothing(), Some<nsISHEntry*>(mLSHE)); |
5601 | } |
5602 | |
5603 | if (!aIsTransientAboutBlank && mozilla::SessionHistoryInParent() && |
5604 | !IsFollowupPartOfMultipart(aRequest)) { |
5605 | bool expired = false; |
5606 | uint32_t cacheKey = 0; |
5607 | nsCOMPtr<nsICacheInfoChannel> cacheChannel = do_QueryInterface(aRequest); |
5608 | if (cacheChannel) { |
5609 | // Check if the page has expired from cache |
5610 | uint32_t expTime = 0; |
5611 | cacheChannel->GetCacheTokenExpirationTime(&expTime); |
5612 | uint32_t now = PRTimeToSeconds(PR_Now()); |
5613 | if (expTime <= now) { |
5614 | expired = true; |
5615 | } |
5616 | |
5617 | // The checks for updating cache key are similar to the old session |
5618 | // history in OnNewURI. Try to update the cache key if |
5619 | // - we should update session history and aren't doing a session |
5620 | // history load. |
5621 | // - we're doing a forced reload. |
5622 | if (((!mLoadingEntry || !mLoadingEntry->mLoadIsFromSessionHistory) && |
5623 | mBrowsingContext->ShouldUpdateSessionHistory(mLoadType)) || |
5624 | IsForceReloadType(mLoadType)) { |
5625 | cacheChannel->GetCacheKey(&cacheKey); |
5626 | } |
5627 | } |
5628 | |
5629 | MOZ_LOG(gSHLog, LogLevel::Debug, ("document %p Embed", this))do { const ::mozilla::LogModule* moz_real_module = gSHLog; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "document %p Embed", this); } } while (0); |
5630 | MoveLoadingToActiveEntry(aPersist, expired, cacheKey, aPreviousURI); |
5631 | } |
5632 | |
5633 | bool updateHistory = true; |
5634 | |
5635 | // Determine if this type of load should update history |
5636 | switch (mLoadType) { |
5637 | case LOAD_NORMAL_REPLACE: |
5638 | case LOAD_REFRESH_REPLACE: |
5639 | case LOAD_STOP_CONTENT_AND_REPLACE: |
5640 | case LOAD_RELOAD_BYPASS_CACHE: |
5641 | case LOAD_RELOAD_BYPASS_PROXY: |
5642 | case LOAD_RELOAD_BYPASS_PROXY_AND_CACHE: |
5643 | case LOAD_REPLACE_BYPASS_CACHE: |
5644 | updateHistory = false; |
5645 | break; |
5646 | default: |
5647 | break; |
5648 | } |
5649 | |
5650 | if (!updateHistory) { |
5651 | SetLayoutHistoryState(nullptr); |
5652 | } |
5653 | |
5654 | return NS_OK; |
5655 | } |
5656 | |
5657 | //***************************************************************************** |
5658 | // nsDocShell::nsIWebProgressListener |
5659 | //***************************************************************************** |
5660 | |
5661 | NS_IMETHODIMPnsresult |
5662 | nsDocShell::OnProgressChange(nsIWebProgress* aProgress, nsIRequest* aRequest, |
5663 | int32_t aCurSelfProgress, int32_t aMaxSelfProgress, |
5664 | int32_t aCurTotalProgress, |
5665 | int32_t aMaxTotalProgress) { |
5666 | return NS_OK; |
5667 | } |
5668 | |
5669 | NS_IMETHODIMPnsresult |
5670 | nsDocShell::OnStateChange(nsIWebProgress* aProgress, nsIRequest* aRequest, |
5671 | uint32_t aStateFlags, nsresult aStatus) { |
5672 | if ((~aStateFlags & (STATE_START | STATE_IS_NETWORK)) == 0) { |
5673 | // Save timing statistics. |
5674 | nsCOMPtr<nsIChannel> channel(do_QueryInterface(aRequest)); |
5675 | nsCOMPtr<nsIURI> uri; |
5676 | channel->GetURI(getter_AddRefs(uri)); |
5677 | nsAutoCString aURI; |
5678 | uri->GetAsciiSpec(aURI); |
5679 | |
5680 | if (this == aProgress) { |
5681 | mozilla::Unused << MaybeInitTiming(); |
5682 | mTiming->NotifyFetchStart(uri, |
5683 | ConvertLoadTypeToNavigationType(mLoadType)); |
5684 | // If we are starting a DocumentChannel, we need to pass the timing |
5685 | // statistics so that should a process switch occur, the starting type can |
5686 | // be passed to the new DocShell running in the other content process. |
5687 | if (RefPtr<DocumentChannel> docChannel = do_QueryObject(aRequest)) { |
5688 | docChannel->SetNavigationTiming(mTiming); |
5689 | } |
5690 | } |
5691 | |
5692 | // Page has begun to load |
5693 | mBusyFlags = (BusyFlags)(BUSY_FLAGS_BUSY | BUSY_FLAGS_BEFORE_PAGE_LOAD); |
5694 | |
5695 | if ((aStateFlags & STATE_RESTORING) == 0) { |
5696 | if (StaticPrefs::browser_sessionstore_platform_collection_AtStartup()) { |
5697 | if (IsForceReloadType(mLoadType)) { |
5698 | if (WindowContext* windowContext = |
5699 | mBrowsingContext->GetCurrentWindowContext()) { |
5700 | SessionStoreChild::From(windowContext->GetWindowGlobalChild()) |
5701 | ->ResetSessionStore(mBrowsingContext, |
5702 | mBrowsingContext->GetSessionStoreEpoch()); |
5703 | } |
5704 | } |
5705 | } |
5706 | } |
5707 | } else if ((~aStateFlags & (STATE_TRANSFERRING | STATE_IS_DOCUMENT)) == 0) { |
5708 | // Page is loading |
5709 | mBusyFlags = (BusyFlags)(BUSY_FLAGS_BUSY | BUSY_FLAGS_PAGE_LOADING); |
5710 | } else if ((aStateFlags & STATE_STOP) && (aStateFlags & STATE_IS_NETWORK)) { |
5711 | // Page has finished loading |
5712 | mBusyFlags = BUSY_FLAGS_NONE; |
5713 | } |
5714 | |
5715 | if ((~aStateFlags & (STATE_IS_DOCUMENT | STATE_STOP)) == 0) { |
5716 | nsCOMPtr<nsIWebProgress> webProgress = |
5717 | do_QueryInterface(GetAsSupports(this)); |
5718 | // Is the document stop notification for this document? |
5719 | if (aProgress == webProgress.get()) { |
5720 | nsCOMPtr<nsIChannel> channel(do_QueryInterface(aRequest)); |
5721 | EndPageLoad(aProgress, channel, aStatus); |
5722 | } |
5723 | } |
5724 | // note that redirect state changes will go through here as well, but it |
5725 | // is better to handle those in OnRedirectStateChange where more |
5726 | // information is available. |
5727 | return NS_OK; |
5728 | } |
5729 | |
5730 | NS_IMETHODIMPnsresult |
5731 | nsDocShell::OnLocationChange(nsIWebProgress* aProgress, nsIRequest* aRequest, |
5732 | nsIURI* aURI, uint32_t aFlags) { |
5733 | // Since we've now changed Documents, notify the BrowsingContext that we've |
5734 | // changed. Ideally we'd just let the BrowsingContext do this when it |
5735 | // changes the current window global, but that happens before this and we |
5736 | // have a lot of tests that depend on the specific ordering of messages. |
5737 | bool isTopLevel = false; |
5738 | if (XRE_IsParentProcess() && |
5739 | !(aFlags & nsIWebProgressListener::LOCATION_CHANGE_SAME_DOCUMENT) && |
5740 | NS_SUCCEEDED(aProgress->GetIsTopLevel(&isTopLevel))((bool)(__builtin_expect(!!(!NS_FAILED_impl(aProgress->GetIsTopLevel (&isTopLevel))), 1))) && isTopLevel) { |
5741 | GetBrowsingContext()->Canonical()->UpdateSecurityState(); |
5742 | } |
5743 | return NS_OK; |
5744 | } |
5745 | |
5746 | void nsDocShell::OnRedirectStateChange(nsIChannel* aOldChannel, |
5747 | nsIChannel* aNewChannel, |
5748 | uint32_t aRedirectFlags, |
5749 | uint32_t aStateFlags) { |
5750 | 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" , 5751); MOZ_PretendNoReturn(); } } while (0) |
5751 | "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" , 5751); MOZ_PretendNoReturn(); } } while (0); |
5752 | |
5753 | if (!(aStateFlags & STATE_IS_DOCUMENT)) { |
5754 | return; // not a toplevel document |
5755 | } |
5756 | |
5757 | nsCOMPtr<nsIURI> oldURI, newURI; |
5758 | aOldChannel->GetURI(getter_AddRefs(oldURI)); |
5759 | aNewChannel->GetURI(getter_AddRefs(newURI)); |
5760 | if (!oldURI || !newURI) { |
5761 | return; |
5762 | } |
5763 | |
5764 | // DocumentChannel adds redirect chain to global history in the parent |
5765 | // process. The redirect chain can't be queried from the content process, so |
5766 | // there's no need to update global history here. |
5767 | RefPtr<DocumentChannel> docChannel = do_QueryObject(aOldChannel); |
5768 | if (!docChannel) { |
5769 | // Below a URI visit is saved (see AddURIVisit method doc). |
5770 | // The visit chain looks something like: |
5771 | // ... |
5772 | // Site N - 1 |
5773 | // => Site N |
5774 | // (redirect to =>) Site N + 1 (we are here!) |
5775 | |
5776 | // Get N - 1 and transition type |
5777 | nsCOMPtr<nsIURI> previousURI; |
5778 | uint32_t previousFlags = 0; |
5779 | ExtractLastVisit(aOldChannel, getter_AddRefs(previousURI), &previousFlags); |
5780 | |
5781 | if (aRedirectFlags & nsIChannelEventSink::REDIRECT_INTERNAL || |
5782 | net::ChannelIsPost(aOldChannel)) { |
5783 | // 1. Internal redirects are ignored because they are specific to the |
5784 | // channel implementation. |
5785 | // 2. POSTs are not saved by global history. |
5786 | // |
5787 | // Regardless, we need to propagate the previous visit to the new |
5788 | // channel. |
5789 | SaveLastVisit(aNewChannel, previousURI, previousFlags); |
5790 | } else { |
5791 | // Get the HTTP response code, if available. |
5792 | uint32_t responseStatus = 0; |
5793 | nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aOldChannel); |
5794 | if (httpChannel) { |
5795 | Unused << httpChannel->GetResponseStatus(&responseStatus); |
5796 | } |
5797 | |
5798 | // Add visit N -1 => N |
5799 | AddURIVisit(oldURI, previousURI, previousFlags, responseStatus); |
5800 | |
5801 | // Since N + 1 could be the final destination, we will not save N => N + 1 |
5802 | // here. OnNewURI will do that, so we will cache it. |
5803 | SaveLastVisit(aNewChannel, oldURI, aRedirectFlags); |
5804 | } |
5805 | } |
5806 | |
5807 | if (!(aRedirectFlags & nsIChannelEventSink::REDIRECT_INTERNAL) && |
5808 | mLoadType & (LOAD_CMD_RELOAD | LOAD_CMD_HISTORY)) { |
5809 | mLoadType = LOAD_NORMAL_REPLACE; |
5810 | SetHistoryEntryAndUpdateBC(Some(nullptr), Nothing()); |
5811 | } |
5812 | } |
5813 | |
5814 | NS_IMETHODIMPnsresult |
5815 | nsDocShell::OnStatusChange(nsIWebProgress* aWebProgress, nsIRequest* aRequest, |
5816 | nsresult aStatus, const char16_t* aMessage) { |
5817 | 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" , 5817); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: " "notification excluded in AddProgressListener(...)" ")"); do { *((volatile int*)__null) = 5817; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
5818 | return NS_OK; |
5819 | } |
5820 | |
5821 | NS_IMETHODIMPnsresult |
5822 | nsDocShell::OnSecurityChange(nsIWebProgress* aWebProgress, nsIRequest* aRequest, |
5823 | uint32_t aState) { |
5824 | 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" , 5824); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: " "notification excluded in AddProgressListener(...)" ")"); do { *((volatile int*)__null) = 5824; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
5825 | return NS_OK; |
5826 | } |
5827 | |
5828 | NS_IMETHODIMPnsresult |
5829 | nsDocShell::OnContentBlockingEvent(nsIWebProgress* aWebProgress, |
5830 | nsIRequest* aRequest, uint32_t aEvent) { |
5831 | 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" , 5831); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: " "notification excluded in AddProgressListener(...)" ")"); do { *((volatile int*)__null) = 5831; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
5832 | return NS_OK; |
5833 | } |
5834 | |
5835 | already_AddRefed<nsIURIFixupInfo> nsDocShell::KeywordToURI( |
5836 | const nsACString& aKeyword, bool aIsPrivateContext) { |
5837 | nsCOMPtr<nsIURIFixupInfo> info; |
5838 | if (!XRE_IsContentProcess()) { |
5839 | nsCOMPtr<nsIURIFixup> uriFixup = components::URIFixup::Service(); |
5840 | if (uriFixup) { |
5841 | uriFixup->KeywordToURI(aKeyword, aIsPrivateContext, getter_AddRefs(info)); |
5842 | } |
5843 | } |
5844 | return info.forget(); |
5845 | } |
5846 | |
5847 | /* static */ |
5848 | already_AddRefed<nsIURI> nsDocShell::MaybeFixBadCertDomainErrorURI( |
5849 | nsIChannel* aChannel, nsIURI* aUrl) { |
5850 | if (!aChannel) { |
5851 | return nullptr; |
5852 | } |
5853 | |
5854 | nsresult rv = NS_OK; |
5855 | nsAutoCString host; |
5856 | rv = aUrl->GetAsciiHost(host); |
5857 | 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" , 5857)) { |
5858 | return nullptr; |
5859 | } |
5860 | |
5861 | // No point in going further if "www." is included in the hostname |
5862 | // already. That is the only hueristic we're applying in this function. |
5863 | if (StringBeginsWith(host, "www."_ns)) { |
5864 | return nullptr; |
5865 | } |
5866 | |
5867 | // Return if fixup enable pref is turned off. |
5868 | if (!mozilla::StaticPrefs::security_bad_cert_domain_error_url_fix_enabled()) { |
5869 | return nullptr; |
5870 | } |
5871 | |
5872 | // Return if scheme is not HTTPS. |
5873 | if (!SchemeIsHTTPS(aUrl)) { |
5874 | return nullptr; |
5875 | } |
5876 | |
5877 | nsCOMPtr<nsILoadInfo> info = aChannel->LoadInfo(); |
5878 | if (!info) { |
5879 | return nullptr; |
5880 | } |
5881 | |
5882 | // Skip doing the fixup if our channel was redirected, because we |
5883 | // shouldn't be guessing things about the post-redirect URI. |
5884 | if (!info->RedirectChain().IsEmpty()) { |
5885 | return nullptr; |
5886 | } |
5887 | |
5888 | int32_t port = 0; |
5889 | rv = aUrl->GetPort(&port); |
5890 | 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" , 5890)) { |
5891 | return nullptr; |
5892 | } |
5893 | |
5894 | // Don't fix up hosts with ports. |
5895 | if (port != -1) { |
5896 | return nullptr; |
5897 | } |
5898 | |
5899 | // Don't fix up localhost url. |
5900 | if (host == "localhost") { |
5901 | return nullptr; |
5902 | } |
5903 | |
5904 | // Don't fix up hostnames with IP address. |
5905 | if (net_IsValidIPv4Addr(host) || net_IsValidIPv6Addr(host)) { |
5906 | return nullptr; |
5907 | } |
5908 | |
5909 | nsAutoCString userPass; |
5910 | rv = aUrl->GetUserPass(userPass); |
5911 | 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" , 5911)) { |
5912 | return nullptr; |
5913 | } |
5914 | |
5915 | // Security - URLs with user / password info should NOT be modified. |
5916 | if (!userPass.IsEmpty()) { |
5917 | return nullptr; |
5918 | } |
5919 | |
5920 | nsCOMPtr<nsITransportSecurityInfo> tsi; |
5921 | rv = aChannel->GetSecurityInfo(getter_AddRefs(tsi)); |
5922 | 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" , 5922)) { |
5923 | return nullptr; |
5924 | } |
5925 | |
5926 | if (NS_WARN_IF(!tsi)NS_warn_if_impl(!tsi, "!tsi", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 5926)) { |
5927 | return nullptr; |
5928 | } |
5929 | |
5930 | nsCOMPtr<nsIX509Cert> cert; |
5931 | rv = tsi->GetServerCert(getter_AddRefs(cert)); |
5932 | 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" , 5932)) { |
5933 | return nullptr; |
5934 | } |
5935 | |
5936 | nsTArray<uint8_t> certBytes; |
5937 | rv = cert->GetRawDER(certBytes); |
5938 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
5939 | return nullptr; |
5940 | } |
5941 | |
5942 | mozilla::pkix::Input serverCertInput; |
5943 | mozilla::pkix::Result rv1 = |
5944 | serverCertInput.Init(certBytes.Elements(), certBytes.Length()); |
5945 | if (rv1 != mozilla::pkix::Success) { |
5946 | return nullptr; |
5947 | } |
5948 | |
5949 | nsAutoCString newHost("www."_ns); |
5950 | newHost.Append(host); |
5951 | |
5952 | mozilla::pkix::Input newHostInput; |
5953 | rv1 = newHostInput.Init( |
5954 | BitwiseCast<const uint8_t*, const char*>(newHost.BeginReading()), |
5955 | newHost.Length()); |
5956 | if (rv1 != mozilla::pkix::Success) { |
5957 | return nullptr; |
5958 | } |
5959 | |
5960 | // Check if adding a "www." prefix to the request's hostname will |
5961 | // cause the response's certificate to match. |
5962 | rv1 = mozilla::pkix::CheckCertHostname(serverCertInput, newHostInput); |
5963 | if (rv1 != mozilla::pkix::Success) { |
5964 | return nullptr; |
5965 | } |
5966 | |
5967 | nsCOMPtr<nsIURI> newURI; |
5968 | Unused << NS_MutateURI(aUrl).SetHost(newHost).Finalize( |
5969 | getter_AddRefs(newURI)); |
5970 | |
5971 | return newURI.forget(); |
5972 | } |
5973 | |
5974 | /* static */ |
5975 | already_AddRefed<nsIURI> nsDocShell::AttemptURIFixup( |
5976 | nsIChannel* aChannel, nsresult aStatus, |
5977 | const mozilla::Maybe<nsCString>& aOriginalURIString, uint32_t aLoadType, |
5978 | bool aIsTopFrame, bool aAllowKeywordFixup, bool aUsePrivateBrowsing, |
5979 | bool aNotifyKeywordSearchLoading, nsIInputStream** aNewPostData, |
5980 | bool* outWasSchemelessInput) { |
5981 | if (aStatus != NS_ERROR_UNKNOWN_HOST && aStatus != NS_ERROR_NET_RESET && |
5982 | aStatus != NS_ERROR_CONNECTION_REFUSED && |
5983 | aStatus != |
5984 | mozilla::psm::GetXPCOMFromNSSError(SSL_ERROR_BAD_CERT_DOMAIN)) { |
5985 | return nullptr; |
5986 | } |
5987 | |
5988 | if (!(aLoadType == LOAD_NORMAL && aIsTopFrame) && !aAllowKeywordFixup) { |
5989 | return nullptr; |
5990 | } |
5991 | |
5992 | nsCOMPtr<nsIURI> url; |
5993 | nsresult rv = aChannel->GetURI(getter_AddRefs(url)); |
5994 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
5995 | return nullptr; |
5996 | } |
5997 | |
5998 | // |
5999 | // Try and make an alternative URI from the old one |
6000 | // |
6001 | nsCOMPtr<nsIURI> newURI; |
6002 | nsCOMPtr<nsIInputStream> newPostData; |
6003 | |
6004 | nsAutoCString oldSpec; |
6005 | url->GetSpec(oldSpec); |
6006 | |
6007 | // |
6008 | // First try keyword fixup |
6009 | // |
6010 | nsAutoString keywordProviderName, keywordAsSent; |
6011 | if (aStatus == NS_ERROR_UNKNOWN_HOST && aAllowKeywordFixup) { |
6012 | // we should only perform a keyword search under the following |
6013 | // conditions: |
6014 | // (0) Pref keyword.enabled is true |
6015 | // (1) the url scheme is http (or https) |
6016 | // (2) the url does not have a protocol scheme |
6017 | // If we don't enforce such a policy, then we end up doing |
6018 | // keyword searchs on urls we don't intend like imap, file, |
6019 | // mailbox, etc. This could lead to a security problem where we |
6020 | // send data to the keyword server that we shouldn't be. |
6021 | // Someone needs to clean up keywords in general so we can |
6022 | // determine on a per url basis if we want keywords |
6023 | // enabled...this is just a bandaid... |
6024 | nsAutoCString scheme; |
6025 | Unused << url->GetScheme(scheme); |
6026 | if (Preferences::GetBool("keyword.enabled", false) && |
6027 | StringBeginsWith(scheme, "http"_ns)) { |
6028 | bool attemptFixup = false; |
6029 | nsAutoCString host; |
6030 | Unused << url->GetHost(host); |
6031 | if (host.FindChar('.') == kNotFound) { |
6032 | attemptFixup = true; |
6033 | } else { |
6034 | // For domains with dots, we check the public suffix validity. |
6035 | nsCOMPtr<nsIEffectiveTLDService> tldService = |
6036 | do_GetService(NS_EFFECTIVETLDSERVICE_CONTRACTID"@mozilla.org/network/effective-tld-service;1"); |
6037 | if (tldService) { |
6038 | nsAutoCString suffix; |
6039 | attemptFixup = |
6040 | NS_SUCCEEDED(tldService->GetKnownPublicSuffix(url, suffix))((bool)(__builtin_expect(!!(!NS_FAILED_impl(tldService->GetKnownPublicSuffix (url, suffix))), 1))) && |
6041 | suffix.IsEmpty(); |
6042 | } |
6043 | } |
6044 | if (attemptFixup) { |
6045 | nsCOMPtr<nsIURIFixupInfo> info; |
6046 | // only send non-qualified hosts to the keyword server |
6047 | if (aOriginalURIString && !aOriginalURIString->IsEmpty()) { |
6048 | info = KeywordToURI(*aOriginalURIString, aUsePrivateBrowsing); |
6049 | } else { |
6050 | // |
6051 | // If this string was passed through nsStandardURL by |
6052 | // chance, then it may have been converted from UTF-8 to |
6053 | // ACE, which would result in a completely bogus keyword |
6054 | // query. Here we try to recover the original Unicode |
6055 | // value, but this is not 100% correct since the value may |
6056 | // have been normalized per the IDN normalization rules. |
6057 | // |
6058 | // Since we don't have access to the exact original string |
6059 | // that was entered by the user, this will just have to do. |
6060 | bool isACE; |
6061 | nsAutoCString utf8Host; |
6062 | nsCOMPtr<nsIIDNService> idnSrv = |
6063 | do_GetService(NS_IDNSERVICE_CONTRACTID"@mozilla.org/network/idn-service;1"); |
6064 | if (idnSrv && NS_SUCCEEDED(idnSrv->IsACE(host, &isACE))((bool)(__builtin_expect(!!(!NS_FAILED_impl(idnSrv->IsACE( host, &isACE))), 1))) && isACE && |
6065 | NS_SUCCEEDED(idnSrv->ConvertACEtoUTF8(host, utf8Host))((bool)(__builtin_expect(!!(!NS_FAILED_impl(idnSrv->ConvertACEtoUTF8 (host, utf8Host))), 1)))) { |
6066 | info = KeywordToURI(utf8Host, aUsePrivateBrowsing); |
6067 | |
6068 | } else { |
6069 | info = KeywordToURI(host, aUsePrivateBrowsing); |
6070 | } |
6071 | } |
6072 | if (info) { |
6073 | info->GetPreferredURI(getter_AddRefs(newURI)); |
6074 | info->GetWasSchemelessInput(outWasSchemelessInput); |
6075 | if (newURI) { |
6076 | info->GetKeywordAsSent(keywordAsSent); |
6077 | info->GetKeywordProviderName(keywordProviderName); |
6078 | info->GetPostData(getter_AddRefs(newPostData)); |
6079 | } |
6080 | } |
6081 | } |
6082 | } |
6083 | } |
6084 | |
6085 | // |
6086 | // Now try change the address, e.g. turn http://foo into |
6087 | // http://www.foo.com, and if that doesn't work try https with |
6088 | // https://foo and https://www.foo.com. |
6089 | // |
6090 | if (aStatus == NS_ERROR_UNKNOWN_HOST || aStatus == NS_ERROR_NET_RESET) { |
6091 | // Skip fixup for anything except a normal document load |
6092 | // operation on the topframe. |
6093 | bool doCreateAlternate = aLoadType == LOAD_NORMAL && aIsTopFrame; |
6094 | |
6095 | if (doCreateAlternate) { |
6096 | nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo(); |
6097 | nsIPrincipal* principal = loadInfo->TriggeringPrincipal(); |
6098 | // Only do this if our channel was loaded directly by the user from the |
6099 | // URL bar or similar (system principal) and not redirected, because we |
6100 | // shouldn't be guessing things about links from other sites, or a |
6101 | // post-redirect URI. |
6102 | doCreateAlternate = principal && principal->IsSystemPrincipal() && |
6103 | loadInfo->RedirectChain().IsEmpty(); |
6104 | } |
6105 | // Test if keyword lookup produced a new URI or not |
6106 | if (doCreateAlternate && newURI) { |
6107 | bool sameURI = false; |
6108 | url->Equals(newURI, &sameURI); |
6109 | if (!sameURI) { |
6110 | // Keyword lookup made a new URI so no need to try |
6111 | // an alternate one. |
6112 | doCreateAlternate = false; |
6113 | } |
6114 | } |
6115 | if (doCreateAlternate) { |
6116 | newURI = nullptr; |
6117 | newPostData = nullptr; |
6118 | keywordProviderName.Truncate(); |
6119 | keywordAsSent.Truncate(); |
6120 | nsCOMPtr<nsIURIFixup> uriFixup = components::URIFixup::Service(); |
6121 | if (uriFixup) { |
6122 | nsCOMPtr<nsIURIFixupInfo> fixupInfo; |
6123 | uriFixup->GetFixupURIInfo(oldSpec, nsIURIFixup::FIXUP_FLAG_NONE, |
6124 | getter_AddRefs(fixupInfo)); |
6125 | if (fixupInfo) { |
6126 | fixupInfo->GetPreferredURI(getter_AddRefs(newURI)); |
6127 | } |
6128 | } |
6129 | } |
6130 | } else if (aStatus == NS_ERROR_CONNECTION_REFUSED && |
6131 | Preferences::GetBool("browser.fixup.fallback-to-https", false)) { |
6132 | // Try HTTPS, since http didn't work |
6133 | if (SchemeIsHTTP(url)) { |
6134 | int32_t port = 0; |
6135 | url->GetPort(&port); |
6136 | |
6137 | // Fall back to HTTPS only if port is default |
6138 | if (port == -1) { |
6139 | newURI = nullptr; |
6140 | newPostData = nullptr; |
6141 | Unused << NS_MutateURI(url) |
6142 | .SetScheme("https"_ns) |
6143 | .Finalize(getter_AddRefs(newURI)); |
6144 | } |
6145 | } |
6146 | } |
6147 | |
6148 | // If we have a SSL_ERROR_BAD_CERT_DOMAIN error, try prefixing the domain name |
6149 | // with www. to see if we can avoid showing the cert error page. For example, |
6150 | // https://example.com -> https://www.example.com. |
6151 | if (aStatus == |
6152 | mozilla::psm::GetXPCOMFromNSSError(SSL_ERROR_BAD_CERT_DOMAIN)) { |
6153 | newPostData = nullptr; |
6154 | newURI = MaybeFixBadCertDomainErrorURI(aChannel, url); |
6155 | } |
6156 | |
6157 | // Did we make a new URI that is different to the old one? If so |
6158 | // load it. |
6159 | // |
6160 | if (newURI) { |
6161 | // Make sure the new URI is different from the old one, |
6162 | // otherwise there's little point trying to load it again. |
6163 | bool sameURI = false; |
6164 | url->Equals(newURI, &sameURI); |
6165 | if (!sameURI) { |
6166 | if (aNewPostData) { |
6167 | newPostData.forget(aNewPostData); |
6168 | } |
6169 | if (aNotifyKeywordSearchLoading) { |
6170 | // This notification is meant for Firefox Health Report so it |
6171 | // can increment counts from the search engine |
6172 | MaybeNotifyKeywordSearchLoading(keywordProviderName, keywordAsSent); |
6173 | } |
6174 | return newURI.forget(); |
6175 | } |
6176 | } |
6177 | |
6178 | return nullptr; |
6179 | } |
6180 | |
6181 | nsresult nsDocShell::FilterStatusForErrorPage( |
6182 | nsresult aStatus, nsIChannel* aChannel, uint32_t aLoadType, |
6183 | bool aIsTopFrame, bool aUseErrorPages, bool aIsInitialDocument, |
6184 | bool* aSkippedUnknownProtocolNavigation) { |
6185 | // Errors to be shown only on top-level frames |
6186 | if ((aStatus == NS_ERROR_UNKNOWN_HOST || |
6187 | aStatus == NS_ERROR_CONNECTION_REFUSED || |
6188 | aStatus == NS_ERROR_UNKNOWN_PROXY_HOST || |
6189 | aStatus == NS_ERROR_PROXY_CONNECTION_REFUSED || |
6190 | aStatus == NS_ERROR_PROXY_FORBIDDEN || |
6191 | aStatus == NS_ERROR_PROXY_NOT_IMPLEMENTED || |
6192 | aStatus == NS_ERROR_PROXY_AUTHENTICATION_FAILED || |
6193 | aStatus == NS_ERROR_PROXY_TOO_MANY_REQUESTS || |
6194 | aStatus == NS_ERROR_MALFORMED_URI || |
6195 | aStatus == NS_ERROR_BLOCKED_BY_POLICY || |
6196 | aStatus == NS_ERROR_DOM_COOP_FAILED || |
6197 | aStatus == NS_ERROR_DOM_COEP_FAILED) && |
6198 | (aIsTopFrame || aUseErrorPages)) { |
6199 | return aStatus; |
6200 | } |
6201 | |
6202 | if (aStatus == NS_ERROR_NET_TIMEOUT || |
6203 | aStatus == NS_ERROR_NET_TIMEOUT_EXTERNAL || |
6204 | aStatus == NS_ERROR_PROXY_GATEWAY_TIMEOUT || |
6205 | aStatus == NS_ERROR_REDIRECT_LOOP || |
6206 | aStatus == NS_ERROR_UNKNOWN_SOCKET_TYPE || |
6207 | aStatus == NS_ERROR_NET_INTERRUPT || aStatus == NS_ERROR_NET_RESET || |
6208 | aStatus == NS_ERROR_PROXY_BAD_GATEWAY || aStatus == NS_ERROR_OFFLINE || |
6209 | aStatus == NS_ERROR_MALWARE_URI || aStatus == NS_ERROR_PHISHING_URI || |
6210 | aStatus == NS_ERROR_UNWANTED_URI || aStatus == NS_ERROR_HARMFUL_URI || |
6211 | aStatus == NS_ERROR_UNSAFE_CONTENT_TYPE || |
6212 | aStatus == NS_ERROR_INTERCEPTION_FAILED || |
6213 | aStatus == NS_ERROR_NET_INADEQUATE_SECURITY || |
6214 | aStatus == NS_ERROR_NET_HTTP2_SENT_GOAWAY || |
6215 | aStatus == NS_ERROR_NET_HTTP3_PROTOCOL_ERROR || |
6216 | aStatus == NS_ERROR_DOM_BAD_URI || aStatus == NS_ERROR_FILE_NOT_FOUND || |
6217 | aStatus == NS_ERROR_FILE_ACCESS_DENIED || |
6218 | aStatus == NS_ERROR_CORRUPTED_CONTENT || |
6219 | aStatus == NS_ERROR_INVALID_CONTENT_ENCODING || |
6220 | NS_ERROR_GET_MODULE(aStatus) == NS_ERROR_MODULE_SECURITY21) { |
6221 | // Errors to be shown for any frame |
6222 | return aStatus; |
6223 | } |
6224 | |
6225 | if (aStatus == NS_ERROR_UNKNOWN_PROTOCOL) { |
6226 | // For unknown protocols we only display an error if the load is triggered |
6227 | // by the browser itself, or we're replacing the initial document (and |
6228 | // nothing else). Showing the error for page-triggered navigations causes |
6229 | // annoying behavior for users, see bug 1528305. |
6230 | // |
6231 | // We could, maybe, try to detect if this is in response to some user |
6232 | // interaction (like clicking a link, or something else) and maybe show |
6233 | // the error page in that case. But this allows for ctrl+clicking and such |
6234 | // to see the error page. |
6235 | nsCOMPtr<nsILoadInfo> info = aChannel->LoadInfo(); |
6236 | if (!info->TriggeringPrincipal()->IsSystemPrincipal() && |
6237 | StaticPrefs::dom_no_unknown_protocol_error_enabled() && |
6238 | !aIsInitialDocument) { |
6239 | if (aSkippedUnknownProtocolNavigation) { |
6240 | *aSkippedUnknownProtocolNavigation = true; |
6241 | } |
6242 | return NS_OK; |
6243 | } |
6244 | return aStatus; |
6245 | } |
6246 | |
6247 | if (aStatus == NS_ERROR_DOCUMENT_NOT_CACHED) { |
6248 | // Non-caching channels will simply return NS_ERROR_OFFLINE. |
6249 | // Caching channels would have to look at their flags to work |
6250 | // out which error to return. Or we can fix up the error here. |
6251 | if (!(aLoadType & LOAD_CMD_HISTORY)) { |
6252 | return NS_ERROR_OFFLINE; |
6253 | } |
6254 | return aStatus; |
6255 | } |
6256 | |
6257 | return NS_OK; |
6258 | } |
6259 | |
6260 | nsresult nsDocShell::EndPageLoad(nsIWebProgress* aProgress, |
6261 | nsIChannel* aChannel, nsresult aStatus) { |
6262 | 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) |
6263 | ("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) |
6264 | 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); |
6265 | if (!aChannel) { |
6266 | return NS_ERROR_NULL_POINTER; |
6267 | } |
6268 | |
6269 | // Make sure to discard the initial client if we never created the initial |
6270 | // about:blank document. Do this before possibly returning from the method |
6271 | // due to an error. |
6272 | mInitialClientSource.reset(); |
6273 | |
6274 | nsCOMPtr<nsIConsoleReportCollector> reporter = do_QueryInterface(aChannel); |
6275 | if (reporter) { |
6276 | nsCOMPtr<nsILoadGroup> loadGroup; |
6277 | aChannel->GetLoadGroup(getter_AddRefs(loadGroup)); |
6278 | if (loadGroup) { |
6279 | reporter->FlushConsoleReports(loadGroup); |
6280 | } else { |
6281 | reporter->FlushConsoleReports(GetDocument()); |
6282 | } |
6283 | } |
6284 | |
6285 | nsCOMPtr<nsIURI> url; |
6286 | nsresult rv = aChannel->GetURI(getter_AddRefs(url)); |
6287 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
6288 | return rv; |
6289 | } |
6290 | |
6291 | nsCOMPtr<nsITimedChannel> timingChannel = do_QueryInterface(aChannel); |
6292 | if (timingChannel) { |
6293 | TimeStamp channelCreationTime; |
6294 | rv = timingChannel->GetChannelCreation(&channelCreationTime); |
6295 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && !channelCreationTime.IsNull()) { |
6296 | Telemetry::AccumulateTimeDelta(Telemetry::TOTAL_CONTENT_PAGE_LOAD_TIME, |
6297 | channelCreationTime); |
6298 | } |
6299 | } |
6300 | |
6301 | // Timing is picked up by the window, we don't need it anymore |
6302 | mTiming = nullptr; |
6303 | |
6304 | // clean up reload state for meta charset |
6305 | if (eCharsetReloadRequested == mCharsetReloadState) { |
6306 | mCharsetReloadState = eCharsetReloadStopOrigional; |
6307 | } else { |
6308 | mCharsetReloadState = eCharsetReloadInit; |
6309 | } |
6310 | |
6311 | // Save a pointer to the currently-loading history entry. |
6312 | // nsDocShell::EndPageLoad will clear mLSHE, but we may need this history |
6313 | // entry further down in this method. |
6314 | nsCOMPtr<nsISHEntry> loadingSHE = mLSHE; |
6315 | mozilla::Unused << loadingSHE; // XXX: Not sure if we need this anymore |
6316 | |
6317 | // |
6318 | // one of many safeguards that prevent death and destruction if |
6319 | // someone is so very very rude as to bring this window down |
6320 | // during this load handler. |
6321 | // |
6322 | nsCOMPtr<nsIDocShell> kungFuDeathGrip(this); |
6323 | |
6324 | // Notify the DocumentViewer that the Document has finished loading. This |
6325 | // will cause any OnLoad(...) and PopState(...) handlers to fire. |
6326 | if (!mEODForCurrentDocument && mDocumentViewer) { |
6327 | mIsExecutingOnLoadHandler = true; |
6328 | nsCOMPtr<nsIDocumentViewer> viewer = mDocumentViewer; |
6329 | viewer->LoadComplete(aStatus); |
6330 | mIsExecutingOnLoadHandler = false; |
6331 | |
6332 | mEODForCurrentDocument = true; |
6333 | } |
6334 | /* Check if the httpChannel has any cache-control related response headers, |
6335 | * like no-store, no-cache. If so, update SHEntry so that |
6336 | * when a user goes back/forward to this page, we appropriately do |
6337 | * form value restoration or load from server. |
6338 | */ |
6339 | nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(aChannel)); |
6340 | if (!httpChannel) { |
6341 | // HttpChannel could be hiding underneath a Multipart channel. |
6342 | GetHttpChannel(aChannel, getter_AddRefs(httpChannel)); |
6343 | } |
6344 | |
6345 | if (httpChannel) { |
6346 | // figure out if SH should be saving layout state. |
6347 | bool discardLayoutState = ShouldDiscardLayoutState(httpChannel); |
6348 | if (mLSHE && discardLayoutState && (mLoadType & LOAD_CMD_NORMAL) && |
6349 | (mLoadType != LOAD_BYPASS_HISTORY) && (mLoadType != LOAD_ERROR_PAGE)) { |
6350 | mLSHE->SetSaveLayoutStateFlag(false); |
6351 | } |
6352 | } |
6353 | |
6354 | // Clear mLSHE after calling the onLoadHandlers. This way, if the |
6355 | // onLoadHandler tries to load something different in |
6356 | // itself or one of its children, we can deal with it appropriately. |
6357 | if (mLSHE) { |
6358 | mLSHE->SetLoadType(LOAD_HISTORY); |
6359 | |
6360 | // Clear the mLSHE reference to indicate document loading is done one |
6361 | // way or another. |
6362 | SetHistoryEntryAndUpdateBC(Some(nullptr), Nothing()); |
6363 | } |
6364 | mActiveEntryIsLoadingFromSessionHistory = false; |
6365 | |
6366 | // if there's a refresh header in the channel, this method |
6367 | // will set it up for us. |
6368 | if (mBrowsingContext->IsActive() || !mDisableMetaRefreshWhenInactive) |
6369 | RefreshURIFromQueue(); |
6370 | |
6371 | // Test whether this is the top frame or a subframe |
6372 | bool isTopFrame = mBrowsingContext->IsTop(); |
6373 | |
6374 | bool hadErrorStatus = false; |
6375 | // If status code indicates an error it means that DocumentChannel already |
6376 | // tried to fixup the uri and failed. Throw an error dialog box here. |
6377 | if (NS_FAILED(aStatus)((bool)(__builtin_expect(!!(NS_FAILED_impl(aStatus)), 0)))) { |
6378 | // If we got CONTENT_BLOCKED from EndPageLoad, then we need to fire |
6379 | // the error event to our embedder, since tests are relying on this. |
6380 | // The error event is usually fired by the caller of InternalLoad, but |
6381 | // this particular error can happen asynchronously. |
6382 | // Bug 1629201 is filed for having much clearer decision making around |
6383 | // which cases need error events. |
6384 | bool fireFrameErrorEvent = (aStatus == NS_ERROR_CONTENT_BLOCKED_SHOW_ALT || |
6385 | aStatus == NS_ERROR_CONTENT_BLOCKED); |
6386 | UnblockEmbedderLoadEventForFailure(fireFrameErrorEvent); |
6387 | |
6388 | bool isInitialDocument = |
6389 | !GetExtantDocument() || GetExtantDocument()->IsInitialDocument(); |
6390 | bool skippedUnknownProtocolNavigation = false; |
6391 | aStatus = FilterStatusForErrorPage(aStatus, aChannel, mLoadType, isTopFrame, |
6392 | mBrowsingContext->GetUseErrorPages(), |
6393 | isInitialDocument, |
6394 | &skippedUnknownProtocolNavigation); |
6395 | hadErrorStatus = true; |
6396 | if (NS_FAILED(aStatus)((bool)(__builtin_expect(!!(NS_FAILED_impl(aStatus)), 0)))) { |
6397 | if (!mIsBeingDestroyed) { |
6398 | DisplayLoadError(aStatus, url, nullptr, aChannel); |
6399 | } |
6400 | } else if (skippedUnknownProtocolNavigation) { |
6401 | nsTArray<nsString> params; |
6402 | if (NS_FAILED(((bool)(__builtin_expect(!!(NS_FAILED_impl(NS_GetSanitizedURIStringFromURI (url, *params.AppendElement()))), 0))) |
6403 | NS_GetSanitizedURIStringFromURI(url, *params.AppendElement()))((bool)(__builtin_expect(!!(NS_FAILED_impl(NS_GetSanitizedURIStringFromURI (url, *params.AppendElement()))), 0)))) { |
6404 | params.LastElement().AssignLiteral(u"(unknown uri)"); |
6405 | } |
6406 | nsContentUtils::ReportToConsole( |
6407 | nsIScriptError::warningFlag, "DOM"_ns, GetExtantDocument(), |
6408 | nsContentUtils::eDOM_PROPERTIES, "UnknownProtocolNavigationPrevented", |
6409 | params); |
6410 | } |
6411 | } else { |
6412 | // If we have a host |
6413 | nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo(); |
6414 | PredictorLearnRedirect(url, aChannel, loadInfo->GetOriginAttributes()); |
6415 | } |
6416 | |
6417 | if (hadErrorStatus) { |
6418 | // Don't send session store updates if the reason EndPageLoad was called is |
6419 | // because we are process switching. Sometimes the update takes too long and |
6420 | // incorrectly overrides session store data from the following load. |
6421 | return NS_OK; |
6422 | } |
6423 | if (StaticPrefs::browser_sessionstore_platform_collection_AtStartup()) { |
6424 | if (WindowContext* windowContext = |
6425 | mBrowsingContext->GetCurrentWindowContext()) { |
6426 | using Change = SessionStoreChangeListener::Change; |
6427 | |
6428 | // We've finished loading the page and now we want to collect all the |
6429 | // session store state that the page is initialized with. |
6430 | SessionStoreChangeListener::CollectSessionStoreData( |
6431 | windowContext, |
6432 | EnumSet<Change>(Change::Input, Change::Scroll, Change::SessionHistory, |
6433 | Change::WireFrame)); |
6434 | } |
6435 | } |
6436 | |
6437 | return NS_OK; |
6438 | } |
6439 | |
6440 | //***************************************************************************** |
6441 | // nsDocShell: Content Viewer Management |
6442 | //***************************************************************************** |
6443 | |
6444 | nsresult nsDocShell::EnsureDocumentViewer() { |
6445 | if (mDocumentViewer) { |
6446 | return NS_OK; |
6447 | } |
6448 | if (mIsBeingDestroyed) { |
6449 | return NS_ERROR_FAILURE; |
6450 | } |
6451 | |
6452 | nsCOMPtr<nsIContentSecurityPolicy> cspToInheritForAboutBlank; |
6453 | nsCOMPtr<nsIURI> baseURI; |
6454 | nsIPrincipal* principal = GetInheritedPrincipal(false); |
6455 | nsIPrincipal* partitionedPrincipal = GetInheritedPrincipal(false, true); |
6456 | |
6457 | nsCOMPtr<nsIDocShellTreeItem> parentItem; |
6458 | GetInProcessSameTypeParent(getter_AddRefs(parentItem)); |
6459 | if (parentItem) { |
6460 | if (nsCOMPtr<nsPIDOMWindowOuter> domWin = GetWindow()) { |
6461 | nsCOMPtr<Element> parentElement = domWin->GetFrameElementInternal(); |
6462 | if (parentElement) { |
6463 | baseURI = parentElement->GetBaseURI(); |
6464 | cspToInheritForAboutBlank = parentElement->GetCsp(); |
6465 | } |
6466 | } |
6467 | } |
6468 | |
6469 | nsresult rv = CreateAboutBlankDocumentViewer( |
6470 | principal, partitionedPrincipal, cspToInheritForAboutBlank, baseURI, |
6471 | /* aIsInitialDocument */ true); |
6472 | |
6473 | 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" , 6473); return NS_ERROR_UNEXPECTED; } } while (false); |
6474 | |
6475 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) { |
6476 | RefPtr<Document> doc(GetDocument()); |
6477 | 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" , 6479); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc" ") (" "Should have doc if CreateAboutBlankDocumentViewer " "succeeded!" ")"); do { *((volatile int*)__null) = 6479; __attribute__ ((nomerge)) ::abort(); } while (false); } } while (false) |
6478 | "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" , 6479); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc" ") (" "Should have doc if CreateAboutBlankDocumentViewer " "succeeded!" ")"); do { *((volatile int*)__null) = 6479; __attribute__ ((nomerge)) ::abort(); } while (false); } } while (false) |
6479 | "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" , 6479); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc" ") (" "Should have doc if CreateAboutBlankDocumentViewer " "succeeded!" ")"); do { *((volatile int*)__null) = 6479; __attribute__ ((nomerge)) ::abort(); } while (false); } } while (false); |
6480 | 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" , 6480); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc->IsInitialDocument()" ") (" "Document should be initial document" ")"); do { *((volatile int*)__null) = 6480; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
6481 | |
6482 | // Documents created using EnsureDocumentViewer may be transient |
6483 | // placeholders created by framescripts before content has a |
6484 | // chance to load. In some cases, window.open(..., "noopener") |
6485 | // will create such a document and then synchronously tear it |
6486 | // down, firing a "pagehide" event. Doing so violates our |
6487 | // assertions about DocGroups. It's easier to silence the |
6488 | // assertion here than to avoid creating the extra document. |
6489 | doc->IgnoreDocGroupMismatches(); |
6490 | } |
6491 | |
6492 | return rv; |
6493 | } |
6494 | |
6495 | nsresult nsDocShell::CreateAboutBlankDocumentViewer( |
6496 | nsIPrincipal* aPrincipal, nsIPrincipal* aPartitionedPrincipal, |
6497 | nsIContentSecurityPolicy* aCSP, nsIURI* aBaseURI, bool aIsInitialDocument, |
6498 | const Maybe<nsILoadInfo::CrossOriginEmbedderPolicy>& aCOEP, |
6499 | bool aTryToSaveOldPresentation, bool aCheckPermitUnload, |
6500 | WindowGlobalChild* aActor) { |
6501 | RefPtr<Document> blankDoc; |
6502 | nsCOMPtr<nsIDocumentViewer> viewer; |
6503 | nsresult rv = NS_ERROR_FAILURE; |
6504 | |
6505 | 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" , 6505); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aActor->DocumentPrincipal() == aPrincipal" ")"); do { *((volatile int*)__null) = 6505; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); |
6506 | |
6507 | /* mCreatingDocument should never be true at this point. However, it's |
6508 | a theoretical possibility. We want to know about it and make it stop, |
6509 | and this sounds like a job for an assertion. */ |
6510 | 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" , 6511); MOZ_PretendNoReturn(); } } while (0) |
6511 | "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" , 6511); MOZ_PretendNoReturn(); } } while (0); |
6512 | if (mCreatingDocument) { |
6513 | return NS_ERROR_FAILURE; |
6514 | } |
6515 | |
6516 | if (!mBrowsingContext->AncestorsAreCurrent() || |
6517 | mBrowsingContext->IsInBFCache()) { |
6518 | mBrowsingContext->RemoveRootFromBFCacheSync(); |
6519 | return NS_ERROR_NOT_AVAILABLE; |
6520 | } |
6521 | |
6522 | // mDocumentViewer->PermitUnload may release |this| docshell. |
6523 | nsCOMPtr<nsIDocShell> kungFuDeathGrip(this); |
6524 | |
6525 | AutoRestore<bool> creatingDocument(mCreatingDocument); |
6526 | mCreatingDocument = true; |
6527 | |
6528 | if (aPrincipal && !aPrincipal->IsSystemPrincipal() && |
6529 | mItemType != typeChrome) { |
6530 | 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" , 6531); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPrincipal->OriginAttributesRef() == mBrowsingContext->OriginAttributesRef()" ")"); do { *((volatile int*)__null) = 6531; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
6531 | 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" , 6531); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPrincipal->OriginAttributesRef() == mBrowsingContext->OriginAttributesRef()" ")"); do { *((volatile int*)__null) = 6531; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
6532 | } |
6533 | |
6534 | // Make sure timing is created. But first record whether we had it |
6535 | // already, so we don't clobber the timing for an in-progress load. |
6536 | bool hadTiming = mTiming; |
6537 | bool toBeReset = MaybeInitTiming(); |
6538 | if (mDocumentViewer) { |
6539 | if (aCheckPermitUnload) { |
6540 | // We've got a content viewer already. Make sure the user |
6541 | // permits us to discard the current document and replace it |
6542 | // with about:blank. And also ensure we fire the unload events |
6543 | // in the current document. |
6544 | |
6545 | // Unload gets fired first for |
6546 | // document loaded from the session history. |
6547 | mTiming->NotifyBeforeUnload(); |
6548 | |
6549 | bool okToUnload; |
6550 | rv = mDocumentViewer->PermitUnload(&okToUnload); |
6551 | |
6552 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && !okToUnload) { |
6553 | // The user chose not to unload the page, interrupt the load. |
6554 | MaybeResetInitTiming(toBeReset); |
6555 | return NS_ERROR_FAILURE; |
6556 | } |
6557 | if (mTiming) { |
6558 | mTiming->NotifyUnloadAccepted(mCurrentURI); |
6559 | } |
6560 | } |
6561 | |
6562 | mSavingOldViewer = |
6563 | aTryToSaveOldPresentation && |
6564 | CanSavePresentation(LOAD_NORMAL, nullptr, nullptr, |
6565 | /* aReportBFCacheComboTelemetry */ true); |
6566 | |
6567 | // Make sure to blow away our mLoadingURI just in case. No loads |
6568 | // from inside this pagehide. |
6569 | mLoadingURI = nullptr; |
6570 | |
6571 | // Stop any in-progress loading, so that we don't accidentally trigger any |
6572 | // PageShow notifications from Embed() interrupting our loading below. |
6573 | Stop(); |
6574 | |
6575 | // Notify the current document that it is about to be unloaded!! |
6576 | // |
6577 | // It is important to fire the unload() notification *before* any state |
6578 | // is changed within the DocShell - otherwise, javascript will get the |
6579 | // wrong information :-( |
6580 | // |
6581 | (void)FirePageHideNotification(!mSavingOldViewer); |
6582 | // pagehide notification might destroy this docshell. |
6583 | if (mIsBeingDestroyed) { |
6584 | return NS_ERROR_DOCSHELL_DYING; |
6585 | } |
6586 | } |
6587 | |
6588 | // Now make sure we don't think we're in the middle of firing unload after |
6589 | // this point. This will make us fire unload when the about:blank document |
6590 | // unloads... but that's ok, more or less. Would be nice if it fired load |
6591 | // too, of course. |
6592 | mFiredUnloadEvent = false; |
6593 | |
6594 | nsCOMPtr<nsIDocumentLoaderFactory> docFactory = |
6595 | nsContentUtils::FindInternalDocumentViewer("text/html"_ns); |
6596 | |
6597 | if (docFactory) { |
6598 | nsCOMPtr<nsIPrincipal> principal, partitionedPrincipal; |
6599 | const uint32_t sandboxFlags = |
6600 | mBrowsingContext->GetHasLoadedNonInitialDocument() |
6601 | ? mBrowsingContext->GetSandboxFlags() |
6602 | : mBrowsingContext->GetInitialSandboxFlags(); |
6603 | // If we're sandboxed, then create a new null principal. We skip |
6604 | // this if we're being created from WindowGlobalChild, since in |
6605 | // that case we already have a null principal if required. |
6606 | // We can't compare againt the BrowsingContext sandbox flag, since |
6607 | // the value was taken when the load initiated and may have since |
6608 | // changed. |
6609 | if ((sandboxFlags & SANDBOXED_ORIGIN) && !aActor) { |
6610 | if (aPrincipal) { |
6611 | principal = NullPrincipal::CreateWithInheritedAttributes(aPrincipal); |
6612 | } else { |
6613 | principal = NullPrincipal::Create(GetOriginAttributes()); |
6614 | } |
6615 | partitionedPrincipal = principal; |
6616 | } else { |
6617 | principal = aPrincipal; |
6618 | partitionedPrincipal = aPartitionedPrincipal; |
6619 | } |
6620 | |
6621 | // We cannot get the foreign partitioned prinicpal for the initial |
6622 | // about:blank page. So, we change to check if we need to use the |
6623 | // partitioned principal for the service worker here. |
6624 | MaybeCreateInitialClientSource( |
6625 | StoragePrincipalHelper::ShouldUsePartitionPrincipalForServiceWorker( |
6626 | this) |
6627 | ? partitionedPrincipal |
6628 | : principal); |
6629 | |
6630 | // generate (about:blank) document to load |
6631 | blankDoc = nsContentDLF::CreateBlankDocument(mLoadGroup, principal, |
6632 | partitionedPrincipal, this); |
6633 | if (blankDoc) { |
6634 | // Hack: manually set the CSP for the new document |
6635 | // Please create an actual copy of the CSP (do not share the same |
6636 | // reference) otherwise appending a new policy within the new |
6637 | // document will be incorrectly propagated to the opening doc. |
6638 | if (aCSP) { |
6639 | RefPtr<nsCSPContext> cspToInherit = new nsCSPContext(); |
6640 | cspToInherit->InitFromOther(static_cast<nsCSPContext*>(aCSP)); |
6641 | blankDoc->SetCsp(cspToInherit); |
6642 | } |
6643 | |
6644 | blankDoc->SetIsInitialDocument(aIsInitialDocument); |
6645 | |
6646 | blankDoc->SetEmbedderPolicy(aCOEP); |
6647 | |
6648 | // Hack: set the base URI manually, since this document never |
6649 | // got Reset() with a channel. |
6650 | blankDoc->SetBaseURI(aBaseURI); |
6651 | |
6652 | // Copy our sandbox flags to the document. These are immutable |
6653 | // after being set here. |
6654 | blankDoc->SetSandboxFlags(sandboxFlags); |
6655 | |
6656 | blankDoc->InitFeaturePolicy(); |
6657 | |
6658 | // create a content viewer for us and the new document |
6659 | docFactory->CreateInstanceForDocument( |
6660 | NS_ISUPPORTS_CAST(nsIDocShell*, this)static_cast<nsISupports*>(static_cast<nsIDocShell*> (this)), blankDoc, "view", |
6661 | getter_AddRefs(viewer)); |
6662 | |
6663 | // hook 'em up |
6664 | if (viewer) { |
6665 | viewer->SetContainer(this); |
6666 | rv = Embed(viewer, aActor, true, false, nullptr, mCurrentURI); |
6667 | 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" , 6667); return rv; } } while (false); |
6668 | |
6669 | SetCurrentURI(blankDoc->GetDocumentURI(), nullptr, |
6670 | /* aFireLocationChange */ true, |
6671 | /* aIsInitialAboutBlank */ true, |
6672 | /* aLocationFlags */ 0); |
6673 | rv = mIsBeingDestroyed ? NS_ERROR_NOT_AVAILABLE : NS_OK; |
6674 | } |
6675 | } |
6676 | } |
6677 | |
6678 | // The transient about:blank viewer doesn't have a session history entry. |
6679 | SetHistoryEntryAndUpdateBC(Nothing(), Some(nullptr)); |
6680 | |
6681 | // Clear out our mTiming like we would in EndPageLoad, if we didn't |
6682 | // have one before entering this function. |
6683 | if (!hadTiming) { |
6684 | mTiming = nullptr; |
6685 | mBlankTiming = true; |
6686 | } |
6687 | |
6688 | return rv; |
6689 | } |
6690 | |
6691 | NS_IMETHODIMPnsresult |
6692 | nsDocShell::CreateAboutBlankDocumentViewer(nsIPrincipal* aPrincipal, |
6693 | nsIPrincipal* aPartitionedPrincipal, |
6694 | nsIContentSecurityPolicy* aCSP) { |
6695 | return CreateAboutBlankDocumentViewer(aPrincipal, aPartitionedPrincipal, aCSP, |
6696 | nullptr, |
6697 | /* aIsInitialDocument */ false); |
6698 | } |
6699 | |
6700 | nsresult nsDocShell::CreateDocumentViewerForActor( |
6701 | WindowGlobalChild* aWindowActor) { |
6702 | 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" , 6702); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aWindowActor" ")"); do { *((volatile int*)__null) = 6702; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
6703 | |
6704 | // FIXME: WindowGlobalChild should provide the PartitionedPrincipal. |
6705 | // FIXME: We may want to support non-initial documents here. |
6706 | nsresult rv = CreateAboutBlankDocumentViewer( |
6707 | aWindowActor->DocumentPrincipal(), aWindowActor->DocumentPrincipal(), |
6708 | /* aCsp */ nullptr, |
6709 | /* aBaseURI */ nullptr, |
6710 | /* aIsInitialDocument */ true, |
6711 | /* aCOEP */ Nothing(), |
6712 | /* aTryToSaveOldPresentation */ true, |
6713 | /* aCheckPermitUnload */ true, aWindowActor); |
6714 | #ifdef DEBUG1 |
6715 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) { |
6716 | RefPtr<Document> doc(GetDocument()); |
6717 | 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" , 6719); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc" ") (" "Should have a document if CreateAboutBlankDocumentViewer succeeded" ")"); do { *((volatile int*)__null) = 6719; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
6718 | 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" , 6719); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc" ") (" "Should have a document if CreateAboutBlankDocumentViewer succeeded" ")"); do { *((volatile int*)__null) = 6719; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
6719 | "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" , 6719); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc" ") (" "Should have a document if CreateAboutBlankDocumentViewer succeeded" ")"); do { *((volatile int*)__null) = 6719; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
6720 | 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" , 6721); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc->GetOwnerGlobal() == aWindowActor->GetWindowGlobal()" ") (" "New document should be in the same global as our actor" ")"); do { *((volatile int*)__null) = 6721; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
6721 | "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" , 6721); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc->GetOwnerGlobal() == aWindowActor->GetWindowGlobal()" ") (" "New document should be in the same global as our actor" ")"); do { *((volatile int*)__null) = 6721; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
6722 | 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" , 6723); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc->IsInitialDocument()" ") (" "New document should be an initial document" ")"); do { *((volatile int*)__null) = 6723; __attribute__((nomerge)) :: abort(); } while (false); } } while (false) |
6723 | "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" , 6723); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc->IsInitialDocument()" ") (" "New document should be an initial document" ")"); do { *((volatile int*)__null) = 6723; __attribute__((nomerge)) :: abort(); } while (false); } } while (false); |
6724 | } |
6725 | #endif |
6726 | |
6727 | return rv; |
6728 | } |
6729 | |
6730 | bool nsDocShell::CanSavePresentation(uint32_t aLoadType, |
6731 | nsIRequest* aNewRequest, |
6732 | Document* aNewDocument, |
6733 | bool aReportBFCacheComboTelemetry) { |
6734 | if (!mOSHE) { |
6735 | return false; // no entry to save into |
6736 | } |
6737 | |
6738 | 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" , 6739); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()" ") (" "mOSHE cannot be non-null with SHIP" ")"); do { *((volatile int*)__null) = 6739; __attribute__((nomerge)) ::abort(); } while (false); } } while (false) |
6739 | "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" , 6739); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()" ") (" "mOSHE cannot be non-null with SHIP" ")"); do { *((volatile int*)__null) = 6739; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
6740 | nsCOMPtr<nsIDocumentViewer> viewer = mOSHE->GetDocumentViewer(); |
6741 | if (viewer) { |
6742 | 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" , 6742); |
6743 | return false; |
6744 | } |
6745 | |
6746 | // Only save presentation for "normal" loads and link loads. Anything else |
6747 | // probably wants to refetch the page, so caching the old presentation |
6748 | // would be incorrect. |
6749 | if (aLoadType != LOAD_NORMAL && aLoadType != LOAD_HISTORY && |
6750 | aLoadType != LOAD_LINK && aLoadType != LOAD_STOP_CONTENT && |
6751 | aLoadType != LOAD_STOP_CONTENT_AND_REPLACE && |
6752 | aLoadType != LOAD_ERROR_PAGE) { |
6753 | return false; |
6754 | } |
6755 | |
6756 | // If the session history entry has the saveLayoutState flag set to false, |
6757 | // then we should not cache the presentation. |
6758 | if (!mOSHE->GetSaveLayoutStateFlag()) { |
6759 | return false; |
6760 | } |
6761 | |
6762 | // If the document is not done loading, don't cache it. |
6763 | if (!mScriptGlobal || mScriptGlobal->IsLoading()) { |
6764 | 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) |
6765 | ("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); |
6766 | return false; |
6767 | } |
6768 | |
6769 | if (mScriptGlobal->WouldReuseInnerWindow(aNewDocument)) { |
6770 | return false; |
6771 | } |
6772 | |
6773 | // Avoid doing the work of saving the presentation state in the case where |
6774 | // the content viewer cache is disabled. |
6775 | if (nsSHistory::GetMaxTotalViewers() == 0) { |
6776 | return false; |
6777 | } |
6778 | |
6779 | // Don't cache the content viewer if we're in a subframe. |
6780 | if (mBrowsingContext->GetParent()) { |
6781 | return false; // this is a subframe load |
6782 | } |
6783 | |
6784 | // If the document does not want its presentation cached, then don't. |
6785 | RefPtr<Document> doc = mScriptGlobal->GetExtantDoc(); |
6786 | |
6787 | uint32_t bfCacheCombo = 0; |
6788 | bool canSavePresentation = |
6789 | doc->CanSavePresentation(aNewRequest, bfCacheCombo, true); |
6790 | 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" , 6790); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bfCacheCombo == 0" ")"); do { *((volatile int*)__null) = 6790; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); |
6791 | if (canSavePresentation && doc->IsTopLevelContentDocument()) { |
6792 | auto* browsingContextGroup = mBrowsingContext->Group(); |
6793 | nsTArray<RefPtr<BrowsingContext>>& topLevelContext = |
6794 | browsingContextGroup->Toplevels(); |
6795 | |
6796 | for (const auto& browsingContext : topLevelContext) { |
6797 | if (browsingContext != mBrowsingContext) { |
6798 | if (StaticPrefs::docshell_shistory_bfcache_require_no_opener()) { |
6799 | canSavePresentation = false; |
6800 | } |
6801 | bfCacheCombo |= BFCacheStatus::NOT_ONLY_TOPLEVEL_IN_BCG; |
6802 | break; |
6803 | } |
6804 | } |
6805 | } |
6806 | |
6807 | if (aReportBFCacheComboTelemetry) { |
6808 | ReportBFCacheComboTelemetry(bfCacheCombo); |
6809 | } |
6810 | return doc && canSavePresentation; |
6811 | } |
6812 | |
6813 | /* static */ |
6814 | void nsDocShell::ReportBFCacheComboTelemetry(uint32_t aCombo) { |
6815 | // There are 11 possible reasons to make a request fails to use BFCache |
6816 | // (see BFCacheStatus in dom/base/Document.h), and we'd like to record |
6817 | // the common combinations for reasons which make requests fail to use |
6818 | // BFCache. These combinations are generated based on some local browsings, |
6819 | // we need to adjust them when necessary. |
6820 | enum BFCacheStatusCombo : uint32_t { |
6821 | BFCACHE_SUCCESS, |
6822 | NOT_ONLY_TOPLEVEL = mozilla::dom::BFCacheStatus::NOT_ONLY_TOPLEVEL_IN_BCG, |
6823 | // If both unload and beforeunload listeners are presented, it'll be |
6824 | // recorded as unload |
6825 | UNLOAD = mozilla::dom::BFCacheStatus::UNLOAD_LISTENER, |
6826 | UNLOAD_REQUEST = mozilla::dom::BFCacheStatus::UNLOAD_LISTENER | |
6827 | mozilla::dom::BFCacheStatus::REQUEST, |
6828 | REQUEST = mozilla::dom::BFCacheStatus::REQUEST, |
6829 | UNLOAD_REQUEST_PEER = mozilla::dom::BFCacheStatus::UNLOAD_LISTENER | |
6830 | mozilla::dom::BFCacheStatus::REQUEST | |
6831 | mozilla::dom::BFCacheStatus::ACTIVE_PEER_CONNECTION, |
6832 | UNLOAD_REQUEST_PEER_MSE = |
6833 | mozilla::dom::BFCacheStatus::UNLOAD_LISTENER | |
6834 | mozilla::dom::BFCacheStatus::REQUEST | |
6835 | mozilla::dom::BFCacheStatus::ACTIVE_PEER_CONNECTION | |
6836 | mozilla::dom::BFCacheStatus::CONTAINS_MSE_CONTENT, |
6837 | UNLOAD_REQUEST_MSE = mozilla::dom::BFCacheStatus::UNLOAD_LISTENER | |
6838 | mozilla::dom::BFCacheStatus::REQUEST | |
6839 | mozilla::dom::BFCacheStatus::CONTAINS_MSE_CONTENT, |
6840 | SUSPENDED_UNLOAD_REQUEST_PEER = |
6841 | mozilla::dom::BFCacheStatus::SUSPENDED | |
6842 | mozilla::dom::BFCacheStatus::UNLOAD_LISTENER | |
6843 | mozilla::dom::BFCacheStatus::REQUEST | |
6844 | mozilla::dom::BFCacheStatus::ACTIVE_PEER_CONNECTION, |
6845 | REMOTE_SUBFRAMES = mozilla::dom::BFCacheStatus::CONTAINS_REMOTE_SUBFRAMES, |
6846 | BEFOREUNLOAD = mozilla::dom::BFCacheStatus::BEFOREUNLOAD_LISTENER, |
6847 | }; |
6848 | |
6849 | // Beforeunload is recorded as a blocker only if it is the only one to block |
6850 | // bfcache. |
6851 | if (aCombo != mozilla::dom::BFCacheStatus::BEFOREUNLOAD_LISTENER) { |
6852 | aCombo &= ~mozilla::dom::BFCacheStatus::BEFOREUNLOAD_LISTENER; |
6853 | } |
6854 | switch (aCombo) { |
6855 | case BFCACHE_SUCCESS: |
6856 | Telemetry::AccumulateCategorical( |
6857 | Telemetry::LABELS_BFCACHE_COMBO::BFCache_Success); |
6858 | break; |
6859 | case NOT_ONLY_TOPLEVEL: |
6860 | if (StaticPrefs::docshell_shistory_bfcache_require_no_opener()) { |
6861 | Telemetry::AccumulateCategorical( |
6862 | Telemetry::LABELS_BFCACHE_COMBO::Other); |
6863 | break; |
6864 | } |
6865 | Telemetry::AccumulateCategorical( |
6866 | Telemetry::LABELS_BFCACHE_COMBO::BFCache_Success); |
6867 | Telemetry::AccumulateCategorical( |
6868 | Telemetry::LABELS_BFCACHE_COMBO::Success_Not_Toplevel); |
6869 | break; |
6870 | case UNLOAD: |
6871 | Telemetry::AccumulateCategorical(Telemetry::LABELS_BFCACHE_COMBO::Unload); |
6872 | break; |
6873 | case BEFOREUNLOAD: |
6874 | Telemetry::AccumulateCategorical( |
6875 | Telemetry::LABELS_BFCACHE_COMBO::Beforeunload); |
6876 | break; |
6877 | case UNLOAD_REQUEST: |
6878 | Telemetry::AccumulateCategorical( |
6879 | Telemetry::LABELS_BFCACHE_COMBO::Unload_Req); |
6880 | break; |
6881 | case REQUEST: |
6882 | Telemetry::AccumulateCategorical(Telemetry::LABELS_BFCACHE_COMBO::Req); |
6883 | break; |
6884 | case UNLOAD_REQUEST_PEER: |
6885 | Telemetry::AccumulateCategorical( |
6886 | Telemetry::LABELS_BFCACHE_COMBO::Unload_Req_Peer); |
6887 | break; |
6888 | case UNLOAD_REQUEST_PEER_MSE: |
6889 | Telemetry::AccumulateCategorical( |
6890 | Telemetry::LABELS_BFCACHE_COMBO::Unload_Req_Peer_MSE); |
6891 | break; |
6892 | case UNLOAD_REQUEST_MSE: |
6893 | Telemetry::AccumulateCategorical( |
6894 | Telemetry::LABELS_BFCACHE_COMBO::Unload_Req_MSE); |
6895 | break; |
6896 | case SUSPENDED_UNLOAD_REQUEST_PEER: |
6897 | Telemetry::AccumulateCategorical( |
6898 | Telemetry::LABELS_BFCACHE_COMBO::SPD_Unload_Req_Peer); |
6899 | break; |
6900 | case REMOTE_SUBFRAMES: |
6901 | Telemetry::AccumulateCategorical( |
6902 | Telemetry::LABELS_BFCACHE_COMBO::Remote_Subframes); |
6903 | break; |
6904 | default: |
6905 | Telemetry::AccumulateCategorical(Telemetry::LABELS_BFCACHE_COMBO::Other); |
6906 | break; |
6907 | } |
6908 | }; |
6909 | |
6910 | void nsDocShell::ReattachEditorToWindow(nsISHEntry* aSHEntry) { |
6911 | 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" , 6911); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()" ")"); do { *((volatile int*)__null) = 6911; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
6912 | 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" , 6912); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mIsBeingDestroyed" ")"); do { *((volatile int*)__null) = 6912; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
6913 | |
6914 | 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" , 6915); MOZ_PretendNoReturn(); } } while (0) |
6915 | "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" , 6915); MOZ_PretendNoReturn(); } } while (0); |
6916 | 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" , 6917); MOZ_PretendNoReturn(); } } while (0) |
6917 | "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" , 6917); MOZ_PretendNoReturn(); } } while (0); |
6918 | |
6919 | if (mEditorData || !aSHEntry) { |
6920 | return; |
6921 | } |
6922 | |
6923 | mEditorData = WrapUnique(aSHEntry->ForgetEditorData()); |
6924 | if (mEditorData) { |
6925 | #ifdef DEBUG1 |
6926 | nsresult rv = |
6927 | #endif |
6928 | mEditorData->ReattachToWindow(this); |
6929 | 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" , 6929); MOZ_PretendNoReturn(); } } while (0); |
6930 | } |
6931 | } |
6932 | |
6933 | void nsDocShell::DetachEditorFromWindow() { |
6934 | if (!mEditorData || mEditorData->WaitingForLoad()) { |
6935 | // If there's nothing to detach, or if the editor data is actually set |
6936 | // up for the _new_ page that's coming in, don't detach. |
6937 | return; |
6938 | } |
6939 | |
6940 | 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" , 6941); MOZ_PretendNoReturn(); } } while (0) |
6941 | "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" , 6941); MOZ_PretendNoReturn(); } } while (0); |
6942 | |
6943 | nsresult res = mEditorData->DetachFromWindow(); |
6944 | 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" , 6944); MOZ_PretendNoReturn(); } } while (0); |
6945 | |
6946 | if (NS_SUCCEEDED(res)((bool)(__builtin_expect(!!(!NS_FAILED_impl(res)), 1)))) { |
6947 | // Make mOSHE hold the owning ref to the editor data. |
6948 | if (mOSHE) { |
6949 | 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" , 6951); 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) = 6951; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
6950 | "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" , 6951); 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) = 6951; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
6951 | "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" , 6951); 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) = 6951; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
6952 | mOSHE->SetEditorData(mEditorData.release()); |
6953 | } else { |
6954 | mEditorData = nullptr; |
6955 | } |
6956 | } |
6957 | |
6958 | #ifdef DEBUG1 |
6959 | { |
6960 | bool isEditable; |
6961 | GetEditable(&isEditable); |
6962 | 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" , 6963); MOZ_PretendNoReturn(); } } while (0) |
6963 | "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" , 6963); MOZ_PretendNoReturn(); } } while (0); |
6964 | } |
6965 | #endif // DEBUG |
6966 | } |
6967 | |
6968 | nsresult nsDocShell::CaptureState() { |
6969 | 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" , 6969); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()" ")"); do { *((volatile int*)__null) = 6969; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
6970 | |
6971 | if (!mOSHE || mOSHE == mLSHE) { |
6972 | // No entry to save into, or we're replacing the existing entry. |
6973 | return NS_ERROR_FAILURE; |
6974 | } |
6975 | |
6976 | if (!mScriptGlobal) { |
6977 | return NS_ERROR_FAILURE; |
6978 | } |
6979 | |
6980 | nsCOMPtr<nsISupports> windowState = mScriptGlobal->SaveWindowState(); |
6981 | 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" , 6981); return NS_ERROR_FAILURE; } } while (false); |
6982 | |
6983 | if (MOZ_UNLIKELY(MOZ_LOG_TEST(gPageCacheLog, LogLevel::Debug))(__builtin_expect(!!((__builtin_expect(!!(mozilla::detail::log_test (gPageCacheLog, LogLevel::Debug)), 0))), 0))) { |
6984 | nsAutoCString spec; |
6985 | nsCOMPtr<nsIURI> uri = mOSHE->GetURI(); |
6986 | if (uri) { |
6987 | uri->GetSpec(spec); |
6988 | } |
6989 | 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) |
6990 | ("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); |
6991 | } |
6992 | |
6993 | mOSHE->SetWindowState(windowState); |
6994 | |
6995 | // Suspend refresh URIs and save off the timer queue |
6996 | mOSHE->SetRefreshURIList(mSavedRefreshURIList); |
6997 | |
6998 | // Capture the current content viewer bounds. |
6999 | if (mDocumentViewer) { |
7000 | nsIntRect bounds; |
7001 | mDocumentViewer->GetBounds(bounds); |
7002 | mOSHE->SetViewerBounds(bounds); |
7003 | } |
7004 | |
7005 | // Capture the docshell hierarchy. |
7006 | mOSHE->ClearChildShells(); |
7007 | |
7008 | uint32_t childCount = mChildList.Length(); |
7009 | for (uint32_t i = 0; i < childCount; ++i) { |
7010 | nsCOMPtr<nsIDocShellTreeItem> childShell = do_QueryInterface(ChildAt(i)); |
7011 | 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" , 7011); MOZ_PretendNoReturn(); } } while (0); |
7012 | |
7013 | mOSHE->AddChildShell(childShell); |
7014 | } |
7015 | |
7016 | return NS_OK; |
7017 | } |
7018 | |
7019 | NS_IMETHODIMPnsresult |
7020 | nsDocShell::RestorePresentationEvent::Run() { |
7021 | 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" , 7021); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()" ")"); do { *((volatile int*)__null) = 7021; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
7022 | |
7023 | if (mDocShell && NS_FAILED(mDocShell->RestoreFromHistory())((bool)(__builtin_expect(!!(NS_FAILED_impl(mDocShell->RestoreFromHistory ())), 0)))) { |
7024 | NS_WARNING("RestoreFromHistory failed")NS_DebugBreak(NS_DEBUG_WARNING, "RestoreFromHistory failed", nullptr , "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 7024); |
7025 | } |
7026 | return NS_OK; |
7027 | } |
7028 | |
7029 | NS_IMETHODIMPnsresult |
7030 | nsDocShell::BeginRestore(nsIDocumentViewer* aDocumentViewer, bool aTop) { |
7031 | 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" , 7031); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()" ")"); do { *((volatile int*)__null) = 7031; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
7032 | |
7033 | nsresult rv; |
7034 | if (!aDocumentViewer) { |
7035 | rv = EnsureDocumentViewer(); |
7036 | 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" , 7036); return rv; } } while (false); |
7037 | |
7038 | aDocumentViewer = mDocumentViewer; |
7039 | } |
7040 | |
7041 | // Dispatch events for restoring the presentation. We try to simulate |
7042 | // the progress notifications loading the document would cause, so we add |
7043 | // the document's channel to the loadgroup to initiate stateChange |
7044 | // notifications. |
7045 | |
7046 | RefPtr<Document> doc = aDocumentViewer->GetDocument(); |
7047 | if (doc) { |
7048 | nsIChannel* channel = doc->GetChannel(); |
7049 | if (channel) { |
7050 | mEODForCurrentDocument = false; |
7051 | mIsRestoringDocument = true; |
7052 | mLoadGroup->AddRequest(channel, nullptr); |
7053 | mIsRestoringDocument = false; |
7054 | } |
7055 | } |
7056 | |
7057 | if (!aTop) { |
7058 | // This point corresponds to us having gotten OnStartRequest or |
7059 | // STATE_START, so do the same thing that CreateDocumentViewer does at |
7060 | // this point to ensure that unload/pagehide events for this document |
7061 | // will fire when it's unloaded again. |
7062 | mFiredUnloadEvent = false; |
7063 | |
7064 | // For non-top frames, there is no notion of making sure that the |
7065 | // previous document is in the domwindow when STATE_START notifications |
7066 | // happen. We can just call BeginRestore for all of the child shells |
7067 | // now. |
7068 | rv = BeginRestoreChildren(); |
7069 | 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" , 7069); return rv; } } while (false); |
7070 | } |
7071 | |
7072 | return NS_OK; |
7073 | } |
7074 | |
7075 | nsresult nsDocShell::BeginRestoreChildren() { |
7076 | 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" , 7076); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()" ")"); do { *((volatile int*)__null) = 7076; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
7077 | |
7078 | for (auto* childDocLoader : mChildList.ForwardRange()) { |
7079 | nsCOMPtr<nsIDocShell> child = do_QueryObject(childDocLoader); |
7080 | if (child) { |
7081 | nsresult rv = child->BeginRestore(nullptr, false); |
7082 | 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" , 7082); return rv; } } while (false); |
7083 | } |
7084 | } |
7085 | return NS_OK; |
7086 | } |
7087 | |
7088 | NS_IMETHODIMPnsresult |
7089 | nsDocShell::FinishRestore() { |
7090 | 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" , 7090); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()" ")"); do { *((volatile int*)__null) = 7090; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
7091 | |
7092 | // First we call finishRestore() on our children. In the simulated load, |
7093 | // all of the child frames finish loading before the main document. |
7094 | |
7095 | for (auto* childDocLoader : mChildList.ForwardRange()) { |
7096 | nsCOMPtr<nsIDocShell> child = do_QueryObject(childDocLoader); |
7097 | if (child) { |
7098 | child->FinishRestore(); |
7099 | } |
7100 | } |
7101 | |
7102 | if (mOSHE && mOSHE->HasDetachedEditor()) { |
7103 | ReattachEditorToWindow(mOSHE); |
7104 | } |
7105 | |
7106 | RefPtr<Document> doc = GetDocument(); |
7107 | if (doc) { |
7108 | // Finally, we remove the request from the loadgroup. This will |
7109 | // cause onStateChange(STATE_STOP) to fire, which will fire the |
7110 | // pageshow event to the chrome. |
7111 | |
7112 | nsIChannel* channel = doc->GetChannel(); |
7113 | if (channel) { |
7114 | mIsRestoringDocument = true; |
7115 | mLoadGroup->RemoveRequest(channel, nullptr, NS_OK); |
7116 | mIsRestoringDocument = false; |
7117 | } |
7118 | } |
7119 | |
7120 | return NS_OK; |
7121 | } |
7122 | |
7123 | NS_IMETHODIMPnsresult |
7124 | nsDocShell::GetRestoringDocument(bool* aRestoring) { |
7125 | *aRestoring = mIsRestoringDocument; |
7126 | return NS_OK; |
7127 | } |
7128 | |
7129 | nsresult nsDocShell::RestorePresentation(nsISHEntry* aSHEntry, |
7130 | bool* aRestoring) { |
7131 | 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" , 7131); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()" ")"); do { *((volatile int*)__null) = 7131; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
7132 | 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" , 7132); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mIsBeingDestroyed" ")"); do { *((volatile int*)__null) = 7132; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
7133 | |
7134 | 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" , 7135); MOZ_PretendNoReturn(); } } while (0) |
7135 | "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" , 7135); MOZ_PretendNoReturn(); } } while (0); |
7136 | |
7137 | nsCOMPtr<nsIDocumentViewer> viewer = aSHEntry->GetDocumentViewer(); |
7138 | |
7139 | nsAutoCString spec; |
7140 | if (MOZ_UNLIKELY(MOZ_LOG_TEST(gPageCacheLog, LogLevel::Debug))(__builtin_expect(!!((__builtin_expect(!!(mozilla::detail::log_test (gPageCacheLog, LogLevel::Debug)), 0))), 0))) { |
7141 | nsCOMPtr<nsIURI> uri = aSHEntry->GetURI(); |
7142 | if (uri) { |
7143 | uri->GetSpec(spec); |
7144 | } |
7145 | } |
7146 | |
7147 | *aRestoring = false; |
7148 | |
7149 | if (!viewer) { |
7150 | 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) |
7151 | ("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); |
7152 | return NS_OK; |
7153 | } |
7154 | |
7155 | // We need to make sure the content viewer's container is this docshell. |
7156 | // In subframe navigation, it's possible for the docshell that the |
7157 | // content viewer was originally loaded into to be replaced with a |
7158 | // different one. We don't currently support restoring the presentation |
7159 | // in that case. |
7160 | |
7161 | nsCOMPtr<nsIDocShell> container; |
7162 | viewer->GetContainer(getter_AddRefs(container)); |
7163 | if (!::SameCOMIdentity(container, GetAsSupports(this))) { |
7164 | 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) |
7165 | ("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); |
7166 | aSHEntry->SetDocumentViewer(nullptr); |
7167 | return NS_ERROR_FAILURE; |
7168 | } |
7169 | |
7170 | 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" , 7170); MOZ_PretendNoReturn(); } } while (0); |
7171 | |
7172 | 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) |
7173 | ("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); |
7174 | |
7175 | SetHistoryEntryAndUpdateBC(Some(aSHEntry), Nothing()); |
7176 | |
7177 | // Post an event that will remove the request after we've returned |
7178 | // to the event loop. This mimics the way it is called by nsIChannel |
7179 | // implementations. |
7180 | |
7181 | // Revoke any pending restore (just in case). |
7182 | 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" , 7183); MOZ_PretendNoReturn(); } } while (0) |
7183 | "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" , 7183); MOZ_PretendNoReturn(); } } while (0); |
7184 | mRestorePresentationEvent.Revoke(); |
7185 | |
7186 | RefPtr<RestorePresentationEvent> evt = new RestorePresentationEvent(this); |
7187 | nsresult rv = Dispatch(do_AddRef(evt)); |
7188 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) { |
7189 | mRestorePresentationEvent = evt.get(); |
7190 | // The rest of the restore processing will happen on our event |
7191 | // callback. |
7192 | *aRestoring = true; |
7193 | } |
7194 | |
7195 | return rv; |
7196 | } |
7197 | |
7198 | namespace { |
7199 | class MOZ_STACK_CLASS PresentationEventForgetter { |
7200 | public: |
7201 | explicit PresentationEventForgetter( |
7202 | nsRevocableEventPtr<nsDocShell::RestorePresentationEvent>& |
7203 | aRestorePresentationEvent) |
7204 | : mRestorePresentationEvent(aRestorePresentationEvent), |
7205 | mEvent(aRestorePresentationEvent.get()) {} |
7206 | |
7207 | ~PresentationEventForgetter() { Forget(); } |
7208 | |
7209 | void Forget() { |
7210 | if (mRestorePresentationEvent.get() == mEvent) { |
7211 | mRestorePresentationEvent.Forget(); |
7212 | mEvent = nullptr; |
7213 | } |
7214 | } |
7215 | |
7216 | private: |
7217 | nsRevocableEventPtr<nsDocShell::RestorePresentationEvent>& |
7218 | mRestorePresentationEvent; |
7219 | RefPtr<nsDocShell::RestorePresentationEvent> mEvent; |
7220 | }; |
7221 | |
7222 | } // namespace |
7223 | |
7224 | bool nsDocShell::SandboxFlagsImplyCookies(const uint32_t& aSandboxFlags) { |
7225 | return (aSandboxFlags & (SANDBOXED_ORIGIN | SANDBOXED_SCRIPTS)) == 0; |
7226 | } |
7227 | |
7228 | nsresult nsDocShell::RestoreFromHistory() { |
7229 | 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" , 7229); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()" ")"); do { *((volatile int*)__null) = 7229; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
7230 | 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" , 7230); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mRestorePresentationEvent.IsPending()" ")"); do { *((volatile int*)__null) = 7230; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
7231 | PresentationEventForgetter forgetter(mRestorePresentationEvent); |
7232 | |
7233 | // This section of code follows the same ordering as CreateDocumentViewer. |
7234 | if (!mLSHE) { |
7235 | return NS_ERROR_FAILURE; |
7236 | } |
7237 | |
7238 | nsCOMPtr<nsIDocumentViewer> viewer = mLSHE->GetDocumentViewer(); |
7239 | if (!viewer) { |
7240 | return NS_ERROR_FAILURE; |
7241 | } |
7242 | |
7243 | if (mSavingOldViewer) { |
7244 | // We determined that it was safe to cache the document presentation |
7245 | // at the time we initiated the new load. We need to check whether |
7246 | // it's still safe to do so, since there may have been DOM mutations |
7247 | // or new requests initiated. |
7248 | RefPtr<Document> doc = viewer->GetDocument(); |
7249 | nsIRequest* request = nullptr; |
7250 | if (doc) { |
7251 | request = doc->GetChannel(); |
7252 | } |
7253 | mSavingOldViewer = CanSavePresentation( |
7254 | mLoadType, request, doc, /* aReportBFCacheComboTelemetry */ false); |
7255 | } |
7256 | |
7257 | // Protect against mLSHE going away via a load triggered from |
7258 | // pagehide or unload. |
7259 | nsCOMPtr<nsISHEntry> origLSHE = mLSHE; |
7260 | |
7261 | // Make sure to blow away our mLoadingURI just in case. No loads |
7262 | // from inside this pagehide. |
7263 | mLoadingURI = nullptr; |
7264 | |
7265 | // Notify the old content viewer that it's being hidden. |
7266 | FirePageHideNotification(!mSavingOldViewer); |
7267 | // pagehide notification might destroy this docshell. |
7268 | if (mIsBeingDestroyed) { |
7269 | return NS_ERROR_DOCSHELL_DYING; |
7270 | } |
7271 | |
7272 | // If mLSHE was changed as a result of the pagehide event, then |
7273 | // something else was loaded. Don't finish restoring. |
7274 | if (mLSHE != origLSHE) { |
7275 | return NS_OK; |
7276 | } |
7277 | |
7278 | // Add the request to our load group. We do this before swapping out |
7279 | // the content viewers so that consumers of STATE_START can access |
7280 | // the old document. We only deal with the toplevel load at this time -- |
7281 | // to be consistent with normal document loading, subframes cannot start |
7282 | // loading until after data arrives, which is after STATE_START completes. |
7283 | |
7284 | RefPtr<RestorePresentationEvent> currentPresentationRestoration = |
7285 | mRestorePresentationEvent.get(); |
7286 | Stop(); |
7287 | // Make sure we're still restoring the same presentation. |
7288 | // If we aren't, docshell is in process doing another load already. |
7289 | 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" , 7290); return NS_ERROR_UNEXPECTED; } } while (false) |
7290 | 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" , 7290); return NS_ERROR_UNEXPECTED; } } while (false); |
7291 | BeginRestore(viewer, true); |
7292 | 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" , 7293); return NS_ERROR_UNEXPECTED; } } while (false) |
7293 | 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" , 7293); return NS_ERROR_UNEXPECTED; } } while (false); |
7294 | forgetter.Forget(); |
7295 | |
7296 | // Set mFiredUnloadEvent = false so that the unload handler for the |
7297 | // *new* document will fire. |
7298 | mFiredUnloadEvent = false; |
7299 | |
7300 | mURIResultedInDocument = true; |
7301 | RefPtr<ChildSHistory> rootSH = GetRootSessionHistory(); |
7302 | if (rootSH) { |
7303 | mPreviousEntryIndex = rootSH->Index(); |
7304 | rootSH->LegacySHistory()->UpdateIndex(); |
7305 | mLoadedEntryIndex = rootSH->Index(); |
7306 | 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) |
7307 | ("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) |
7308 | 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); |
7309 | } |
7310 | |
7311 | // Rather than call Embed(), we will retrieve the viewer from the session |
7312 | // history entry and swap it in. |
7313 | // XXX can we refactor this so that we can just call Embed()? |
7314 | PersistLayoutHistoryState(); |
7315 | nsresult rv; |
7316 | if (mDocumentViewer) { |
7317 | if (mSavingOldViewer && NS_FAILED(CaptureState())((bool)(__builtin_expect(!!(NS_FAILED_impl(CaptureState())), 0 )))) { |
7318 | if (mOSHE) { |
7319 | mOSHE->SyncPresentationState(); |
7320 | } |
7321 | mSavingOldViewer = false; |
7322 | } |
7323 | } |
7324 | |
7325 | mSavedRefreshURIList = nullptr; |
7326 | |
7327 | // In cases where we use a transient about:blank viewer between loads, |
7328 | // we never show the transient viewer, so _its_ previous viewer is never |
7329 | // unhooked from the view hierarchy. Destroy any such previous viewer now, |
7330 | // before we grab the root view sibling, so that we don't grab a view |
7331 | // that's about to go away. |
7332 | |
7333 | if (mDocumentViewer) { |
7334 | // Make sure to hold a strong ref to previousViewer here while we |
7335 | // drop the reference to it from mDocumentViewer. |
7336 | nsCOMPtr<nsIDocumentViewer> previousViewer = |
7337 | mDocumentViewer->GetPreviousViewer(); |
7338 | if (previousViewer) { |
7339 | mDocumentViewer->SetPreviousViewer(nullptr); |
7340 | previousViewer->Destroy(); |
7341 | } |
7342 | } |
7343 | |
7344 | // Save off the root view's parent and sibling so that we can insert the |
7345 | // new content viewer's root view at the same position. Also save the |
7346 | // bounds of the root view's widget. |
7347 | |
7348 | nsView* rootViewSibling = nullptr; |
7349 | nsView* rootViewParent = nullptr; |
7350 | nsIntRect newBounds(0, 0, 0, 0); |
7351 | |
7352 | PresShell* oldPresShell = GetPresShell(); |
7353 | if (oldPresShell) { |
7354 | nsViewManager* vm = oldPresShell->GetViewManager(); |
7355 | if (vm) { |
7356 | nsView* oldRootView = vm->GetRootView(); |
7357 | |
7358 | if (oldRootView) { |
7359 | rootViewSibling = oldRootView->GetNextSibling(); |
7360 | rootViewParent = oldRootView->GetParent(); |
7361 | |
7362 | mDocumentViewer->GetBounds(newBounds); |
7363 | } |
7364 | } |
7365 | } |
7366 | |
7367 | nsCOMPtr<nsIContent> container; |
7368 | RefPtr<Document> sibling; |
7369 | if (rootViewParent && rootViewParent->GetParent()) { |
7370 | nsIFrame* frame = rootViewParent->GetParent()->GetFrame(); |
7371 | container = frame ? frame->GetContent() : nullptr; |
7372 | } |
7373 | if (rootViewSibling) { |
7374 | nsIFrame* frame = rootViewSibling->GetFrame(); |
7375 | sibling = frame ? frame->PresShell()->GetDocument() : nullptr; |
7376 | } |
7377 | |
7378 | // Transfer ownership to mDocumentViewer. By ensuring that either the |
7379 | // docshell or the session history, but not both, have references to the |
7380 | // content viewer, we prevent the viewer from being torn down after |
7381 | // Destroy() is called. |
7382 | |
7383 | if (mDocumentViewer) { |
7384 | mDocumentViewer->Close(mSavingOldViewer ? mOSHE.get() : nullptr); |
7385 | viewer->SetPreviousViewer(mDocumentViewer); |
7386 | } |
7387 | if (mOSHE && (!mDocumentViewer || !mSavingOldViewer)) { |
7388 | // We don't plan to save a viewer in mOSHE; tell it to drop |
7389 | // any other state it's holding. |
7390 | mOSHE->SyncPresentationState(); |
7391 | } |
7392 | |
7393 | // Order the mDocumentViewer setup just like Embed does. |
7394 | mDocumentViewer = nullptr; |
7395 | |
7396 | // Now that we're about to switch documents, forget all of our children. |
7397 | // Note that we cached them as needed up in CaptureState above. |
7398 | DestroyChildren(); |
7399 | |
7400 | mDocumentViewer.swap(viewer); |
7401 | |
7402 | // Grab all of the related presentation from the SHEntry now. |
7403 | // Clearing the viewer from the SHEntry will clear all of this state. |
7404 | nsCOMPtr<nsISupports> windowState = mLSHE->GetWindowState(); |
7405 | mLSHE->SetWindowState(nullptr); |
7406 | |
7407 | bool sticky = mLSHE->GetSticky(); |
7408 | |
7409 | RefPtr<Document> document = mDocumentViewer->GetDocument(); |
7410 | |
7411 | nsCOMArray<nsIDocShellTreeItem> childShells; |
7412 | int32_t i = 0; |
7413 | nsCOMPtr<nsIDocShellTreeItem> child; |
7414 | while (NS_SUCCEEDED(mLSHE->ChildShellAt(i++, getter_AddRefs(child)))((bool)(__builtin_expect(!!(!NS_FAILED_impl(mLSHE->ChildShellAt (i++, getter_AddRefs(child)))), 1))) && |
7415 | child) { |
7416 | childShells.AppendObject(child); |
7417 | } |
7418 | |
7419 | // get the previous content viewer size |
7420 | nsIntRect oldBounds(0, 0, 0, 0); |
7421 | mLSHE->GetViewerBounds(oldBounds); |
7422 | |
7423 | // Restore the refresh URI list. The refresh timers will be restarted |
7424 | // when EndPageLoad() is called. |
7425 | nsCOMPtr<nsIMutableArray> refreshURIList = mLSHE->GetRefreshURIList(); |
7426 | |
7427 | // Reattach to the window object. |
7428 | mIsRestoringDocument = true; // for MediaDocument::BecomeInteractive |
7429 | rv = mDocumentViewer->Open(windowState, mLSHE); |
7430 | mIsRestoringDocument = false; |
7431 | |
7432 | // Hack to keep nsDocShellEditorData alive across the |
7433 | // SetContentViewer(nullptr) call below. |
7434 | UniquePtr<nsDocShellEditorData> data(mLSHE->ForgetEditorData()); |
7435 | |
7436 | // Now remove it from the cached presentation. |
7437 | mLSHE->SetDocumentViewer(nullptr); |
7438 | mEODForCurrentDocument = false; |
7439 | |
7440 | mLSHE->SetEditorData(data.release()); |
7441 | |
7442 | #ifdef DEBUG1 |
7443 | { |
7444 | nsCOMPtr<nsIMutableArray> refreshURIs = mLSHE->GetRefreshURIList(); |
7445 | nsCOMPtr<nsIDocShellTreeItem> childShell; |
7446 | mLSHE->ChildShellAt(0, getter_AddRefs(childShell)); |
7447 | 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" , 7448); MOZ_PretendNoReturn(); } } while (0) |
7448 | "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" , 7448); MOZ_PretendNoReturn(); } } while (0); |
7449 | } |
7450 | #endif |
7451 | |
7452 | // Restore the sticky state of the viewer. The viewer has set this state |
7453 | // on the history entry in Destroy() just before marking itself non-sticky, |
7454 | // to avoid teardown of the presentation. |
7455 | mDocumentViewer->SetSticky(sticky); |
7456 | |
7457 | 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" , 7457); return rv; } } while (false); |
7458 | |
7459 | // mLSHE is now our currently-loaded document. |
7460 | SetHistoryEntryAndUpdateBC(Nothing(), Some<nsISHEntry*>(mLSHE)); |
7461 | |
7462 | // We aren't going to restore any items from the LayoutHistoryState, |
7463 | // but we don't want them to stay around in case the page is reloaded. |
7464 | SetLayoutHistoryState(nullptr); |
7465 | |
7466 | // This is the end of our Embed() replacement |
7467 | |
7468 | mSavingOldViewer = false; |
7469 | mEODForCurrentDocument = false; |
7470 | |
7471 | if (document) { |
7472 | RefPtr<nsDocShell> parent = GetInProcessParentDocshell(); |
7473 | if (parent) { |
7474 | RefPtr<Document> d = parent->GetDocument(); |
7475 | if (d) { |
7476 | if (d->EventHandlingSuppressed()) { |
7477 | document->SuppressEventHandling(d->EventHandlingSuppressed()); |
7478 | } |
7479 | } |
7480 | } |
7481 | |
7482 | // Use the uri from the mLSHE we had when we entered this function |
7483 | // (which need not match the document's URI if anchors are involved), |
7484 | // since that's the history entry we're loading. Note that if we use |
7485 | // origLSHE we don't have to worry about whether the entry in question |
7486 | // is still mLSHE or whether it's now mOSHE. |
7487 | nsCOMPtr<nsIURI> uri = origLSHE->GetURI(); |
7488 | SetCurrentURI(uri, document->GetChannel(), /* aFireLocationChange */ true, |
7489 | /* aIsInitialAboutBlank */ false, |
7490 | /* aLocationFlags */ 0); |
7491 | } |
7492 | |
7493 | // This is the end of our CreateDocumentViewer() replacement. |
7494 | // Now we simulate a load. First, we restore the state of the javascript |
7495 | // window object. |
7496 | nsCOMPtr<nsPIDOMWindowOuter> privWin = GetWindow(); |
7497 | 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" , 7497); MOZ_PretendNoReturn(); } } while (0); |
7498 | |
7499 | // Now, dispatch a title change event which would happen as the |
7500 | // <head> is parsed. |
7501 | document->NotifyPossibleTitleChange(false); |
7502 | |
7503 | // Now we simulate appending child docshells for subframes. |
7504 | for (i = 0; i < childShells.Count(); ++i) { |
7505 | nsIDocShellTreeItem* childItem = childShells.ObjectAt(i); |
7506 | nsCOMPtr<nsIDocShell> childShell = do_QueryInterface(childItem); |
7507 | |
7508 | // Make sure to not clobber the state of the child. Since AddChild |
7509 | // always clobbers it, save it off first. |
7510 | bool allowRedirects; |
7511 | childShell->GetAllowMetaRedirects(&allowRedirects); |
7512 | |
7513 | bool allowSubframes; |
7514 | childShell->GetAllowSubframes(&allowSubframes); |
7515 | |
7516 | bool allowImages; |
7517 | childShell->GetAllowImages(&allowImages); |
7518 | |
7519 | bool allowMedia = childShell->GetAllowMedia(); |
7520 | |
7521 | bool allowDNSPrefetch; |
7522 | childShell->GetAllowDNSPrefetch(&allowDNSPrefetch); |
7523 | |
7524 | bool allowContentRetargeting = childShell->GetAllowContentRetargeting(); |
7525 | bool allowContentRetargetingOnChildren = |
7526 | childShell->GetAllowContentRetargetingOnChildren(); |
7527 | |
7528 | // this.AddChild(child) calls child.SetDocLoaderParent(this), meaning that |
7529 | // the child inherits our state. Among other things, this means that the |
7530 | // child inherits our mPrivateBrowsingId, which is what we want. |
7531 | AddChild(childItem); |
7532 | |
7533 | childShell->SetAllowMetaRedirects(allowRedirects); |
7534 | childShell->SetAllowSubframes(allowSubframes); |
7535 | childShell->SetAllowImages(allowImages); |
7536 | childShell->SetAllowMedia(allowMedia); |
7537 | childShell->SetAllowDNSPrefetch(allowDNSPrefetch); |
7538 | childShell->SetAllowContentRetargeting(allowContentRetargeting); |
7539 | childShell->SetAllowContentRetargetingOnChildren( |
7540 | allowContentRetargetingOnChildren); |
7541 | |
7542 | rv = childShell->BeginRestore(nullptr, false); |
7543 | 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" , 7543); return rv; } } while (false); |
7544 | } |
7545 | |
7546 | // Make sure to restore the window state after adding the child shells back |
7547 | // to the tree. This is necessary for Thaw() and Resume() to propagate |
7548 | // properly. |
7549 | rv = privWin->RestoreWindowState(windowState); |
7550 | 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" , 7550); return rv; } } while (false); |
7551 | |
7552 | RefPtr<PresShell> presShell = GetPresShell(); |
7553 | |
7554 | // We may be displayed on a different monitor (or in a different |
7555 | // HiDPI mode) than when we got into the history list. So we need |
7556 | // to check if this has happened. See bug 838239. |
7557 | |
7558 | // Because the prescontext normally handles resolution changes via |
7559 | // a runnable (see nsPresContext::UIResolutionChanged), its device |
7560 | // context won't be -immediately- updated as a result of calling |
7561 | // presShell->BackingScaleFactorChanged(). |
7562 | |
7563 | // But we depend on that device context when adjusting the view size |
7564 | // via mDocumentViewer->SetBounds(newBounds) below. So we need to |
7565 | // explicitly tell it to check for changed resolution here. |
7566 | if (presShell) { |
7567 | RefPtr<nsPresContext> pc = presShell->GetPresContext(); |
7568 | if (pc->DeviceContext()->CheckDPIChange()) { |
7569 | presShell->BackingScaleFactorChanged(); |
7570 | } |
7571 | // Recompute zoom and text-zoom and such. |
7572 | pc->RecomputeBrowsingContextDependentData(); |
7573 | } |
7574 | |
7575 | nsViewManager* newVM = presShell ? presShell->GetViewManager() : nullptr; |
7576 | nsView* newRootView = newVM ? newVM->GetRootView() : nullptr; |
7577 | |
7578 | // Insert the new root view at the correct location in the view tree. |
7579 | if (container) { |
7580 | nsSubDocumentFrame* subDocFrame = |
7581 | do_QueryFrame(container->GetPrimaryFrame()); |
7582 | rootViewParent = subDocFrame ? subDocFrame->EnsureInnerView() : nullptr; |
7583 | } else { |
7584 | rootViewParent = nullptr; |
7585 | } |
7586 | if (sibling && sibling->GetPresShell() && |
7587 | sibling->GetPresShell()->GetViewManager()) { |
7588 | rootViewSibling = sibling->GetPresShell()->GetViewManager()->GetRootView(); |
7589 | } else { |
7590 | rootViewSibling = nullptr; |
7591 | } |
7592 | if (rootViewParent && newRootView && |
7593 | newRootView->GetParent() != rootViewParent) { |
7594 | nsViewManager* parentVM = rootViewParent->GetViewManager(); |
7595 | if (parentVM) { |
7596 | // InsertChild(parent, child, sib, true) inserts the child after |
7597 | // sib in content order, which is before sib in view order. BUT |
7598 | // when sib is null it inserts at the end of the the document |
7599 | // order, i.e., first in view order. But when oldRootSibling is |
7600 | // null, the old root as at the end of the view list --- last in |
7601 | // content order --- and we want to call InsertChild(parent, child, |
7602 | // nullptr, false) in that case. |
7603 | parentVM->InsertChild(rootViewParent, newRootView, rootViewSibling, |
7604 | rootViewSibling ? true : false); |
7605 | |
7606 | 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" , 7607); MOZ_PretendNoReturn(); } } while (0) |
7607 | "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" , 7607); MOZ_PretendNoReturn(); } } while (0); |
7608 | } |
7609 | } |
7610 | |
7611 | nsCOMPtr<nsPIDOMWindowInner> privWinInner = privWin->GetCurrentInnerWindow(); |
7612 | |
7613 | // If parent is suspended, increase suspension count. |
7614 | // This can't be done as early as event suppression since this |
7615 | // depends on docshell tree. |
7616 | privWinInner->SyncStateFromParentWindow(); |
7617 | |
7618 | // Now that all of the child docshells have been put into place, we can |
7619 | // restart the timers for the window and all of the child frames. |
7620 | privWinInner->Resume(); |
7621 | |
7622 | // Now that we have found the inner window of the page restored |
7623 | // from the history, we have to make sure that |
7624 | // performance.navigation.type is 2. |
7625 | Performance* performance = privWinInner->GetPerformance(); |
7626 | if (performance) { |
7627 | performance->GetDOMTiming()->NotifyRestoreStart(); |
7628 | } |
7629 | |
7630 | // Restore the refresh URI list. The refresh timers will be restarted |
7631 | // when EndPageLoad() is called. |
7632 | mRefreshURIList = refreshURIList; |
7633 | |
7634 | // Meta-refresh timers have been restarted for this shell, but not |
7635 | // for our children. Walk the child shells and restart their timers. |
7636 | for (auto* childDocLoader : mChildList.ForwardRange()) { |
7637 | nsCOMPtr<nsIDocShell> child = do_QueryObject(childDocLoader); |
7638 | if (child) { |
7639 | child->ResumeRefreshURIs(); |
7640 | } |
7641 | } |
7642 | |
7643 | // Make sure this presentation is the same size as the previous |
7644 | // presentation. If this is not the same size we showed it at last time, |
7645 | // then we need to resize the widget. |
7646 | |
7647 | // XXXbryner This interacts poorly with Firefox's infobar. If the old |
7648 | // presentation had the infobar visible, then we will resize the new |
7649 | // presentation to that smaller size. However, firing the locationchanged |
7650 | // event will hide the infobar, which will immediately resize the window |
7651 | // back to the larger size. A future optimization might be to restore |
7652 | // the presentation at the "wrong" size, then fire the locationchanged |
7653 | // event and check whether the docshell's new size is the same as the |
7654 | // cached viewer size (skipping the resize if they are equal). |
7655 | |
7656 | if (newRootView) { |
7657 | if (!newBounds.IsEmpty() && !newBounds.IsEqualEdges(oldBounds)) { |
7658 | 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) |
7659 | ("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) |
7660 | 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); |
7661 | mDocumentViewer->SetBounds(newBounds); |
7662 | } else { |
7663 | nsIScrollableFrame* rootScrollFrame = |
7664 | presShell->GetRootScrollFrameAsScrollable(); |
7665 | if (rootScrollFrame) { |
7666 | rootScrollFrame->PostScrolledAreaEventForCurrentArea(); |
7667 | } |
7668 | } |
7669 | } |
7670 | |
7671 | // The FinishRestore call below can kill these, null them out so we don't |
7672 | // have invalid pointer lying around. |
7673 | newRootView = rootViewSibling = rootViewParent = nullptr; |
7674 | newVM = nullptr; |
7675 | |
7676 | // If the IsUnderHiddenEmbedderElement() state has been changed, we need to |
7677 | // update it. |
7678 | if (oldPresShell && presShell && |
7679 | presShell->IsUnderHiddenEmbedderElement() != |
7680 | oldPresShell->IsUnderHiddenEmbedderElement()) { |
7681 | presShell->SetIsUnderHiddenEmbedderElement( |
7682 | oldPresShell->IsUnderHiddenEmbedderElement()); |
7683 | } |
7684 | |
7685 | // Simulate the completion of the load. |
7686 | nsDocShell::FinishRestore(); |
7687 | |
7688 | // Restart plugins, and paint the content. |
7689 | if (presShell) { |
7690 | presShell->Thaw(); |
7691 | } |
7692 | |
7693 | return privWin->FireDelayedDOMEvents(true); |
7694 | } |
7695 | |
7696 | nsresult nsDocShell::CreateDocumentViewer(const nsACString& aContentType, |
7697 | nsIRequest* aRequest, |
7698 | nsIStreamListener** aContentHandler) { |
7699 | if (DocGroup::TryToLoadIframesInBackground()) { |
7700 | ResetToFirstLoad(); |
7701 | } |
7702 | |
7703 | *aContentHandler = nullptr; |
7704 | |
7705 | if (!mTreeOwner || mIsBeingDestroyed) { |
7706 | // If we don't have a tree owner, then we're in the process of being |
7707 | // destroyed. Rather than continue trying to load something, just give up. |
7708 | return NS_ERROR_DOCSHELL_DYING; |
7709 | } |
7710 | |
7711 | if (!mBrowsingContext->AncestorsAreCurrent() || |
7712 | mBrowsingContext->IsInBFCache()) { |
7713 | mBrowsingContext->RemoveRootFromBFCacheSync(); |
7714 | return NS_ERROR_NOT_AVAILABLE; |
7715 | } |
7716 | |
7717 | // Can we check the content type of the current content viewer |
7718 | // and reuse it without destroying it and re-creating it? |
7719 | |
7720 | 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" , 7720); MOZ_PretendNoReturn(); } } while (0); |
7721 | |
7722 | // Instantiate the content viewer object |
7723 | nsCOMPtr<nsIDocumentViewer> viewer; |
7724 | nsresult rv = NewDocumentViewerObj(aContentType, aRequest, mLoadGroup, |
7725 | aContentHandler, getter_AddRefs(viewer)); |
7726 | |
7727 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
7728 | return rv; |
7729 | } |
7730 | |
7731 | // Notify the current document that it is about to be unloaded!! |
7732 | // |
7733 | // It is important to fire the unload() notification *before* any state |
7734 | // is changed within the DocShell - otherwise, javascript will get the |
7735 | // wrong information :-( |
7736 | // |
7737 | |
7738 | if (mSavingOldViewer) { |
7739 | // We determined that it was safe to cache the document presentation |
7740 | // at the time we initiated the new load. We need to check whether |
7741 | // it's still safe to do so, since there may have been DOM mutations |
7742 | // or new requests initiated. |
7743 | RefPtr<Document> doc = viewer->GetDocument(); |
7744 | mSavingOldViewer = CanSavePresentation( |
7745 | mLoadType, aRequest, doc, /* aReportBFCacheComboTelemetry */ false); |
7746 | } |
7747 | |
7748 | 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" , 7748); MOZ_PretendNoReturn(); } } while (0); |
7749 | |
7750 | nsCOMPtr<nsIChannel> aOpenedChannel = do_QueryInterface(aRequest); |
7751 | if (aOpenedChannel) { |
7752 | aOpenedChannel->GetURI(getter_AddRefs(mLoadingURI)); |
7753 | } |
7754 | |
7755 | // Grab the current URI, we need to pass it to Embed, and OnNewURI will reset |
7756 | // it before we do call Embed. |
7757 | nsCOMPtr<nsIURI> previousURI = mCurrentURI; |
7758 | |
7759 | FirePageHideNotification(!mSavingOldViewer); |
7760 | if (mIsBeingDestroyed) { |
7761 | // Force to stop the newly created orphaned viewer. |
7762 | viewer->Stop(); |
7763 | return NS_ERROR_DOCSHELL_DYING; |
7764 | } |
7765 | mLoadingURI = nullptr; |
7766 | |
7767 | // Set mFiredUnloadEvent = false so that the unload handler for the |
7768 | // *new* document will fire. |
7769 | mFiredUnloadEvent = false; |
7770 | |
7771 | // we've created a new document so go ahead and call |
7772 | // OnNewURI(), but don't fire OnLocationChange() |
7773 | // notifications before we've called Embed(). See bug 284993. |
7774 | mURIResultedInDocument = true; |
7775 | bool errorOnLocationChangeNeeded = false; |
7776 | nsCOMPtr<nsIChannel> failedChannel = mFailedChannel; |
7777 | nsCOMPtr<nsIURI> failedURI; |
7778 | |
7779 | if (mLoadType == LOAD_ERROR_PAGE) { |
7780 | // We need to set the SH entry and our current URI here and not |
7781 | // at the moment we load the page. We want the same behavior |
7782 | // of Stop() as for a normal page load. See bug 514232 for details. |
7783 | |
7784 | // Revert mLoadType to load type to state the page load failed, |
7785 | // following function calls need it. |
7786 | mLoadType = mFailedLoadType; |
7787 | |
7788 | Document* doc = viewer->GetDocument(); |
7789 | if (doc) { |
7790 | doc->SetFailedChannel(failedChannel); |
7791 | } |
7792 | |
7793 | nsCOMPtr<nsIPrincipal> triggeringPrincipal; |
7794 | if (failedChannel) { |
7795 | // Make sure we have a URI to set currentURI. |
7796 | NS_GetFinalChannelURI(failedChannel, getter_AddRefs(failedURI)); |
7797 | } else { |
7798 | // if there is no failed channel we have to explicitly provide |
7799 | // a triggeringPrincipal for the history entry. |
7800 | triggeringPrincipal = nsContentUtils::GetSystemPrincipal(); |
7801 | } |
7802 | |
7803 | if (!failedURI) { |
7804 | failedURI = mFailedURI; |
7805 | } |
7806 | if (!failedURI) { |
7807 | // We need a URI object to store a session history entry, so make up a URI |
7808 | NS_NewURI(getter_AddRefs(failedURI), "about:blank"); |
7809 | } |
7810 | |
7811 | // When we don't have failedURI, something wrong will happen. See |
7812 | // bug 291876. |
7813 | 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" , 7813); AnnotateMozCrashReason("MOZ_ASSERT" "(" "failedURI" ") (" "We don't have a URI for history APIs." ")"); do { *((volatile int*)__null) = 7813; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
7814 | |
7815 | mFailedChannel = nullptr; |
7816 | mFailedURI = nullptr; |
7817 | |
7818 | // Create an shistory entry for the old load. |
7819 | if (failedURI) { |
7820 | errorOnLocationChangeNeeded = |
7821 | OnNewURI(failedURI, failedChannel, triggeringPrincipal, nullptr, |
7822 | nullptr, nullptr, false, false); |
7823 | } |
7824 | |
7825 | // Be sure to have a correct mLSHE, it may have been cleared by |
7826 | // EndPageLoad. See bug 302115. |
7827 | ChildSHistory* shistory = GetSessionHistory(); |
7828 | if (!mozilla::SessionHistoryInParent() && shistory && !mLSHE) { |
7829 | int32_t idx = shistory->LegacySHistory()->GetRequestedIndex(); |
7830 | if (idx == -1) { |
7831 | idx = shistory->Index(); |
7832 | } |
7833 | shistory->LegacySHistory()->GetEntryAtIndex(idx, getter_AddRefs(mLSHE)); |
7834 | } |
7835 | |
7836 | mLoadType = LOAD_ERROR_PAGE; |
7837 | } |
7838 | |
7839 | nsCOMPtr<nsIURI> finalURI; |
7840 | // If this a redirect, use the final url (uri) |
7841 | // else use the original url |
7842 | // |
7843 | // Note that this should match what documents do (see Document::Reset). |
7844 | NS_GetFinalChannelURI(aOpenedChannel, getter_AddRefs(finalURI)); |
7845 | |
7846 | bool onLocationChangeNeeded = false; |
7847 | if (finalURI) { |
7848 | // Pass false for aCloneSHChildren, since we're loading a new page here. |
7849 | onLocationChangeNeeded = OnNewURI(finalURI, aOpenedChannel, nullptr, |
7850 | nullptr, nullptr, nullptr, true, false); |
7851 | } |
7852 | |
7853 | // let's try resetting the load group if we need to... |
7854 | nsCOMPtr<nsILoadGroup> currentLoadGroup; |
7855 | 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" , 7857); return NS_ERROR_FAILURE; } } while (false) |
7856 | 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" , 7857); return NS_ERROR_FAILURE; } } while (false) |
7857 | 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" , 7857); return NS_ERROR_FAILURE; } } while (false); |
7858 | |
7859 | if (currentLoadGroup != mLoadGroup) { |
7860 | nsLoadFlags loadFlags = 0; |
7861 | |
7862 | // Cancel any URIs that are currently loading... |
7863 | // XXX: Need to do this eventually Stop(); |
7864 | // |
7865 | // Retarget the document to this loadgroup... |
7866 | // |
7867 | /* First attach the channel to the right loadgroup |
7868 | * and then remove from the old loadgroup. This |
7869 | * puts the notifications in the right order and |
7870 | * we don't null-out mLSHE in OnStateChange() for |
7871 | * all redirected urls |
7872 | */ |
7873 | aOpenedChannel->SetLoadGroup(mLoadGroup); |
7874 | |
7875 | // Mark the channel as being a document URI... |
7876 | aOpenedChannel->GetLoadFlags(&loadFlags); |
7877 | loadFlags |= nsIChannel::LOAD_DOCUMENT_URI; |
7878 | nsCOMPtr<nsILoadInfo> loadInfo = aOpenedChannel->LoadInfo(); |
7879 | if (SandboxFlagsImplyCookies(loadInfo->GetSandboxFlags())) { |
7880 | loadFlags |= nsIRequest::LOAD_DOCUMENT_NEEDS_COOKIE; |
7881 | } |
7882 | |
7883 | aOpenedChannel->SetLoadFlags(loadFlags); |
7884 | |
7885 | mLoadGroup->AddRequest(aRequest, nullptr); |
7886 | if (currentLoadGroup) { |
7887 | currentLoadGroup->RemoveRequest(aRequest, nullptr, NS_BINDING_RETARGETED); |
7888 | } |
7889 | |
7890 | // Update the notification callbacks, so that progress and |
7891 | // status information are sent to the right docshell... |
7892 | aOpenedChannel->SetNotificationCallbacks(this); |
7893 | } |
7894 | |
7895 | if (DocGroup::TryToLoadIframesInBackground()) { |
7896 | if ((!mDocumentViewer || GetDocument()->IsInitialDocument()) && |
7897 | IsSubframe()) { |
7898 | // At this point, we know we just created a new iframe document based on |
7899 | // the response from the server, and we check if it's a cross-domain |
7900 | // iframe |
7901 | |
7902 | RefPtr<Document> newDoc = viewer->GetDocument(); |
7903 | |
7904 | RefPtr<nsDocShell> parent = GetInProcessParentDocshell(); |
7905 | nsCOMPtr<nsIPrincipal> parentPrincipal = |
7906 | parent->GetDocument()->NodePrincipal(); |
7907 | nsCOMPtr<nsIPrincipal> thisPrincipal = newDoc->NodePrincipal(); |
7908 | |
7909 | SiteIdentifier parentSite; |
7910 | SiteIdentifier thisSite; |
7911 | |
7912 | nsresult rv = |
7913 | BasePrincipal::Cast(parentPrincipal)->GetSiteIdentifier(parentSite); |
7914 | 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" , 7914); return rv; } } while (false); |
7915 | |
7916 | rv = BasePrincipal::Cast(thisPrincipal)->GetSiteIdentifier(thisSite); |
7917 | 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" , 7917); return rv; } } while (false); |
7918 | |
7919 | if (!parentSite.Equals(thisSite)) { |
7920 | if (profiler_thread_is_being_profiled_for_markers()) { |
7921 | nsCOMPtr<nsIURI> prinURI; |
7922 | BasePrincipal::Cast(thisPrincipal)->GetURI(getter_AddRefs(prinURI)); |
7923 | nsPrintfCString marker( |
7924 | "Iframe loaded in background: %s", |
7925 | nsContentUtils::TruncatedURLForDisplay(prinURI).get()); |
7926 | PROFILER_MARKER_TEXT("Background Iframe", DOM, {}, marker)do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl ("Background Iframe", ::geckoprofiler::category::DOM, {}, ::geckoprofiler ::markers::TextMarker{}, marker); } } while (false); } while ( false); |
7927 | } |
7928 | SetBackgroundLoadIframe(); |
7929 | } |
7930 | } |
7931 | } |
7932 | |
7933 | 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" , 7936); return NS_ERROR_FAILURE; } } while (false) |
7934 | 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" , 7936); return NS_ERROR_FAILURE; } } while (false) |
7935 | 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" , 7936); return NS_ERROR_FAILURE; } } while (false) |
7936 | 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" , 7936); return NS_ERROR_FAILURE; } } while (false); |
7937 | |
7938 | if (!mBrowsingContext->GetHasLoadedNonInitialDocument()) { |
7939 | 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" , 7939); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false" ") (" "NS_SUCCEEDED(mBrowsingContext->SetHasLoadedNonInitialDocument(true))" ")"); do { *((volatile int*)__null) = 7939; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); |
7940 | } |
7941 | |
7942 | if (TreatAsBackgroundLoad()) { |
7943 | nsCOMPtr<nsIRunnable> triggerParentCheckDocShell = |
7944 | NewRunnableMethod("nsDocShell::TriggerParentCheckDocShellIsEmpty", this, |
7945 | &nsDocShell::TriggerParentCheckDocShellIsEmpty); |
7946 | nsresult rv = NS_DispatchToCurrentThread(triggerParentCheckDocShell); |
7947 | 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" , 7947); return rv; } } while (false); |
7948 | } |
7949 | |
7950 | mSavedRefreshURIList = nullptr; |
7951 | mSavingOldViewer = false; |
7952 | mEODForCurrentDocument = false; |
7953 | |
7954 | // if this document is part of a multipart document, |
7955 | // the ID can be used to distinguish it from the other parts. |
7956 | nsCOMPtr<nsIMultiPartChannel> multiPartChannel(do_QueryInterface(aRequest)); |
7957 | if (multiPartChannel) { |
7958 | if (PresShell* presShell = GetPresShell()) { |
7959 | if (Document* doc = presShell->GetDocument()) { |
7960 | uint32_t partID; |
7961 | multiPartChannel->GetPartID(&partID); |
7962 | doc->SetPartID(partID); |
7963 | } |
7964 | } |
7965 | } |
7966 | |
7967 | if (errorOnLocationChangeNeeded) { |
7968 | FireOnLocationChange(this, failedChannel, failedURI, |
7969 | LOCATION_CHANGE_ERROR_PAGE); |
7970 | } else if (onLocationChangeNeeded) { |
7971 | uint32_t locationFlags = |
7972 | (mLoadType & LOAD_CMD_RELOAD) ? uint32_t(LOCATION_CHANGE_RELOAD) : 0; |
7973 | FireOnLocationChange(this, aRequest, mCurrentURI, locationFlags); |
7974 | } |
7975 | |
7976 | return NS_OK; |
7977 | } |
7978 | |
7979 | nsresult nsDocShell::NewDocumentViewerObj(const nsACString& aContentType, |
7980 | nsIRequest* aRequest, |
7981 | nsILoadGroup* aLoadGroup, |
7982 | nsIStreamListener** aContentHandler, |
7983 | nsIDocumentViewer** aViewer) { |
7984 | nsCOMPtr<nsIChannel> aOpenedChannel = do_QueryInterface(aRequest); |
7985 | |
7986 | nsCOMPtr<nsIDocumentLoaderFactory> docLoaderFactory = |
7987 | nsContentUtils::FindInternalDocumentViewer(aContentType); |
7988 | if (!docLoaderFactory) { |
7989 | return NS_ERROR_FAILURE; |
7990 | } |
7991 | |
7992 | // Now create an instance of the content viewer nsLayoutDLF makes the |
7993 | // determination if it should be a "view-source" instead of "view" |
7994 | nsresult rv = docLoaderFactory->CreateInstance( |
7995 | "view", aOpenedChannel, aLoadGroup, aContentType, this, nullptr, |
7996 | aContentHandler, aViewer); |
7997 | 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" , 7997); return rv; } } while (false); |
7998 | |
7999 | (*aViewer)->SetContainer(this); |
8000 | return NS_OK; |
8001 | } |
8002 | |
8003 | nsresult nsDocShell::SetupNewViewer(nsIDocumentViewer* aNewViewer, |
8004 | WindowGlobalChild* aWindowActor) { |
8005 | 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" , 8005); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mIsBeingDestroyed" ")"); do { *((volatile int*)__null) = 8005; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
8006 | |
8007 | // |
8008 | // Copy content viewer state from previous or parent content viewer. |
8009 | // |
8010 | // The following logic is mirrored in nsHTMLDocument::StartDocumentLoad! |
8011 | // |
8012 | // Do NOT to maintain a reference to the old content viewer outside |
8013 | // of this "copying" block, or it will not be destroyed until the end of |
8014 | // this routine and all <SCRIPT>s and event handlers fail! (bug 20315) |
8015 | // |
8016 | // In this block of code, if we get an error result, we return it |
8017 | // but if we get a null pointer, that's perfectly legal for parent |
8018 | // and parentContentViewer. |
8019 | // |
8020 | |
8021 | int32_t x = 0; |
8022 | int32_t y = 0; |
8023 | int32_t cx = 0; |
8024 | int32_t cy = 0; |
8025 | |
8026 | // This will get the size from the current content viewer or from the |
8027 | // Init settings |
8028 | DoGetPositionAndSize(&x, &y, &cx, &cy); |
8029 | |
8030 | nsCOMPtr<nsIDocShellTreeItem> parentAsItem; |
8031 | 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" , 8032); return NS_ERROR_FAILURE; } } while (false) |
8032 | 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" , 8032); return NS_ERROR_FAILURE; } } while (false); |
8033 | nsCOMPtr<nsIDocShell> parent(do_QueryInterface(parentAsItem)); |
8034 | |
8035 | const Encoding* reloadEncoding = nullptr; |
8036 | int32_t reloadEncodingSource = kCharsetUninitialized; |
8037 | // |newMUDV| also serves as a flag to set the data from the above vars |
8038 | nsCOMPtr<nsIDocumentViewer> newViewer; |
8039 | |
8040 | if (mDocumentViewer || parent) { |
8041 | nsCOMPtr<nsIDocumentViewer> oldViewer; |
8042 | if (mDocumentViewer) { |
8043 | // Get any interesting state from old content viewer |
8044 | // XXX: it would be far better to just reuse the document viewer , |
8045 | // since we know we're just displaying the same document as before |
8046 | oldViewer = mDocumentViewer; |
8047 | |
8048 | // Tell the old content viewer to hibernate in session history when |
8049 | // it is destroyed. |
8050 | |
8051 | if (mSavingOldViewer && NS_FAILED(CaptureState())((bool)(__builtin_expect(!!(NS_FAILED_impl(CaptureState())), 0 )))) { |
8052 | if (mOSHE) { |
8053 | mOSHE->SyncPresentationState(); |
8054 | } |
8055 | mSavingOldViewer = false; |
8056 | } |
8057 | } else { |
8058 | // No old content viewer, so get state from parent's content viewer |
8059 | parent->GetDocViewer(getter_AddRefs(oldViewer)); |
8060 | } |
8061 | |
8062 | if (oldViewer) { |
8063 | newViewer = aNewViewer; |
8064 | if (newViewer) { |
8065 | reloadEncoding = |
8066 | oldViewer->GetReloadEncodingAndSource(&reloadEncodingSource); |
8067 | } |
8068 | } |
8069 | } |
8070 | |
8071 | nscolor bgcolor = NS_RGBA(0, 0, 0, 0)((nscolor)(((0) << 24) | ((0) << 16) | ((0) << 8) | (0))); |
8072 | bool isUnderHiddenEmbedderElement = false; |
8073 | // Ensure that the content viewer is destroyed *after* the GC - bug 71515 |
8074 | nsCOMPtr<nsIDocumentViewer> viewer = mDocumentViewer; |
8075 | if (viewer) { |
8076 | // Stop any activity that may be happening in the old document before |
8077 | // releasing it... |
8078 | viewer->Stop(); |
8079 | |
8080 | // Try to extract the canvas background color from the old |
8081 | // presentation shell, so we can use it for the next document. |
8082 | if (PresShell* presShell = viewer->GetPresShell()) { |
8083 | bgcolor = presShell->GetCanvasBackground(); |
8084 | isUnderHiddenEmbedderElement = presShell->IsUnderHiddenEmbedderElement(); |
8085 | } |
8086 | |
8087 | viewer->Close(mSavingOldViewer ? mOSHE.get() : nullptr); |
8088 | aNewViewer->SetPreviousViewer(viewer); |
8089 | } |
8090 | if (mOSHE && (!mDocumentViewer || !mSavingOldViewer)) { |
8091 | // We don't plan to save a viewer in mOSHE; tell it to drop |
8092 | // any other state it's holding. |
8093 | mOSHE->SyncPresentationState(); |
8094 | } |
8095 | |
8096 | mDocumentViewer = nullptr; |
8097 | |
8098 | // Now that we're about to switch documents, forget all of our children. |
8099 | // Note that we cached them as needed up in CaptureState above. |
8100 | DestroyChildren(); |
8101 | |
8102 | mDocumentViewer = aNewViewer; |
8103 | |
8104 | nsCOMPtr<nsIWidget> widget; |
8105 | 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" , 8105); return NS_ERROR_FAILURE; } } while (false); |
8106 | |
8107 | nsIntRect bounds(x, y, cx, cy); |
8108 | |
8109 | mDocumentViewer->SetNavigationTiming(mTiming); |
8110 | |
8111 | if (NS_FAILED(mDocumentViewer->Init(widget, bounds, aWindowActor))((bool)(__builtin_expect(!!(NS_FAILED_impl(mDocumentViewer-> Init(widget, bounds, aWindowActor))), 0)))) { |
8112 | nsCOMPtr<nsIDocumentViewer> viewer = mDocumentViewer; |
8113 | viewer->Close(nullptr); |
8114 | viewer->Destroy(); |
8115 | mDocumentViewer = nullptr; |
8116 | SetCurrentURIInternal(nullptr); |
8117 | 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" , 8117); |
8118 | return NS_ERROR_FAILURE; |
8119 | } |
8120 | |
8121 | // If we have old state to copy, set the old state onto the new content |
8122 | // viewer |
8123 | if (newViewer) { |
8124 | newViewer->SetReloadEncodingAndSource(reloadEncoding, reloadEncodingSource); |
8125 | } |
8126 | |
8127 | 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" , 8127); return NS_ERROR_FAILURE; } } while (false); |
8128 | |
8129 | // Stuff the bgcolor from the old pres shell into the new |
8130 | // pres shell. This improves page load continuity. |
8131 | if (RefPtr<PresShell> presShell = mDocumentViewer->GetPresShell()) { |
8132 | presShell->SetCanvasBackground(bgcolor); |
8133 | presShell->ActivenessMaybeChanged(); |
8134 | if (isUnderHiddenEmbedderElement) { |
8135 | presShell->SetIsUnderHiddenEmbedderElement(isUnderHiddenEmbedderElement); |
8136 | } |
8137 | } |
8138 | |
8139 | // XXX: It looks like the LayoutState gets restored again in Embed() |
8140 | // right after the call to SetupNewViewer(...) |
8141 | |
8142 | // We don't show the mDocumentViewer yet, since we want to draw the old page |
8143 | // until we have enough of the new page to show. Just return with the new |
8144 | // viewer still set to hidden. |
8145 | |
8146 | return NS_OK; |
8147 | } |
8148 | |
8149 | void nsDocShell::SetDocCurrentStateObj(nsISHEntry* aShEntry, |
8150 | SessionHistoryInfo* aInfo) { |
8151 | 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" , 8151); return; } } while (false); |
8152 | |
8153 | RefPtr<Document> document = GetDocument(); |
8154 | 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" , 8154); return; } } while (false); |
8155 | |
8156 | nsCOMPtr<nsIStructuredCloneContainer> scContainer; |
8157 | if (mozilla::SessionHistoryInParent()) { |
8158 | // If aInfo is null, just set the document's state object to null. |
8159 | if (aInfo) { |
8160 | scContainer = aInfo->GetStateData(); |
8161 | } |
8162 | 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) |
8163 | ("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); |
8164 | } else { |
8165 | if (aShEntry) { |
8166 | scContainer = aShEntry->GetStateData(); |
8167 | |
8168 | // If aShEntry is null, just set the document's state object to null. |
8169 | } |
8170 | } |
8171 | |
8172 | // It's OK for scContainer too be null here; that just means there's no |
8173 | // state data associated with this history entry. |
8174 | document->SetStateObject(scContainer); |
8175 | } |
8176 | |
8177 | nsresult nsDocShell::CheckLoadingPermissions() { |
8178 | // This method checks whether the caller may load content into |
8179 | // this docshell. Even though we've done our best to hide windows |
8180 | // from code that doesn't have the right to access them, it's |
8181 | // still possible for an evil site to open a window and access |
8182 | // frames in the new window through window.frames[] (which is |
8183 | // allAccess for historic reasons), so we still need to do this |
8184 | // check on load. |
8185 | nsresult rv = NS_OK; |
8186 | |
8187 | if (!IsSubframe()) { |
8188 | // We're not a frame. Permit all loads. |
8189 | return rv; |
8190 | } |
8191 | |
8192 | // Note - The check for a current JSContext here isn't necessarily sensical. |
8193 | // It's just designed to preserve the old semantics during a mass-conversion |
8194 | // patch. |
8195 | if (!nsContentUtils::GetCurrentJSContext()) { |
8196 | return NS_OK; |
8197 | } |
8198 | |
8199 | // Check if the caller is from the same origin as this docshell, |
8200 | // or any of its ancestors. |
8201 | for (RefPtr<BrowsingContext> bc = mBrowsingContext; bc; |
8202 | bc = bc->GetParent()) { |
8203 | // If the BrowsingContext is not in process, then it |
8204 | // is true by construction that its principal will not |
8205 | // subsume the current docshell principal. |
8206 | if (!bc->IsInProcess()) { |
8207 | continue; |
8208 | } |
8209 | |
8210 | nsCOMPtr<nsIScriptGlobalObject> sgo = |
8211 | bc->GetDocShell()->GetScriptGlobalObject(); |
8212 | nsCOMPtr<nsIScriptObjectPrincipal> sop(do_QueryInterface(sgo)); |
8213 | |
8214 | nsIPrincipal* p; |
8215 | if (!sop || !(p = sop->GetPrincipal())) { |
8216 | return NS_ERROR_UNEXPECTED; |
8217 | } |
8218 | |
8219 | if (nsContentUtils::SubjectPrincipal()->Subsumes(p)) { |
8220 | // Same origin, permit load |
8221 | return NS_OK; |
8222 | } |
8223 | } |
8224 | |
8225 | return NS_ERROR_DOM_PROP_ACCESS_DENIED; |
8226 | } |
8227 | |
8228 | //***************************************************************************** |
8229 | // nsDocShell: Site Loading |
8230 | //***************************************************************************** |
8231 | |
8232 | void nsDocShell::CopyFavicon(nsIURI* aOldURI, nsIURI* aNewURI, |
8233 | bool aInPrivateBrowsing) { |
8234 | if (XRE_IsContentProcess()) { |
8235 | dom::ContentChild* contentChild = dom::ContentChild::GetSingleton(); |
8236 | if (contentChild) { |
8237 | contentChild->SendCopyFavicon(aOldURI, aNewURI, aInPrivateBrowsing); |
8238 | } |
8239 | return; |
8240 | } |
8241 | |
8242 | #ifdef MOZ_PLACES1 |
8243 | nsCOMPtr<nsIFaviconService> favSvc = |
8244 | do_GetService("@mozilla.org/browser/favicon-service;1"); |
8245 | if (favSvc) { |
8246 | favSvc->CopyFavicons(aOldURI, aNewURI, |
8247 | aInPrivateBrowsing |
8248 | ? nsIFaviconService::FAVICON_LOAD_PRIVATE |
8249 | : nsIFaviconService::FAVICON_LOAD_NON_PRIVATE, |
8250 | nullptr); |
8251 | } |
8252 | #endif |
8253 | } |
8254 | |
8255 | class InternalLoadEvent : public Runnable { |
8256 | public: |
8257 | InternalLoadEvent(nsDocShell* aDocShell, nsDocShellLoadState* aLoadState) |
8258 | : mozilla::Runnable("InternalLoadEvent"), |
8259 | mDocShell(aDocShell), |
8260 | mLoadState(aLoadState) { |
8261 | // For events, both target and filename should be the version of "null" they |
8262 | // expect. By the time the event is fired, both window targeting and file |
8263 | // downloading have been handled, so we should never have an internal load |
8264 | // event that retargets or had a download. |
8265 | mLoadState->SetTarget(u""_ns); |
8266 | mLoadState->SetFileName(VoidString()); |
8267 | } |
8268 | |
8269 | NS_IMETHODvirtual nsresult |
8270 | Run() override { |
8271 | #ifndef ANDROID |
8272 | 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" , 8273); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLoadState->TriggeringPrincipal()" ") (" "InternalLoadEvent: Should always have a principal here" ")"); do { *((volatile int*)__null) = 8273; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
8273 | "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" , 8273); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLoadState->TriggeringPrincipal()" ") (" "InternalLoadEvent: Should always have a principal here" ")"); do { *((volatile int*)__null) = 8273; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
8274 | #endif |
8275 | return mDocShell->InternalLoad(mLoadState); |
8276 | } |
8277 | |
8278 | private: |
8279 | RefPtr<nsDocShell> mDocShell; |
8280 | RefPtr<nsDocShellLoadState> mLoadState; |
8281 | }; |
8282 | |
8283 | /** |
8284 | * Returns true if we started an asynchronous load (i.e., from the network), but |
8285 | * the document we're loading there hasn't yet become this docshell's active |
8286 | * document. |
8287 | * |
8288 | * When JustStartedNetworkLoad is true, you should be careful about modifying |
8289 | * mLoadType and mLSHE. These are both set when the asynchronous load first |
8290 | * starts, and the load expects that, when it eventually runs InternalLoad, |
8291 | * mLoadType and mLSHE will have their original values. |
8292 | */ |
8293 | bool nsDocShell::JustStartedNetworkLoad() { |
8294 | return mDocumentRequest && mDocumentRequest != GetCurrentDocChannel(); |
8295 | } |
8296 | |
8297 | // The contentType will be INTERNAL_(I)FRAME if this docshell is for a |
8298 | // non-toplevel browsing context in spec terms. (frame, iframe, <object>, |
8299 | // <embed>, etc) |
8300 | // |
8301 | // This return value will be used when we call NS_CheckContentLoadPolicy, and |
8302 | // later when we call DoURILoad. |
8303 | nsContentPolicyType nsDocShell::DetermineContentType() { |
8304 | if (!IsSubframe()) { |
8305 | return nsIContentPolicy::TYPE_DOCUMENT; |
8306 | } |
8307 | |
8308 | const auto& maybeEmbedderElementType = |
8309 | GetBrowsingContext()->GetEmbedderElementType(); |
8310 | if (!maybeEmbedderElementType) { |
8311 | // If the EmbedderElementType hasn't been set yet, just assume we're |
8312 | // an iframe since that's more common. |
8313 | return nsIContentPolicy::TYPE_INTERNAL_IFRAME; |
8314 | } |
8315 | |
8316 | return maybeEmbedderElementType->EqualsLiteral("iframe") |
8317 | ? nsIContentPolicy::TYPE_INTERNAL_IFRAME |
8318 | : nsIContentPolicy::TYPE_INTERNAL_FRAME; |
8319 | } |
8320 | |
8321 | bool nsDocShell::NoopenerForceEnabled() { |
8322 | // If current's top-level browsing context's active document's |
8323 | // cross-origin-opener-policy is "same-origin" or "same-origin + COEP" then |
8324 | // if currentDoc's origin is not same origin with currentDoc's top-level |
8325 | // origin, noopener is force enabled, and name is cleared to "_blank". |
8326 | auto topPolicy = mBrowsingContext->Top()->GetOpenerPolicy(); |
8327 | return (topPolicy == nsILoadInfo::OPENER_POLICY_SAME_ORIGIN || |
8328 | topPolicy == |
8329 | nsILoadInfo:: |
8330 | OPENER_POLICY_SAME_ORIGIN_EMBEDDER_POLICY_REQUIRE_CORP) && |
8331 | !mBrowsingContext->SameOriginWithTop(); |
8332 | } |
8333 | |
8334 | nsresult nsDocShell::PerformRetargeting(nsDocShellLoadState* aLoadState) { |
8335 | 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" , 8335); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState" ") (" "need a load state!" ")"); do { *((volatile int*)__null ) = 8335; __attribute__((nomerge)) ::abort(); } while (false) ; } } while (false); |
8336 | 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" , 8336); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aLoadState->Target().IsEmpty()" ") (" "should have a target here!" ")"); do { *((volatile int *)__null) = 8336; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
8337 | 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" , 8338); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->TargetBrowsingContext().IsNull()" ") (" "should not have picked target yet" ")"); do { *((volatile int*)__null) = 8338; __attribute__((nomerge)) ::abort(); } while (false); } } while (false) |
8338 | "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" , 8338); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->TargetBrowsingContext().IsNull()" ") (" "should not have picked target yet" ")"); do { *((volatile int*)__null) = 8338; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
8339 | |
8340 | nsresult rv = NS_OK; |
8341 | RefPtr<BrowsingContext> targetContext; |
8342 | |
8343 | // Only _self, _parent, and _top are supported in noopener case. But we |
8344 | // have to be careful to not apply that to the noreferrer case. See bug |
8345 | // 1358469. |
8346 | bool allowNamedTarget = |
8347 | !aLoadState->HasInternalLoadFlags(INTERNAL_LOAD_FLAGS_NO_OPENER) || |
8348 | aLoadState->HasInternalLoadFlags(INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER); |
8349 | if (allowNamedTarget || |
8350 | aLoadState->Target().LowerCaseEqualsLiteral("_self") || |
8351 | aLoadState->Target().LowerCaseEqualsLiteral("_parent") || |
8352 | aLoadState->Target().LowerCaseEqualsLiteral("_top")) { |
8353 | Document* document = GetDocument(); |
8354 | 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" , 8354); return NS_ERROR_FAILURE; } } while (false); |
8355 | WindowGlobalChild* wgc = document->GetWindowGlobalChild(); |
8356 | 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" , 8356); return NS_ERROR_FAILURE; } } while (false); |
8357 | targetContext = wgc->FindBrowsingContextWithName( |
8358 | aLoadState->Target(), /* aUseEntryGlobalForAccessCheck */ false); |
8359 | } |
8360 | |
8361 | if (!targetContext) { |
8362 | // If the targetContext doesn't exist, then this is a new docShell and we |
8363 | // should consider this a TYPE_DOCUMENT load |
8364 | // |
8365 | // For example, when target="_blank" |
8366 | |
8367 | // If there's no targetContext, that means we are about to create a new |
8368 | // window. Perform a content policy check before creating the window. Please |
8369 | // note for all other docshell loads content policy checks are performed |
8370 | // within the contentSecurityManager when the channel is about to be |
8371 | // openend. |
8372 | nsISupports* requestingContext = nullptr; |
8373 | if (XRE_IsContentProcess()) { |
8374 | // In e10s the child process doesn't have access to the element that |
8375 | // contains the browsing context (because that element is in the chrome |
8376 | // process). So we just pass mScriptGlobal. |
8377 | requestingContext = ToSupports(mScriptGlobal); |
8378 | } else { |
8379 | // This is for loading non-e10s tabs and toplevel windows of various |
8380 | // sorts. |
8381 | // For the toplevel window cases, requestingElement will be null. |
8382 | nsCOMPtr<Element> requestingElement = |
8383 | mScriptGlobal->GetFrameElementInternal(); |
8384 | requestingContext = requestingElement; |
8385 | } |
8386 | |
8387 | // Ideally we should use the same loadinfo as within DoURILoad which |
8388 | // should match this one when both are applicable. |
8389 | nsCOMPtr<nsILoadInfo> secCheckLoadInfo = |
8390 | new LoadInfo(mScriptGlobal, aLoadState->URI(), |
8391 | aLoadState->TriggeringPrincipal(), requestingContext, |
8392 | nsILoadInfo::SEC_ONLY_FOR_EXPLICIT_CONTENTSEC_CHECK, 0); |
8393 | |
8394 | // Since Content Policy checks are performed within docShell as well as |
8395 | // the ContentSecurityManager we need a reliable way to let certain |
8396 | // nsIContentPolicy consumers ignore duplicate calls. |
8397 | secCheckLoadInfo->SetSkipContentPolicyCheckForWebRequest(true); |
8398 | |
8399 | int16_t shouldLoad = nsIContentPolicy::ACCEPT; |
8400 | rv = NS_CheckContentLoadPolicy(aLoadState->URI(), secCheckLoadInfo, |
8401 | ""_ns, // mime guess |
8402 | &shouldLoad); |
8403 | |
8404 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || NS_CP_REJECTED(shouldLoad)((shouldLoad) != nsIContentPolicy::ACCEPT)) { |
8405 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) { |
8406 | if (shouldLoad == nsIContentPolicy::REJECT_TYPE) { |
8407 | return NS_ERROR_CONTENT_BLOCKED_SHOW_ALT; |
8408 | } |
8409 | if (shouldLoad == nsIContentPolicy::REJECT_POLICY) { |
8410 | return NS_ERROR_BLOCKED_BY_POLICY; |
8411 | } |
8412 | } |
8413 | |
8414 | return NS_ERROR_CONTENT_BLOCKED; |
8415 | } |
8416 | } |
8417 | |
8418 | // |
8419 | // Resolve the window target before going any further... |
8420 | // If the load has been targeted to another DocShell, then transfer the |
8421 | // load to it... |
8422 | // |
8423 | |
8424 | // We've already done our owner-inheriting. Mask out that bit, so we |
8425 | // don't try inheriting an owner from the target window if we came up |
8426 | // with a null owner above. |
8427 | aLoadState->UnsetInternalLoadFlag(INTERNAL_LOAD_FLAGS_INHERIT_PRINCIPAL); |
8428 | |
8429 | if (!targetContext) { |
8430 | // If the docshell's document is sandboxed, only open a new window |
8431 | // if the document's SANDBOXED_AUXILLARY_NAVIGATION flag is not set. |
8432 | // (i.e. if allow-popups is specified) |
8433 | 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" , 8433); return NS_ERROR_FAILURE; } } while (false); |
8434 | Document* doc = mDocumentViewer->GetDocument(); |
8435 | |
8436 | const bool isDocumentAuxSandboxed = |
8437 | doc && (doc->GetSandboxFlags() & SANDBOXED_AUXILIARY_NAVIGATION); |
8438 | |
8439 | if (isDocumentAuxSandboxed) { |
8440 | return NS_ERROR_DOM_INVALID_ACCESS_ERR; |
8441 | } |
8442 | |
8443 | nsCOMPtr<nsPIDOMWindowOuter> win = GetWindow(); |
8444 | 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" , 8444); return NS_ERROR_NOT_AVAILABLE; } } while (false); |
8445 | |
8446 | RefPtr<BrowsingContext> newBC; |
8447 | nsAutoCString spec; |
8448 | aLoadState->URI()->GetSpec(spec); |
8449 | |
8450 | // If we are a noopener load, we just hand the whole thing over to our |
8451 | // window. |
8452 | if (aLoadState->HasInternalLoadFlags(INTERNAL_LOAD_FLAGS_NO_OPENER) || |
8453 | NoopenerForceEnabled()) { |
8454 | // Various asserts that we know to hold because NO_OPENER loads can only |
8455 | // happen for links. |
8456 | 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" , 8456); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aLoadState->LoadReplace()" ")"); do { *((volatile int*)__null) = 8456; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
8457 | 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" , 8458); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->PrincipalToInherit() == aLoadState->TriggeringPrincipal()" ")"); do { *((volatile int*)__null) = 8458; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
8458 | 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" , 8458); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->PrincipalToInherit() == aLoadState->TriggeringPrincipal()" ")"); do { *((volatile int*)__null) = 8458; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
8459 | 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" , 8463); 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) = 8463; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
8460 | ~(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" , 8463); 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) = 8463; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
8461 | 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" , 8463); 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) = 8463; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
8462 | "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" , 8463); 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) = 8463; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
8463 | "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" , 8463); 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) = 8463; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
8464 | 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" , 8465); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->IsFormSubmission()" ")"); do { *((volatile int*)__null) = 8465; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) |
8465 | 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" , 8465); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->IsFormSubmission()" ")"); do { *((volatile int*)__null) = 8465; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); |
8466 | 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" , 8466); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aLoadState->HeadersStream()" ")"); do { *((volatile int*)__null) = 8466; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
8467 | // If OnLinkClickSync was invoked inside the onload handler, the load |
8468 | // type would be set to LOAD_NORMAL_REPLACE; otherwise it should be |
8469 | // LOAD_LINK. |
8470 | 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" , 8471); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->LoadType() == LOAD_LINK || aLoadState->LoadType() == LOAD_NORMAL_REPLACE" ")"); do { *((volatile int*)__null) = 8471; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
8471 | 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" , 8471); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->LoadType() == LOAD_LINK || aLoadState->LoadType() == LOAD_NORMAL_REPLACE" ")"); do { *((volatile int*)__null) = 8471; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
8472 | 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" , 8472); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aLoadState->LoadIsFromSessionHistory()" ")"); do { *((volatile int*)__null) = 8472; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
8473 | 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" , 8473); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->FirstParty()" ")"); do { *((volatile int*)__null) = 8473; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); // Windowwatcher will assume this. |
8474 | |
8475 | RefPtr<nsDocShellLoadState> loadState = |
8476 | new nsDocShellLoadState(aLoadState->URI()); |
8477 | |
8478 | // Set up our loadinfo so it will do the load as much like we would have |
8479 | // as possible. |
8480 | loadState->SetReferrerInfo(aLoadState->GetReferrerInfo()); |
8481 | loadState->SetOriginalURI(aLoadState->OriginalURI()); |
8482 | |
8483 | Maybe<nsCOMPtr<nsIURI>> resultPrincipalURI; |
8484 | aLoadState->GetMaybeResultPrincipalURI(resultPrincipalURI); |
8485 | |
8486 | loadState->SetMaybeResultPrincipalURI(resultPrincipalURI); |
8487 | loadState->SetKeepResultPrincipalURIIfSet( |
8488 | aLoadState->KeepResultPrincipalURIIfSet()); |
8489 | // LoadReplace will always be false due to asserts above, skip setting |
8490 | // it. |
8491 | loadState->SetTriggeringPrincipal(aLoadState->TriggeringPrincipal()); |
8492 | loadState->SetTriggeringSandboxFlags( |
8493 | aLoadState->TriggeringSandboxFlags()); |
8494 | loadState->SetTriggeringWindowId(aLoadState->TriggeringWindowId()); |
8495 | loadState->SetTriggeringStorageAccess( |
8496 | aLoadState->TriggeringStorageAccess()); |
8497 | loadState->SetCsp(aLoadState->Csp()); |
8498 | loadState->SetInheritPrincipal(aLoadState->HasInternalLoadFlags( |
8499 | INTERNAL_LOAD_FLAGS_INHERIT_PRINCIPAL)); |
8500 | // Explicit principal because we do not want any guesses as to what the |
8501 | // principal to inherit is: it should be aTriggeringPrincipal. |
8502 | loadState->SetPrincipalIsExplicit(true); |
8503 | loadState->SetLoadType(aLoadState->LoadType()); |
8504 | loadState->SetForceAllowDataURI(aLoadState->HasInternalLoadFlags( |
8505 | INTERNAL_LOAD_FLAGS_FORCE_ALLOW_DATA_URI)); |
8506 | |
8507 | loadState->SetHasValidUserGestureActivation( |
8508 | aLoadState->HasValidUserGestureActivation()); |
8509 | |
8510 | // Propagate POST data to the new load. |
8511 | loadState->SetPostDataStream(aLoadState->PostDataStream()); |
8512 | loadState->SetIsFormSubmission(aLoadState->IsFormSubmission()); |
8513 | |
8514 | rv = win->Open(NS_ConvertUTF8toUTF16(spec), |
8515 | aLoadState->Target(), // window name |
8516 | u""_ns, // Features |
8517 | loadState, |
8518 | true, // aForceNoOpener |
8519 | getter_AddRefs(newBC)); |
8520 | 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" , 8520); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!newBC" ")" ); do { *((volatile int*)__null) = 8520; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
8521 | return rv; |
8522 | } |
8523 | |
8524 | rv = win->OpenNoNavigate(NS_ConvertUTF8toUTF16(spec), |
8525 | aLoadState->Target(), // window name |
8526 | u""_ns, // Features |
8527 | getter_AddRefs(newBC)); |
8528 | |
8529 | // In some cases the Open call doesn't actually result in a new |
8530 | // window being opened. We can detect these cases by examining the |
8531 | // document in |newBC|, if any. |
8532 | nsCOMPtr<nsPIDOMWindowOuter> piNewWin = |
8533 | newBC ? newBC->GetDOMWindow() : nullptr; |
8534 | if (piNewWin) { |
8535 | RefPtr<Document> newDoc = piNewWin->GetExtantDoc(); |
8536 | if (!newDoc || newDoc->IsInitialDocument()) { |
8537 | aLoadState->SetInternalLoadFlag(INTERNAL_LOAD_FLAGS_FIRST_LOAD); |
8538 | } |
8539 | } |
8540 | |
8541 | if (newBC) { |
8542 | targetContext = newBC; |
8543 | } |
8544 | } |
8545 | 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" , 8545); return rv; } } while (false); |
8546 | 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" , 8546); return rv; } } while (false); |
8547 | |
8548 | // If our target BrowsingContext is still pending initialization, ignore the |
8549 | // navigation request targeting it. |
8550 | 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" , 8550)) { |
8551 | return NS_OK; |
8552 | } |
8553 | |
8554 | aLoadState->SetTargetBrowsingContext(targetContext); |
8555 | if (aLoadState->IsFormSubmission()) { |
8556 | aLoadState->SetLoadType( |
8557 | GetLoadTypeForFormSubmission(targetContext, aLoadState)); |
8558 | } |
8559 | |
8560 | // |
8561 | // Transfer the load to the target BrowsingContext... Clear the window target |
8562 | // name to the empty string to prevent recursive retargeting! |
8563 | // |
8564 | // No window target |
8565 | aLoadState->SetTarget(u""_ns); |
8566 | // No forced download |
8567 | aLoadState->SetFileName(VoidString()); |
8568 | return targetContext->InternalLoad(aLoadState); |
8569 | } |
8570 | |
8571 | static nsAutoCString RefMaybeNull(nsIURI* aURI) { |
8572 | nsAutoCString result; |
8573 | if (NS_FAILED(aURI->GetRef(result))((bool)(__builtin_expect(!!(NS_FAILED_impl(aURI->GetRef(result ))), 0)))) { |
8574 | result.SetIsVoid(true); |
8575 | } |
8576 | return result; |
8577 | } |
8578 | |
8579 | uint32_t nsDocShell::GetSameDocumentNavigationFlags(nsIURI* aNewURI) { |
8580 | uint32_t flags = LOCATION_CHANGE_SAME_DOCUMENT; |
8581 | |
8582 | bool equal = false; |
8583 | if (mCurrentURI && |
8584 | NS_SUCCEEDED(mCurrentURI->EqualsExceptRef(aNewURI, &equal))((bool)(__builtin_expect(!!(!NS_FAILED_impl(mCurrentURI->EqualsExceptRef (aNewURI, &equal))), 1))) && equal && |
8585 | RefMaybeNull(mCurrentURI) != RefMaybeNull(aNewURI)) { |
8586 | flags |= LOCATION_CHANGE_HASHCHANGE; |
8587 | } |
8588 | |
8589 | return flags; |
8590 | } |
8591 | |
8592 | bool nsDocShell::IsSameDocumentNavigation(nsDocShellLoadState* aLoadState, |
8593 | SameDocumentNavigationState& aState) { |
8594 | 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" , 8594); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState" ")"); do { *((volatile int*)__null) = 8594; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
8595 | if (!(aLoadState->LoadType() == LOAD_NORMAL || |
8596 | aLoadState->LoadType() == LOAD_STOP_CONTENT || |
8597 | LOAD_TYPE_HAS_FLAGS(aLoadState->LoadType(),((aLoadState->LoadType()) & ((LOAD_FLAGS_REPLACE_HISTORY ) << 16)) |
8598 | LOAD_FLAGS_REPLACE_HISTORY)((aLoadState->LoadType()) & ((LOAD_FLAGS_REPLACE_HISTORY ) << 16)) || |
8599 | aLoadState->LoadType() == LOAD_HISTORY || |
8600 | aLoadState->LoadType() == LOAD_LINK)) { |
8601 | return false; |
8602 | } |
8603 | |
8604 | nsCOMPtr<nsIURI> currentURI = mCurrentURI; |
8605 | |
8606 | nsresult rvURINew = aLoadState->URI()->GetRef(aState.mNewHash); |
8607 | if (NS_SUCCEEDED(rvURINew)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rvURINew)), 1)))) { |
8608 | rvURINew = aLoadState->URI()->GetHasRef(&aState.mNewURIHasRef); |
8609 | } |
8610 | |
8611 | if (currentURI && NS_SUCCEEDED(rvURINew)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rvURINew)), 1)))) { |
8612 | nsresult rvURIOld = currentURI->GetRef(aState.mCurrentHash); |
8613 | if (NS_SUCCEEDED(rvURIOld)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rvURIOld)), 1)))) { |
8614 | rvURIOld = currentURI->GetHasRef(&aState.mCurrentURIHasRef); |
8615 | } |
8616 | if (NS_SUCCEEDED(rvURIOld)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rvURIOld)), 1)))) { |
8617 | if (NS_FAILED(currentURI->EqualsExceptRef(aLoadState->URI(),((bool)(__builtin_expect(!!(NS_FAILED_impl(currentURI->EqualsExceptRef (aLoadState->URI(), &aState.mSameExceptHashes))), 0))) |
8618 | &aState.mSameExceptHashes))((bool)(__builtin_expect(!!(NS_FAILED_impl(currentURI->EqualsExceptRef (aLoadState->URI(), &aState.mSameExceptHashes))), 0)))) { |
8619 | aState.mSameExceptHashes = false; |
8620 | } |
8621 | } |
8622 | } |
8623 | |
8624 | if (!aState.mSameExceptHashes && currentURI && NS_SUCCEEDED(rvURINew)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rvURINew)), 1)))) { |
8625 | // Maybe aLoadState->URI() came from the exposable form of currentURI? |
8626 | nsCOMPtr<nsIURI> currentExposableURI = |
8627 | nsIOService::CreateExposableURI(currentURI); |
8628 | nsresult rvURIOld = currentExposableURI->GetRef(aState.mCurrentHash); |
8629 | if (NS_SUCCEEDED(rvURIOld)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rvURIOld)), 1)))) { |
8630 | rvURIOld = currentExposableURI->GetHasRef(&aState.mCurrentURIHasRef); |
8631 | } |
8632 | if (NS_SUCCEEDED(rvURIOld)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rvURIOld)), 1)))) { |
8633 | if (NS_FAILED(currentExposableURI->EqualsExceptRef(((bool)(__builtin_expect(!!(NS_FAILED_impl(currentExposableURI ->EqualsExceptRef( aLoadState->URI(), &aState.mSameExceptHashes ))), 0))) |
8634 | aLoadState->URI(), &aState.mSameExceptHashes))((bool)(__builtin_expect(!!(NS_FAILED_impl(currentExposableURI ->EqualsExceptRef( aLoadState->URI(), &aState.mSameExceptHashes ))), 0)))) { |
8635 | aState.mSameExceptHashes = false; |
8636 | } |
8637 | // HTTPS-Only Mode upgrades schemes from http to https in Necko, hence we |
8638 | // have to perform a special check here to avoid an actual navigation. If |
8639 | // HTTPS-Only Mode is enabled and the two URIs are same-origin (modulo the |
8640 | // fact that the new URI is currently http), then set mSameExceptHashes to |
8641 | // true and only perform a fragment navigation. |
8642 | if (!aState.mSameExceptHashes) { |
8643 | if (nsCOMPtr<nsIChannel> docChannel = GetCurrentDocChannel()) { |
8644 | nsCOMPtr<nsILoadInfo> docLoadInfo = docChannel->LoadInfo(); |
8645 | if (!docLoadInfo->GetLoadErrorPage() && |
8646 | nsHTTPSOnlyUtils::IsEqualURIExceptSchemeAndRef( |
8647 | currentExposableURI, aLoadState->URI(), docLoadInfo)) { |
8648 | uint32_t status = docLoadInfo->GetHttpsOnlyStatus(); |
8649 | if (status & (nsILoadInfo::HTTPS_ONLY_UPGRADED_LISTENER_REGISTERED | |
8650 | nsILoadInfo::HTTPS_ONLY_UPGRADED_HTTPS_FIRST)) { |
8651 | // At this point the requested URI is for sure a fragment |
8652 | // navigation via HTTP and HTTPS-Only mode or HTTPS-First is |
8653 | // enabled. Also it is not interfering the upgrade order of |
8654 | // https://searchfox.org/mozilla-central/source/netwerk/base/nsNetUtil.cpp#2948-2953. |
8655 | // Since we are on an HTTPS site the fragment |
8656 | // navigation should also be an HTTPS. |
8657 | // For that reason we should upgrade the URI to HTTPS. |
8658 | aState.mSecureUpgradeURI = true; |
8659 | aState.mSameExceptHashes = true; |
8660 | } |
8661 | } |
8662 | } |
8663 | } |
8664 | } |
8665 | } |
8666 | |
8667 | if (mozilla::SessionHistoryInParent()) { |
8668 | if (mActiveEntry && aLoadState->LoadIsFromSessionHistory()) { |
8669 | aState.mHistoryNavBetweenSameDoc = mActiveEntry->SharesDocumentWith( |
8670 | aLoadState->GetLoadingSessionHistoryInfo()->mInfo); |
8671 | } |
8672 | 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) |
8673 | ("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) |
8674 | 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); |
8675 | } else { |
8676 | if (mOSHE && aLoadState->LoadIsFromSessionHistory()) { |
8677 | // We're doing a history load. |
8678 | |
8679 | mOSHE->SharesDocumentWith(aLoadState->SHEntry(), |
8680 | &aState.mHistoryNavBetweenSameDoc); |
8681 | } |
8682 | } |
8683 | |
8684 | // A same document navigation happens when we navigate between two SHEntries |
8685 | // for the same document. We do a same document navigation under two |
8686 | // circumstances. Either |
8687 | // |
8688 | // a) we're navigating between two different SHEntries which share a |
8689 | // document, or |
8690 | // |
8691 | // b) we're navigating to a new shentry whose URI differs from the |
8692 | // current URI only in its hash, the new hash is non-empty, and |
8693 | // we're not doing a POST. |
8694 | // |
8695 | // The restriction that the SHEntries in (a) must be different ensures |
8696 | // that history.go(0) and the like trigger full refreshes, rather than |
8697 | // same document navigations. |
8698 | if (!mozilla::SessionHistoryInParent()) { |
8699 | bool doSameDocumentNavigation = |
8700 | (aState.mHistoryNavBetweenSameDoc && mOSHE != aLoadState->SHEntry()) || |
8701 | (!aLoadState->SHEntry() && !aLoadState->PostDataStream() && |
8702 | aState.mSameExceptHashes && aState.mNewURIHasRef); |
8703 | 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) |
8704 | ("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) |
8705 | 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); |
8706 | return doSameDocumentNavigation; |
8707 | } |
8708 | |
8709 | if (aState.mHistoryNavBetweenSameDoc && |
8710 | !aLoadState->GetLoadingSessionHistoryInfo()->mLoadingCurrentEntry) { |
8711 | return true; |
8712 | } |
8713 | |
8714 | 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) |
8715 | 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) |
8716 | ("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) |
8717 | "!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) |
8718 | 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) |
8719 | !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) |
8720 | 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) |
8721 | 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); |
8722 | return !aLoadState->LoadIsFromSessionHistory() && |
8723 | !aLoadState->PostDataStream() && aState.mSameExceptHashes && |
8724 | aState.mNewURIHasRef; |
8725 | } |
8726 | |
8727 | nsresult nsDocShell::HandleSameDocumentNavigation( |
8728 | nsDocShellLoadState* aLoadState, SameDocumentNavigationState& aState, |
8729 | bool& aSameDocument) { |
8730 | aSameDocument = true; |
8731 | #ifdef DEBUG1 |
8732 | SameDocumentNavigationState state; |
8733 | 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" , 8733); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsSameDocumentNavigation(aLoadState, state)" ")"); do { *((volatile int*)__null) = 8733; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
8734 | #endif |
8735 | |
8736 | 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) |
8737 | ("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) |
8738 | 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) |
8739 | 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); |
8740 | |
8741 | RefPtr<Document> doc = GetDocument(); |
8742 | 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" , 8742); return NS_ERROR_FAILURE; } } while (false); |
8743 | doc->DoNotifyPossibleTitleChange(); |
8744 | |
8745 | nsCOMPtr<nsIURI> currentURI = mCurrentURI; |
8746 | |
8747 | // We need to upgrade the new URI from http: to https: |
8748 | nsCOMPtr<nsIURI> newURI = aLoadState->URI(); |
8749 | if (aState.mSecureUpgradeURI) { |
8750 | 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); |
8751 | 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) |
8752 | ("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); |
8753 | } |
8754 | |
8755 | if (StaticPrefs::dom_security_setdocumenturi()) { |
8756 | // check if aLoadState->URI(), principalURI, mCurrentURI are same origin |
8757 | // skip handling otherwise |
8758 | nsCOMPtr<nsIPrincipal> origPrincipal = doc->NodePrincipal(); |
8759 | nsCOMPtr<nsIURI> principalURI = origPrincipal->GetURI(); |
8760 | if (origPrincipal->GetIsNullPrincipal()) { |
8761 | nsCOMPtr<nsIPrincipal> precursor = origPrincipal->GetPrecursorPrincipal(); |
8762 | if (precursor) { |
8763 | principalURI = precursor->GetURI(); |
8764 | } |
8765 | } |
8766 | |
8767 | auto isLoadableViaInternet = [](nsIURI* uri) { |
8768 | return (uri && (net::SchemeIsHTTP(uri) || net::SchemeIsHTTPS(uri))); |
8769 | }; |
8770 | |
8771 | if (isLoadableViaInternet(principalURI) && |
8772 | isLoadableViaInternet(mCurrentURI) && isLoadableViaInternet(newURI)) { |
8773 | nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager(); |
8774 | if (!NS_SUCCEEDED(((bool)(__builtin_expect(!!(!NS_FAILED_impl(ssm->CheckSameOriginURI (newURI, principalURI, false, false))), 1))) |
8775 | ssm->CheckSameOriginURI(newURI, principalURI, false, false))((bool)(__builtin_expect(!!(!NS_FAILED_impl(ssm->CheckSameOriginURI (newURI, principalURI, false, false))), 1))) || |
8776 | !NS_SUCCEEDED(ssm->CheckSameOriginURI(mCurrentURI, principalURI,((bool)(__builtin_expect(!!(!NS_FAILED_impl(ssm->CheckSameOriginURI (mCurrentURI, principalURI, false, false))), 1))) |
8777 | false, false))((bool)(__builtin_expect(!!(!NS_FAILED_impl(ssm->CheckSameOriginURI (mCurrentURI, principalURI, false, false))), 1)))) { |
8778 | 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) |
8779 | ("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) |
8780 | "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) |
8781 | 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); |
8782 | aSameDocument = false; |
8783 | return NS_OK; |
8784 | } |
8785 | } |
8786 | } |
8787 | |
8788 | #ifdef DEBUG1 |
8789 | if (aState.mSameExceptHashes) { |
8790 | bool sameExceptHashes = false; |
8791 | currentURI->EqualsExceptRef(newURI, &sameExceptHashes); |
8792 | 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" , 8792); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sameExceptHashes" ")"); do { *((volatile int*)__null) = 8792; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
8793 | } |
8794 | #endif |
8795 | |
8796 | // Save the position of the scrollers. |
8797 | nsPoint scrollPos = GetCurScrollPos(); |
8798 | |
8799 | // Reset mLoadType to its original value once we exit this block, because this |
8800 | // same document navigation might have started after a normal, network load, |
8801 | // and we don't want to clobber its load type. See bug 737307. |
8802 | AutoRestore<uint32_t> loadTypeResetter(mLoadType); |
8803 | |
8804 | // If a non-same-document-navigation (i.e., a network load) is pending, make |
8805 | // this a replacement load, so that we don't add a SHEntry here and the |
8806 | // network load goes into the SHEntry it expects to. |
8807 | if (JustStartedNetworkLoad() && (aLoadState->LoadType() & LOAD_CMD_NORMAL)) { |
8808 | mLoadType = LOAD_NORMAL_REPLACE; |
8809 | } else { |
8810 | mLoadType = aLoadState->LoadType(); |
8811 | } |
8812 | |
8813 | mURIResultedInDocument = true; |
8814 | |
8815 | nsCOMPtr<nsISHEntry> oldLSHE = mLSHE; |
8816 | |
8817 | // we need to assign aLoadState->SHEntry() to mLSHE right here, so that on |
8818 | // History loads, SetCurrentURI() called from OnNewURI() will send proper |
8819 | // onLocationChange() notifications to the browser to update back/forward |
8820 | // buttons. |
8821 | SetHistoryEntryAndUpdateBC(Some<nsISHEntry*>(aLoadState->SHEntry()), |
8822 | Nothing()); |
8823 | UniquePtr<mozilla::dom::LoadingSessionHistoryInfo> oldLoadingEntry; |
8824 | mLoadingEntry.swap(oldLoadingEntry); |
8825 | if (aLoadState->GetLoadingSessionHistoryInfo()) { |
8826 | mLoadingEntry = MakeUnique<LoadingSessionHistoryInfo>( |
8827 | *aLoadState->GetLoadingSessionHistoryInfo()); |
8828 | mNeedToReportActiveAfterLoadingBecomesActive = false; |
8829 | } |
8830 | |
8831 | // Set the doc's URI according to the new history entry's URI. |
8832 | doc->SetDocumentURI(newURI); |
8833 | |
8834 | /* This is a anchor traversal within the same page. |
8835 | * call OnNewURI() so that, this traversal will be |
8836 | * recorded in session and global history. |
8837 | */ |
8838 | nsCOMPtr<nsIPrincipal> newURITriggeringPrincipal, newURIPrincipalToInherit, |
8839 | newURIPartitionedPrincipalToInherit; |
8840 | nsCOMPtr<nsIContentSecurityPolicy> newCsp; |
8841 | if (mozilla::SessionHistoryInParent() ? !!mActiveEntry : !!mOSHE) { |
8842 | if (mozilla::SessionHistoryInParent()) { |
8843 | newURITriggeringPrincipal = mActiveEntry->GetTriggeringPrincipal(); |
8844 | newURIPrincipalToInherit = mActiveEntry->GetPrincipalToInherit(); |
8845 | newURIPartitionedPrincipalToInherit = |
8846 | mActiveEntry->GetPartitionedPrincipalToInherit(); |
8847 | newCsp = mActiveEntry->GetCsp(); |
8848 | } else { |
8849 | newURITriggeringPrincipal = mOSHE->GetTriggeringPrincipal(); |
8850 | newURIPrincipalToInherit = mOSHE->GetPrincipalToInherit(); |
8851 | newURIPartitionedPrincipalToInherit = |
8852 | mOSHE->GetPartitionedPrincipalToInherit(); |
8853 | newCsp = mOSHE->GetCsp(); |
8854 | } |
8855 | } else { |
8856 | newURITriggeringPrincipal = aLoadState->TriggeringPrincipal(); |
8857 | newURIPrincipalToInherit = doc->NodePrincipal(); |
8858 | newURIPartitionedPrincipalToInherit = doc->PartitionedPrincipal(); |
8859 | newCsp = doc->GetCsp(); |
8860 | } |
8861 | |
8862 | uint32_t locationChangeFlags = GetSameDocumentNavigationFlags(newURI); |
8863 | |
8864 | // Pass true for aCloneSHChildren, since we're not |
8865 | // changing documents here, so all of our subframes are |
8866 | // still relevant to the new session history entry. |
8867 | // |
8868 | // It also makes OnNewURI(...) set LOCATION_CHANGE_SAME_DOCUMENT |
8869 | // flag on firing onLocationChange(...). |
8870 | // Anyway, aCloneSHChildren param is simply reflecting |
8871 | // doSameDocumentNavigation in this scope. |
8872 | // |
8873 | // Note: we'll actually fire onLocationChange later, in order to preserve |
8874 | // ordering of HistoryCommit() in the parent vs onLocationChange (bug |
8875 | // 1668126) |
8876 | bool locationChangeNeeded = OnNewURI( |
8877 | newURI, nullptr, newURITriggeringPrincipal, newURIPrincipalToInherit, |
8878 | newURIPartitionedPrincipalToInherit, newCsp, true, true); |
8879 | |
8880 | nsCOMPtr<nsIInputStream> postData; |
8881 | uint32_t cacheKey = 0; |
8882 | |
8883 | bool scrollRestorationIsManual = false; |
8884 | if (!mozilla::SessionHistoryInParent()) { |
8885 | if (mOSHE) { |
8886 | /* save current position of scroller(s) (bug 59774) */ |
8887 | mOSHE->SetScrollPosition(scrollPos.x, scrollPos.y); |
8888 | scrollRestorationIsManual = mOSHE->GetScrollRestorationIsManual(); |
8889 | // Get the postdata and page ident from the current page, if |
8890 | // the new load is being done via normal means. Note that |
8891 | // "normal means" can be checked for just by checking for |
8892 | // LOAD_CMD_NORMAL, given the loadType and allowScroll check |
8893 | // above -- it filters out some LOAD_CMD_NORMAL cases that we |
8894 | // wouldn't want here. |
8895 | if (aLoadState->LoadType() & LOAD_CMD_NORMAL) { |
8896 | postData = mOSHE->GetPostData(); |
8897 | cacheKey = mOSHE->GetCacheKey(); |
8898 | } |
8899 | |
8900 | // Link our new SHEntry to the old SHEntry's back/forward |
8901 | // cache data, since the two SHEntries correspond to the |
8902 | // same document. |
8903 | if (mLSHE) { |
8904 | if (!aLoadState->LoadIsFromSessionHistory()) { |
8905 | // If we're not doing a history load, scroll restoration |
8906 | // should be inherited from the previous session history entry. |
8907 | SetScrollRestorationIsManualOnHistoryEntry(mLSHE, |
8908 | scrollRestorationIsManual); |
8909 | } |
8910 | mLSHE->AdoptBFCacheEntry(mOSHE); |
8911 | } |
8912 | } |
8913 | } else { |
8914 | if (mActiveEntry) { |
8915 | mActiveEntry->SetScrollPosition(scrollPos.x, scrollPos.y); |
8916 | if (mBrowsingContext) { |
8917 | CollectWireframe(); |
8918 | if (XRE_IsParentProcess()) { |
8919 | SessionHistoryEntry* entry = |
8920 | mBrowsingContext->Canonical()->GetActiveSessionHistoryEntry(); |
8921 | if (entry) { |
8922 | entry->SetScrollPosition(scrollPos.x, scrollPos.y); |
8923 | } |
8924 | } else { |
8925 | mozilla::Unused << ContentChild::GetSingleton() |
8926 | ->SendSessionHistoryEntryScrollPosition( |
8927 | mBrowsingContext, scrollPos.x, |
8928 | scrollPos.y); |
8929 | } |
8930 | } |
8931 | } |
8932 | if (mLoadingEntry) { |
8933 | if (!mLoadingEntry->mLoadIsFromSessionHistory) { |
8934 | // If we're not doing a history load, scroll restoration |
8935 | // should be inherited from the previous session history entry. |
8936 | // XXX This needs most probably tweaks once fragment navigation is |
8937 | // fixed to work with session-history-in-parent. |
8938 | SetScrollRestorationIsManualOnHistoryEntry(nullptr, |
8939 | scrollRestorationIsManual); |
8940 | } |
8941 | } |
8942 | } |
8943 | |
8944 | // If we're doing a history load, use its scroll restoration state. |
8945 | if (aLoadState->LoadIsFromSessionHistory()) { |
8946 | if (mozilla::SessionHistoryInParent()) { |
8947 | scrollRestorationIsManual = aLoadState->GetLoadingSessionHistoryInfo() |
8948 | ->mInfo.GetScrollRestorationIsManual(); |
8949 | } else { |
8950 | scrollRestorationIsManual = |
8951 | aLoadState->SHEntry()->GetScrollRestorationIsManual(); |
8952 | } |
8953 | } |
8954 | |
8955 | /* Assign mLSHE to mOSHE. This will either be a new entry created |
8956 | * by OnNewURI() for normal loads or aLoadState->SHEntry() for history |
8957 | * loads. |
8958 | */ |
8959 | if (!mozilla::SessionHistoryInParent()) { |
8960 | if (mLSHE) { |
8961 | SetHistoryEntryAndUpdateBC(Nothing(), Some<nsISHEntry*>(mLSHE)); |
8962 | // Save the postData obtained from the previous page |
8963 | // in to the session history entry created for the |
8964 | // anchor page, so that any history load of the anchor |
8965 | // page will restore the appropriate postData. |
8966 | if (postData) { |
8967 | mOSHE->SetPostData(postData); |
8968 | } |
8969 | |
8970 | // Make sure we won't just repost without hitting the |
8971 | // cache first |
8972 | if (cacheKey != 0) { |
8973 | mOSHE->SetCacheKey(cacheKey); |
8974 | } |
8975 | } |
8976 | |
8977 | /* Set the title for the SH entry for this target url so that |
8978 | * SH menus in go/back/forward buttons won't be empty for this. |
8979 | * Note, this happens on mOSHE (and mActiveEntry in the future) because of |
8980 | * the code above. |
8981 | * Note, when session history lives in the parent process, this does not |
8982 | * update the title there. |
8983 | */ |
8984 | SetTitleOnHistoryEntry(false); |
8985 | } else { |
8986 | if (aLoadState->LoadIsFromSessionHistory()) { |
8987 | 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) |
8988 | 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) |
8989 | ("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) |
8990 | "%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) |
8991 | 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); |
8992 | |
8993 | nsCOMPtr<nsILayoutHistoryState> currentLayoutHistoryState; |
8994 | if (mActiveEntry) { |
8995 | currentLayoutHistoryState = mActiveEntry->GetLayoutHistoryState(); |
8996 | } |
8997 | |
8998 | UniquePtr<SessionHistoryInfo> previousActiveEntry(mActiveEntry.release()); |
8999 | mActiveEntry = MakeUnique<SessionHistoryInfo>(mLoadingEntry->mInfo); |
9000 | if (currentLayoutHistoryState) { |
9001 | // Restore the existing nsILayoutHistoryState object, since it is |
9002 | // possibly being used by the layout. When doing a new load, the |
9003 | // shared state is copied from the existing active entry, so this |
9004 | // special case is needed only with the history loads. |
9005 | mActiveEntry->SetLayoutHistoryState(currentLayoutHistoryState); |
9006 | } |
9007 | |
9008 | if (cacheKey != 0) { |
9009 | mActiveEntry->SetCacheKey(cacheKey); |
9010 | } |
9011 | // We're passing in mCurrentURI, which could be null. SessionHistoryCommit |
9012 | // does require a non-null uri if this is for a refresh load of the same |
9013 | // URI, but in that case mCurrentURI won't be null here. |
9014 | mBrowsingContext->SessionHistoryCommit( |
9015 | *mLoadingEntry, mLoadType, mCurrentURI, previousActiveEntry.get(), |
9016 | true, true, |
9017 | /* No expiration update on the same document loads*/ |
9018 | false, cacheKey); |
9019 | // FIXME Need to set postdata. |
9020 | |
9021 | // Set the title for the SH entry for this target url so that |
9022 | // SH menus in go/back/forward buttons won't be empty for this. |
9023 | // Note, when session history lives in the parent process, this does not |
9024 | // update the title there. |
9025 | SetTitleOnHistoryEntry(false); |
9026 | } else { |
9027 | Maybe<bool> scrollRestorationIsManual; |
9028 | if (mActiveEntry) { |
9029 | scrollRestorationIsManual.emplace( |
9030 | mActiveEntry->GetScrollRestorationIsManual()); |
9031 | |
9032 | // Get the postdata and page ident from the current page, if the new |
9033 | // load is being done via normal means. Note that "normal means" can be |
9034 | // checked for just by checking for LOAD_CMD_NORMAL, given the loadType |
9035 | // and allowScroll check above -- it filters out some LOAD_CMD_NORMAL |
9036 | // cases that we wouldn't want here. |
9037 | if (aLoadState->LoadType() & LOAD_CMD_NORMAL) { |
9038 | postData = mActiveEntry->GetPostData(); |
9039 | cacheKey = mActiveEntry->GetCacheKey(); |
9040 | } |
9041 | } |
9042 | |
9043 | 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) |
9044 | ("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) |
9045 | 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); |
9046 | if (mActiveEntry) { |
9047 | mActiveEntry = MakeUnique<SessionHistoryInfo>(*mActiveEntry, newURI); |
9048 | } else { |
9049 | mActiveEntry = MakeUnique<SessionHistoryInfo>( |
9050 | newURI, newURITriggeringPrincipal, newURIPrincipalToInherit, |
9051 | newURIPartitionedPrincipalToInherit, newCsp, mContentTypeHint); |
9052 | } |
9053 | |
9054 | // Save the postData obtained from the previous page in to the session |
9055 | // history entry created for the anchor page, so that any history load of |
9056 | // the anchor page will restore the appropriate postData. |
9057 | if (postData) { |
9058 | mActiveEntry->SetPostData(postData); |
9059 | } |
9060 | |
9061 | // Make sure we won't just repost without hitting the |
9062 | // cache first |
9063 | if (cacheKey != 0) { |
9064 | mActiveEntry->SetCacheKey(cacheKey); |
9065 | } |
9066 | |
9067 | // Set the title for the SH entry for this target url so that |
9068 | // SH menus in go/back/forward buttons won't be empty for this. |
9069 | mActiveEntry->SetTitle(mTitle); |
9070 | |
9071 | if (scrollRestorationIsManual.isSome()) { |
9072 | mActiveEntry->SetScrollRestorationIsManual( |
9073 | scrollRestorationIsManual.value()); |
9074 | } |
9075 | |
9076 | if (LOAD_TYPE_HAS_FLAGS(mLoadType, LOAD_FLAGS_REPLACE_HISTORY)((mLoadType) & ((LOAD_FLAGS_REPLACE_HISTORY) << 16) )) { |
9077 | mBrowsingContext->ReplaceActiveSessionHistoryEntry(mActiveEntry.get()); |
9078 | } else { |
9079 | mBrowsingContext->IncrementHistoryEntryCountForBrowsingContext(); |
9080 | // FIXME We should probably just compute mChildOffset in the parent |
9081 | // instead of passing it over IPC here. |
9082 | mBrowsingContext->SetActiveSessionHistoryEntry( |
9083 | Some(scrollPos), mActiveEntry.get(), mLoadType, cacheKey); |
9084 | // FIXME Do we need to update mPreviousEntryIndex and mLoadedEntryIndex? |
9085 | } |
9086 | } |
9087 | } |
9088 | |
9089 | if (locationChangeNeeded) { |
9090 | FireOnLocationChange(this, nullptr, newURI, locationChangeFlags); |
9091 | } |
9092 | |
9093 | /* Restore the original LSHE if we were loading something |
9094 | * while same document navigation was initiated. |
9095 | */ |
9096 | SetHistoryEntryAndUpdateBC(Some<nsISHEntry*>(oldLSHE), Nothing()); |
9097 | mLoadingEntry.swap(oldLoadingEntry); |
9098 | |
9099 | /* Set the title for the Global History entry for this anchor url. |
9100 | */ |
9101 | UpdateGlobalHistoryTitle(newURI); |
9102 | |
9103 | SetDocCurrentStateObj(mOSHE, mActiveEntry.get()); |
9104 | |
9105 | // Inform the favicon service that the favicon for oldURI also |
9106 | // applies to newURI. |
9107 | CopyFavicon(currentURI, newURI, UsePrivateBrowsing()); |
9108 | |
9109 | RefPtr<nsGlobalWindowOuter> scriptGlobal = mScriptGlobal; |
9110 | nsCOMPtr<nsPIDOMWindowInner> win = |
9111 | scriptGlobal ? scriptGlobal->GetCurrentInnerWindow() : nullptr; |
9112 | |
9113 | // ScrollToAnchor doesn't necessarily cause us to scroll the window; |
9114 | // the function decides whether a scroll is appropriate based on the |
9115 | // arguments it receives. But even if we don't end up scrolling, |
9116 | // ScrollToAnchor performs other important tasks, such as informing |
9117 | // the presShell that we have a new hash. See bug 680257. |
9118 | nsresult rv = ScrollToAnchor(aState.mCurrentURIHasRef, aState.mNewURIHasRef, |
9119 | aState.mNewHash, aLoadState->LoadType()); |
9120 | 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" , 9120); return rv; } } while (false); |
9121 | |
9122 | /* restore previous position of scroller(s), if we're moving |
9123 | * back in history (bug 59774) |
9124 | */ |
9125 | nscoord bx = 0; |
9126 | nscoord by = 0; |
9127 | bool needsScrollPosUpdate = false; |
9128 | if ((mozilla::SessionHistoryInParent() ? !!mActiveEntry : !!mOSHE) && |
9129 | (aLoadState->LoadType() == LOAD_HISTORY || |
9130 | aLoadState->LoadType() == LOAD_RELOAD_NORMAL) && |
9131 | !scrollRestorationIsManual) { |
9132 | needsScrollPosUpdate = true; |
9133 | if (mozilla::SessionHistoryInParent()) { |
9134 | mActiveEntry->GetScrollPosition(&bx, &by); |
9135 | } else { |
9136 | mOSHE->GetScrollPosition(&bx, &by); |
9137 | } |
9138 | } |
9139 | |
9140 | // Dispatch the popstate and hashchange events, as appropriate. |
9141 | // |
9142 | // The event dispatch below can cause us to re-enter script and |
9143 | // destroy the docshell, nulling out mScriptGlobal. Hold a stack |
9144 | // reference to avoid null derefs. See bug 914521. |
9145 | if (win) { |
9146 | // Fire a hashchange event URIs differ, and only in their hashes. |
9147 | bool doHashchange = aState.mSameExceptHashes && |
9148 | (aState.mCurrentURIHasRef != aState.mNewURIHasRef || |
9149 | !aState.mCurrentHash.Equals(aState.mNewHash)); |
9150 | |
9151 | if (aState.mHistoryNavBetweenSameDoc || doHashchange) { |
9152 | win->DispatchSyncPopState(); |
9153 | } |
9154 | |
9155 | if (needsScrollPosUpdate && win->HasActiveDocument()) { |
9156 | SetCurScrollPosEx(bx, by); |
9157 | } |
9158 | |
9159 | if (doHashchange) { |
9160 | // Note that currentURI hasn't changed because it's on the |
9161 | // stack, so we can just use it directly as the old URI. |
9162 | win->DispatchAsyncHashchange(currentURI, newURI); |
9163 | } |
9164 | } |
9165 | |
9166 | return NS_OK; |
9167 | } |
9168 | |
9169 | static bool NavigationShouldTakeFocus(nsDocShell* aDocShell, |
9170 | nsDocShellLoadState* aLoadState) { |
9171 | if (!aLoadState->AllowFocusMove()) { |
9172 | return false; |
9173 | } |
9174 | if (!aLoadState->HasValidUserGestureActivation()) { |
9175 | return false; |
9176 | } |
9177 | const auto& sourceBC = aLoadState->SourceBrowsingContext(); |
9178 | if (!sourceBC || !sourceBC->IsActive()) { |
9179 | // If the navigation didn't come from a foreground tab, then we don't steal |
9180 | // focus. |
9181 | return false; |
9182 | } |
9183 | auto* bc = aDocShell->GetBrowsingContext(); |
9184 | if (sourceBC.get() == bc) { |
9185 | // If it comes from the same tab / frame, don't steal focus either. |
9186 | return false; |
9187 | } |
9188 | auto* fm = nsFocusManager::GetFocusManager(); |
9189 | if (fm && bc->IsActive() && fm->IsInActiveWindow(bc)) { |
9190 | // If we're already on the foreground tab of the foreground window, then we |
9191 | // don't need to do this. This helps to e.g. not steal focus from the |
9192 | // browser chrome unnecessarily. |
9193 | return false; |
9194 | } |
9195 | if (auto* doc = aDocShell->GetExtantDocument()) { |
9196 | if (doc->IsInitialDocument()) { |
9197 | // If we're the initial load for the browsing context, the browser |
9198 | // chrome determines what to focus. This is important because the |
9199 | // browser chrome may want to e.g focus the url-bar |
9200 | return false; |
9201 | } |
9202 | } |
9203 | // Take loadDivertedInBackground into account so the behavior would be the |
9204 | // same as how the tab first opened. |
9205 | return !Preferences::GetBool("browser.tabs.loadDivertedInBackground", false); |
9206 | } |
9207 | |
9208 | uint32_t nsDocShell::GetLoadTypeForFormSubmission( |
9209 | BrowsingContext* aTargetBC, nsDocShellLoadState* aLoadState) { |
9210 | 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" , 9210); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->IsFormSubmission()" ")"); do { *((volatile int*)__null) = 9210; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
9211 | |
9212 | // https://html.spec.whatwg.org/#form-submission-algorithm |
9213 | // 22. Let historyHandling be "push". |
9214 | // 23. If form document equals targetNavigable's active document, and |
9215 | // form document has not yet completely loaded, then set |
9216 | // historyHandling to "replace". |
9217 | return GetBrowsingContext() == aTargetBC && !mEODForCurrentDocument |
9218 | ? LOAD_NORMAL_REPLACE |
9219 | : LOAD_LINK; |
9220 | } |
9221 | |
9222 | nsresult nsDocShell::InternalLoad(nsDocShellLoadState* aLoadState, |
9223 | Maybe<uint32_t> aCacheKey) { |
9224 | 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" , 9224); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState" ") (" "need a load state!" ")"); do { *((volatile int*)__null ) = 9224; __attribute__((nomerge)) ::abort(); } while (false) ; } } while (false); |
9225 | 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" , 9226); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->TriggeringPrincipal()" ") (" "need a valid TriggeringPrincipal" ")"); do { *((volatile int*)__null) = 9226; __attribute__((nomerge)) ::abort(); } while (false); } } while (false) |
9226 | "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" , 9226); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->TriggeringPrincipal()" ") (" "need a valid TriggeringPrincipal" ")"); do { *((volatile int*)__null) = 9226; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
9227 | |
9228 | if (!aLoadState->TriggeringPrincipal()) { |
9229 | 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" , 9229); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "InternalLoad needs a valid triggeringPrincipal" ")"); do { * ((volatile int*)__null) = 9229; __attribute__((nomerge)) ::abort (); } while (false); } } while (false); |
9230 | return NS_ERROR_FAILURE; |
9231 | } |
9232 | 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" , 9232)) { |
9233 | return NS_ERROR_NOT_AVAILABLE; |
9234 | } |
9235 | |
9236 | const bool shouldTakeFocus = NavigationShouldTakeFocus(this, aLoadState); |
9237 | |
9238 | mOriginalUriString.Truncate(); |
9239 | |
9240 | 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) |
9241 | ("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) |
9242 | 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); |
9243 | |
9244 | 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" , 9244); return NS_ERROR_INVALID_ARG; } } while (false); |
9245 | |
9246 | // Cancel loads coming from Docshells that are being destroyed. |
9247 | if (mIsBeingDestroyed) { |
9248 | return NS_ERROR_NOT_AVAILABLE; |
9249 | } |
9250 | |
9251 | nsresult rv = EnsureScriptEnvironment(); |
9252 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
9253 | return rv; |
9254 | } |
9255 | |
9256 | // If we have a target to move to, do that now. |
9257 | if (!aLoadState->Target().IsEmpty()) { |
9258 | return PerformRetargeting(aLoadState); |
9259 | } |
9260 | |
9261 | // This is the non-retargeting load path, we've already set the right loadtype |
9262 | // for form submissions in nsDocShell::OnLinkClickSync. |
9263 | if (aLoadState->TargetBrowsingContext().IsNull()) { |
9264 | aLoadState->SetTargetBrowsingContext(GetBrowsingContext()); |
9265 | } |
9266 | |
9267 | 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" , 9269); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "aLoadState->TargetBrowsingContext() == GetBrowsingContext()" ") (" "Load must be targeting this BrowsingContext" ")"); do { *((volatile int*)__null) = 9269; __attribute__((nomerge)) :: abort(); } while (false); } } while (false) |
9268 | 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" , 9269); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "aLoadState->TargetBrowsingContext() == GetBrowsingContext()" ") (" "Load must be targeting this BrowsingContext" ")"); do { *((volatile int*)__null) = 9269; __attribute__((nomerge)) :: abort(); } while (false); } } while (false) |
9269 | "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" , 9269); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "aLoadState->TargetBrowsingContext() == GetBrowsingContext()" ") (" "Load must be targeting this BrowsingContext" ")"); do { *((volatile int*)__null) = 9269; __attribute__((nomerge)) :: abort(); } while (false); } } while (false); |
9270 | |
9271 | MOZ_TRY(CheckDisallowedJavascriptLoad(aLoadState))do { auto mozTryTempResult_ = ::mozilla::ToResult(CheckDisallowedJavascriptLoad (aLoadState)); if ((__builtin_expect(!!(mozTryTempResult_.isErr ()), 0))) { return mozTryTempResult_.propagateErr(); } } while (0); |
9272 | |
9273 | // If we don't have a target, we're loading into ourselves, and our load |
9274 | // delegate may want to intercept that load. |
9275 | SameDocumentNavigationState sameDocumentNavigationState; |
9276 | bool sameDocument = |
9277 | IsSameDocumentNavigation(aLoadState, sameDocumentNavigationState) && |
9278 | !aLoadState->GetPendingRedirectedChannel(); |
9279 | |
9280 | // Note: We do this check both here and in BrowsingContext:: |
9281 | // LoadURI/InternalLoad, since document-specific sandbox flags are only |
9282 | // available in the process triggering the load, and we don't want the target |
9283 | // process to have to trust the triggering process to do the appropriate |
9284 | // checks for the BrowsingContext's sandbox flags. |
9285 | MOZ_TRY(mBrowsingContext->CheckSandboxFlags(aLoadState))do { auto mozTryTempResult_ = ::mozilla::ToResult(mBrowsingContext ->CheckSandboxFlags(aLoadState)); if ((__builtin_expect(!! (mozTryTempResult_.isErr()), 0))) { return mozTryTempResult_. propagateErr(); } } while (0); |
9286 | |
9287 | 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" , 9287); return NS_ERROR_UNEXPECTED; } } while (false); |
9288 | |
9289 | rv = CheckLoadingPermissions(); |
9290 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
9291 | return rv; |
9292 | } |
9293 | |
9294 | if (mFiredUnloadEvent) { |
9295 | if (IsOKToLoadURI(aLoadState->URI())) { |
9296 | 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" , 9297); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->Target().IsEmpty()" ") (" "Shouldn't have a window target here!" ")"); do { *((volatile int*)__null) = 9297; __attribute__((nomerge)) ::abort(); } while (false); } } while (false) |
9297 | "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" , 9297); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->Target().IsEmpty()" ") (" "Shouldn't have a window target here!" ")"); do { *((volatile int*)__null) = 9297; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
9298 | |
9299 | // If this is a replace load, make whatever load triggered |
9300 | // the unload event also a replace load, so we don't |
9301 | // create extra history entries. |
9302 | if (LOAD_TYPE_HAS_FLAGS(aLoadState->LoadType(),((aLoadState->LoadType()) & ((LOAD_FLAGS_REPLACE_HISTORY ) << 16)) |
9303 | LOAD_FLAGS_REPLACE_HISTORY)((aLoadState->LoadType()) & ((LOAD_FLAGS_REPLACE_HISTORY ) << 16))) { |
9304 | mLoadType = LOAD_NORMAL_REPLACE; |
9305 | } |
9306 | |
9307 | // Do this asynchronously |
9308 | nsCOMPtr<nsIRunnable> ev = new InternalLoadEvent(this, aLoadState); |
9309 | return Dispatch(ev.forget()); |
9310 | } |
9311 | |
9312 | // Just ignore this load attempt |
9313 | return NS_OK; |
9314 | } |
9315 | |
9316 | // If we are loading a URI that should inherit a security context (basically |
9317 | // javascript: at this point), and the caller has said that principal |
9318 | // inheritance is allowed, there are a few possible cases: |
9319 | // |
9320 | // 1) We are provided with the principal to inherit. In that case, we just use |
9321 | // it. |
9322 | // |
9323 | // 2) The load is coming from some other application. In this case we don't |
9324 | // want to inherit from whatever document we have loaded now, since the |
9325 | // load is unrelated to it. |
9326 | // |
9327 | // 3) It's a load from our application, but does not provide an explicit |
9328 | // principal to inherit. In that case, we want to inherit the principal of |
9329 | // our current document, or of our parent document (if any) if we don't |
9330 | // have a current document. |
9331 | { |
9332 | bool inherits; |
9333 | |
9334 | if (!aLoadState->HasLoadFlags(LOAD_FLAGS_FROM_EXTERNAL) && |
9335 | !aLoadState->PrincipalToInherit() && |
9336 | (aLoadState->HasInternalLoadFlags( |
9337 | INTERNAL_LOAD_FLAGS_INHERIT_PRINCIPAL)) && |
9338 | NS_SUCCEEDED(nsContentUtils::URIInheritsSecurityContext(((bool)(__builtin_expect(!!(!NS_FAILED_impl(nsContentUtils::URIInheritsSecurityContext ( aLoadState->URI(), &inherits))), 1))) |
9339 | aLoadState->URI(), &inherits))((bool)(__builtin_expect(!!(!NS_FAILED_impl(nsContentUtils::URIInheritsSecurityContext ( aLoadState->URI(), &inherits))), 1))) && |
9340 | inherits) { |
9341 | aLoadState->SetPrincipalToInherit(GetInheritedPrincipal(true)); |
9342 | } |
9343 | // If principalToInherit is still null (e.g. if some of the conditions of |
9344 | // were not satisfied), then no inheritance of any sort will happen: the |
9345 | // load will just get a principal based on the URI being loaded. |
9346 | } |
9347 | |
9348 | // If this docshell is owned by a frameloader, make sure to cancel |
9349 | // possible frameloader initialization before loading a new page. |
9350 | nsCOMPtr<nsIDocShellTreeItem> parent = GetInProcessParentDocshell(); |
9351 | if (parent) { |
9352 | RefPtr<Document> doc = parent->GetDocument(); |
9353 | if (doc) { |
9354 | doc->TryCancelFrameLoaderInitialization(this); |
9355 | } |
9356 | } |
9357 | |
9358 | // Before going any further vet loads initiated by external programs. |
9359 | if (aLoadState->HasLoadFlags(LOAD_FLAGS_FROM_EXTERNAL)) { |
9360 | 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" , 9360); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "aLoadState->LoadType() == LOAD_NORMAL" ")"); do { *((volatile int*)__null) = 9360; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
9361 | |
9362 | // Disallow external chrome: loads targetted at content windows |
9363 | if (SchemeIsChrome(aLoadState->URI())) { |
9364 | 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" , 9364); |
9365 | return NS_ERROR_FAILURE; |
9366 | } |
9367 | |
9368 | // clear the decks to prevent context bleed-through (bug 298255) |
9369 | rv = CreateAboutBlankDocumentViewer(nullptr, nullptr, nullptr, nullptr, |
9370 | /* aIsInitialDocument */ false); |
9371 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
9372 | return NS_ERROR_FAILURE; |
9373 | } |
9374 | } |
9375 | |
9376 | mAllowKeywordFixup = aLoadState->HasInternalLoadFlags( |
9377 | INTERNAL_LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP); |
9378 | mURIResultedInDocument = false; // reset the clock... |
9379 | |
9380 | // See if this is actually a load between two history entries for the same |
9381 | // document. If the process fails, or if we successfully navigate within the |
9382 | // same document, return. |
9383 | if (sameDocument) { |
9384 | nsresult rv = HandleSameDocumentNavigation( |
9385 | aLoadState, sameDocumentNavigationState, sameDocument); |
9386 | 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" , 9386); return rv; } } while (false); |
9387 | if (shouldTakeFocus) { |
9388 | mBrowsingContext->Focus(CallerType::System, IgnoreErrors()); |
9389 | } |
9390 | if (sameDocument) { |
9391 | return rv; |
9392 | } |
9393 | } |
9394 | |
9395 | // mDocumentViewer->PermitUnload can destroy |this| docShell, which |
9396 | // causes the next call of CanSavePresentation to crash. |
9397 | // Hold onto |this| until we return, to prevent a crash from happening. |
9398 | // (bug#331040) |
9399 | nsCOMPtr<nsIDocShell> kungFuDeathGrip(this); |
9400 | |
9401 | // Don't init timing for javascript:, since it generally doesn't |
9402 | // actually start a load or anything. If it does, we'll init |
9403 | // timing then, from OnStateChange. |
9404 | |
9405 | // XXXbz mTiming should know what channel it's for, so we don't |
9406 | // need this hackery. |
9407 | bool toBeReset = false; |
9408 | bool isJavaScript = SchemeIsJavascript(aLoadState->URI()); |
9409 | |
9410 | if (!isJavaScript) { |
9411 | toBeReset = MaybeInitTiming(); |
9412 | } |
9413 | bool isNotDownload = aLoadState->FileName().IsVoid(); |
9414 | if (mTiming && isNotDownload) { |
9415 | mTiming->NotifyBeforeUnload(); |
9416 | } |
9417 | // Check if the page doesn't want to be unloaded. The javascript: |
9418 | // protocol handler deals with this for javascript: URLs. |
9419 | if (!isJavaScript && isNotDownload && |
9420 | !aLoadState->NotifiedBeforeUnloadListeners() && mDocumentViewer) { |
9421 | bool okToUnload; |
9422 | |
9423 | // Check if request is exempted from HTTPSOnlyMode and if https-first is |
9424 | // enabled, if so it means: |
9425 | // * https-first failed to upgrade request to https |
9426 | // * we already asked for permission to unload and the user accepted |
9427 | // otherwise we wouldn't be here. |
9428 | bool isPrivateWin = GetOriginAttributes().mPrivateBrowsingId > 0; |
9429 | bool isHistoryOrReload = false; |
9430 | uint32_t loadType = aLoadState->LoadType(); |
9431 | |
9432 | // Check if request is a reload. |
9433 | if (loadType == LOAD_RELOAD_NORMAL || |
9434 | loadType == LOAD_RELOAD_BYPASS_CACHE || |
9435 | loadType == LOAD_RELOAD_BYPASS_PROXY || |
9436 | loadType == LOAD_RELOAD_BYPASS_PROXY_AND_CACHE || |
9437 | loadType == LOAD_HISTORY) { |
9438 | isHistoryOrReload = true; |
9439 | } |
9440 | |
9441 | // If it isn't a reload, the request already failed to be upgraded and |
9442 | // https-first is enabled then don't ask the user again for permission to |
9443 | // unload and just unload. |
9444 | if (!isHistoryOrReload && aLoadState->IsExemptFromHTTPSFirstMode() && |
9445 | nsHTTPSOnlyUtils::IsHttpsFirstModeEnabled(isPrivateWin)) { |
9446 | rv = mDocumentViewer->PermitUnload( |
9447 | nsIDocumentViewer::PermitUnloadAction::eDontPromptAndUnload, |
9448 | &okToUnload); |
9449 | } else { |
9450 | rv = mDocumentViewer->PermitUnload(&okToUnload); |
9451 | } |
9452 | |
9453 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && !okToUnload) { |
9454 | // The user chose not to unload the page, interrupt the |
9455 | // load. |
9456 | MaybeResetInitTiming(toBeReset); |
9457 | return NS_OK; |
9458 | } |
9459 | } |
9460 | |
9461 | if (mTiming && isNotDownload) { |
9462 | mTiming->NotifyUnloadAccepted(mCurrentURI); |
9463 | } |
9464 | |
9465 | // In e10s, in the parent process, we refuse to load anything other than |
9466 | // "safe" resources that we ship or trust enough to give "special" URLs. |
9467 | // Similar check will be performed by the ParentProcessDocumentChannel if in |
9468 | // use. |
9469 | if (XRE_IsE10sParentProcess() && |
9470 | !DocumentChannel::CanUseDocumentChannel(aLoadState->URI()) && |
9471 | !CanLoadInParentProcess(aLoadState->URI())) { |
9472 | return NS_ERROR_FAILURE; |
9473 | } |
9474 | |
9475 | // Whenever a top-level browsing context is navigated, the user agent MUST |
9476 | // lock the orientation of the document to the document's default |
9477 | // orientation. We don't explicitly check for a top-level browsing context |
9478 | // here because orientation is only set on top-level browsing contexts. |
9479 | if (mBrowsingContext->GetOrientationLock() != hal::ScreenOrientation::None) { |
9480 | 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" , 9480); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mBrowsingContext->IsTop()" ")"); do { *((volatile int*)__null) = 9480; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
9481 | 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" , 9482); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false" ") (" "NS_SUCCEEDED(mBrowsingContext->SetOrientationLock(hal::ScreenOrientation::None))" ")"); do { *((volatile int*)__null) = 9482; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) |
9482 | 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" , 9482); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false" ") (" "NS_SUCCEEDED(mBrowsingContext->SetOrientationLock(hal::ScreenOrientation::None))" ")"); do { *((volatile int*)__null) = 9482; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); |
9483 | if (mBrowsingContext->IsActive()) { |
9484 | ScreenOrientation::UpdateActiveOrientationLock( |
9485 | hal::ScreenOrientation::None); |
9486 | } |
9487 | } |
9488 | |
9489 | // Check for saving the presentation here, before calling Stop(). |
9490 | // This is necessary so that we can catch any pending requests. |
9491 | // Since the new request has not been created yet, we pass null for the |
9492 | // new request parameter. |
9493 | // Also pass nullptr for the document, since it doesn't affect the return |
9494 | // value for our purposes here. |
9495 | bool savePresentation = |
9496 | CanSavePresentation(aLoadState->LoadType(), nullptr, nullptr, |
9497 | /* aReportBFCacheComboTelemetry */ true); |
9498 | |
9499 | // nsDocShell::CanSavePresentation is for non-SHIP version only. Do a |
9500 | // separate check for SHIP so that we know if there are ongoing requests |
9501 | // before calling Stop() below. |
9502 | if (mozilla::SessionHistoryInParent()) { |
9503 | Document* document = GetDocument(); |
9504 | uint32_t flags = 0; |
9505 | if (document && !document->CanSavePresentation(nullptr, flags, true)) { |
9506 | // This forces some flags into the WindowGlobalParent's mBFCacheStatus, |
9507 | // which we'll then use in CanonicalBrowsingContext::AllowedInBFCache, |
9508 | // and in particular we'll store BFCacheStatus::REQUEST if needed. |
9509 | // Also, we want to report all the flags to the parent process here (and |
9510 | // not just BFCacheStatus::NOT_ALLOWED), so that it can update the |
9511 | // telemetry data correctly. |
9512 | document->DisallowBFCaching(flags); |
9513 | } |
9514 | } |
9515 | |
9516 | // Don't stop current network activity for javascript: URL's since |
9517 | // they might not result in any data, and thus nothing should be |
9518 | // stopped in those cases. In the case where they do result in |
9519 | // data, the javascript: URL channel takes care of stopping |
9520 | // current network activity. |
9521 | if (!isJavaScript && isNotDownload) { |
9522 | // Stop any current network activity. |
9523 | // Also stop content if this is a zombie doc. otherwise |
9524 | // the onload will be delayed by other loads initiated in the |
9525 | // background by the first document that |
9526 | // didn't fully load before the next load was initiated. |
9527 | // If not a zombie, don't stop content until data |
9528 | // starts arriving from the new URI... |
9529 | |
9530 | if ((mDocumentViewer && mDocumentViewer->GetPreviousViewer()) || |
9531 | LOAD_TYPE_HAS_FLAGS(aLoadState->LoadType(), LOAD_FLAGS_STOP_CONTENT)((aLoadState->LoadType()) & ((LOAD_FLAGS_STOP_CONTENT) << 16))) { |
9532 | rv = Stop(nsIWebNavigation::STOP_ALL); |
9533 | } else { |
9534 | rv = Stop(nsIWebNavigation::STOP_NETWORK); |
9535 | } |
9536 | |
9537 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
9538 | return rv; |
9539 | } |
9540 | } |
9541 | |
9542 | mLoadType = aLoadState->LoadType(); |
9543 | |
9544 | // aLoadState->SHEntry() should be assigned to mLSHE, only after Stop() has |
9545 | // been called. But when loading an error page, do not clear the |
9546 | // mLSHE for the real page. |
9547 | if (mLoadType != LOAD_ERROR_PAGE) { |
9548 | SetHistoryEntryAndUpdateBC(Some<nsISHEntry*>(aLoadState->SHEntry()), |
9549 | Nothing()); |
9550 | if (aLoadState->LoadIsFromSessionHistory() && |
9551 | !mozilla::SessionHistoryInParent()) { |
9552 | // We're making history navigation or a reload. Make sure our history ID |
9553 | // points to the same ID as SHEntry's docshell ID. |
9554 | nsID historyID = {}; |
9555 | aLoadState->SHEntry()->GetDocshellID(historyID); |
9556 | |
9557 | Unused << mBrowsingContext->SetHistoryID(historyID); |
9558 | } |
9559 | } |
9560 | |
9561 | mSavingOldViewer = savePresentation; |
9562 | |
9563 | // If we have a saved content viewer in history, restore and show it now. |
9564 | if (aLoadState->LoadIsFromSessionHistory() && |
9565 | (mLoadType & LOAD_CMD_HISTORY)) { |
9566 | // https://html.spec.whatwg.org/#history-traversal: |
9567 | // To traverse the history |
9568 | // "If entry has a different Document object than the current entry, then |
9569 | // run the following substeps: Remove any tasks queued by the history |
9570 | // traversal task source..." |
9571 | // Same document object case was handled already above with |
9572 | // HandleSameDocumentNavigation call. |
9573 | RefPtr<ChildSHistory> shistory = GetRootSessionHistory(); |
9574 | if (shistory) { |
9575 | shistory->RemovePendingHistoryNavigations(); |
9576 | } |
9577 | if (!mozilla::SessionHistoryInParent()) { |
9578 | // It's possible that the previous viewer of mDocumentViewer is the |
9579 | // viewer that will end up in aLoadState->SHEntry() when it gets closed. |
9580 | // If that's the case, we need to go ahead and force it into its shentry |
9581 | // so we can restore it. |
9582 | if (mDocumentViewer) { |
9583 | nsCOMPtr<nsIDocumentViewer> prevViewer = |
9584 | mDocumentViewer->GetPreviousViewer(); |
9585 | if (prevViewer) { |
9586 | #ifdef DEBUG1 |
9587 | nsCOMPtr<nsIDocumentViewer> prevPrevViewer = |
9588 | prevViewer->GetPreviousViewer(); |
9589 | 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" , 9589); MOZ_PretendNoReturn(); } } while (0); |
9590 | #endif |
9591 | nsCOMPtr<nsISHEntry> viewerEntry; |
9592 | prevViewer->GetHistoryEntry(getter_AddRefs(viewerEntry)); |
9593 | if (viewerEntry == aLoadState->SHEntry()) { |
9594 | // Make sure this viewer ends up in the right place |
9595 | mDocumentViewer->SetPreviousViewer(nullptr); |
9596 | prevViewer->Destroy(); |
9597 | } |
9598 | } |
9599 | } |
9600 | nsCOMPtr<nsISHEntry> oldEntry = mOSHE; |
9601 | bool restoring; |
9602 | rv = RestorePresentation(aLoadState->SHEntry(), &restoring); |
9603 | if (restoring) { |
9604 | Telemetry::Accumulate(Telemetry::BFCACHE_PAGE_RESTORED, true); |
9605 | return rv; |
9606 | } |
9607 | Telemetry::Accumulate(Telemetry::BFCACHE_PAGE_RESTORED, false); |
9608 | |
9609 | // We failed to restore the presentation, so clean up. |
9610 | // Both the old and new history entries could potentially be in |
9611 | // an inconsistent state. |
9612 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
9613 | if (oldEntry) { |
9614 | oldEntry->SyncPresentationState(); |
9615 | } |
9616 | |
9617 | aLoadState->SHEntry()->SyncPresentationState(); |
9618 | } |
9619 | } |
9620 | } |
9621 | |
9622 | bool isTopLevelDoc = mBrowsingContext->IsTopContent(); |
9623 | |
9624 | OriginAttributes attrs = GetOriginAttributes(); |
9625 | attrs.SetFirstPartyDomain(isTopLevelDoc, aLoadState->URI()); |
9626 | |
9627 | PredictorLearn(aLoadState->URI(), nullptr, |
9628 | nsINetworkPredictor::LEARN_LOAD_TOPLEVEL, attrs); |
9629 | PredictorPredict(aLoadState->URI(), nullptr, |
9630 | nsINetworkPredictor::PREDICT_LOAD, attrs, nullptr); |
9631 | |
9632 | nsCOMPtr<nsIRequest> req; |
9633 | rv = DoURILoad(aLoadState, aCacheKey, getter_AddRefs(req)); |
9634 | |
9635 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) { |
9636 | if (shouldTakeFocus) { |
9637 | mBrowsingContext->Focus(CallerType::System, IgnoreErrors()); |
9638 | } |
9639 | } |
9640 | |
9641 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
9642 | nsCOMPtr<nsIChannel> chan(do_QueryInterface(req)); |
9643 | UnblockEmbedderLoadEventForFailure(); |
9644 | nsCOMPtr<nsIURI> uri = aLoadState->URI(); |
9645 | if (DisplayLoadError(rv, uri, nullptr, chan) && |
9646 | // FIXME: At this point code was using internal load flags, but checking |
9647 | // non-internal load flags? |
9648 | aLoadState->HasLoadFlags(LOAD_FLAGS_ERROR_LOAD_CHANGES_RV)) { |
9649 | return NS_ERROR_LOAD_SHOWED_ERRORPAGE; |
9650 | } |
9651 | |
9652 | // We won't report any error if this is an unknown protocol error. The |
9653 | // reason behind this is that it will allow enumeration of external |
9654 | // protocols if we report an error for each unknown protocol. |
9655 | if (NS_ERROR_UNKNOWN_PROTOCOL == rv) { |
9656 | return NS_OK; |
9657 | } |
9658 | } |
9659 | |
9660 | return rv; |
9661 | } |
9662 | |
9663 | /* static */ |
9664 | bool nsDocShell::CanLoadInParentProcess(nsIURI* aURI) { |
9665 | nsCOMPtr<nsIURI> uri = aURI; |
9666 | // In e10s, in the parent process, we refuse to load anything other than |
9667 | // "safe" resources that we ship or trust enough to give "special" URLs. |
9668 | bool canLoadInParent = false; |
9669 | if (NS_SUCCEEDED(NS_URIChainHasFlags(((bool)(__builtin_expect(!!(!NS_FAILED_impl(NS_URIChainHasFlags ( uri, nsIProtocolHandler::URI_IS_UI_RESOURCE, &canLoadInParent ))), 1))) |
9670 | uri, nsIProtocolHandler::URI_IS_UI_RESOURCE, &canLoadInParent))((bool)(__builtin_expect(!!(!NS_FAILED_impl(NS_URIChainHasFlags ( uri, nsIProtocolHandler::URI_IS_UI_RESOURCE, &canLoadInParent ))), 1))) && |
9671 | canLoadInParent) { |
9672 | // We allow UI resources. |
9673 | return true; |
9674 | } |
9675 | // For about: and extension-based URIs, which don't get |
9676 | // URI_IS_UI_RESOURCE, first remove layers of view-source:, if present. |
9677 | while (uri && uri->SchemeIs("view-source")) { |
9678 | nsCOMPtr<nsINestedURI> nested = do_QueryInterface(uri); |
9679 | if (nested) { |
9680 | nested->GetInnerURI(getter_AddRefs(uri)); |
9681 | } else { |
9682 | break; |
9683 | } |
9684 | } |
9685 | // Allow about: URIs, and allow moz-extension ones if we're running |
9686 | // extension content in the parent process. |
9687 | if (!uri || uri->SchemeIs("about") || |
9688 | (!StaticPrefs::extensions_webextensions_remote() && |
9689 | uri->SchemeIs("moz-extension"))) { |
9690 | return true; |
9691 | } |
9692 | #ifdef MOZ_THUNDERBIRD |
9693 | if (uri->SchemeIs("imap") || uri->SchemeIs("mailbox") || |
9694 | uri->SchemeIs("news") || uri->SchemeIs("nntp") || |
9695 | uri->SchemeIs("snews")) { |
9696 | return true; |
9697 | } |
9698 | #endif |
9699 | nsAutoCString scheme; |
9700 | uri->GetScheme(scheme); |
9701 | // Allow ext+foo URIs (extension-registered custom protocols). See |
9702 | // https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/protocol_handlers |
9703 | if (StringBeginsWith(scheme, "ext+"_ns) && |
9704 | !StaticPrefs::extensions_webextensions_remote()) { |
9705 | return true; |
9706 | } |
9707 | // Final exception for some legacy automated tests: |
9708 | if (xpc::IsInAutomation() && |
9709 | StaticPrefs::security_allow_unsafe_parent_loads()) { |
9710 | return true; |
9711 | } |
9712 | return false; |
9713 | } |
9714 | |
9715 | nsIPrincipal* nsDocShell::GetInheritedPrincipal( |
9716 | bool aConsiderCurrentDocument, bool aConsiderPartitionedPrincipal) { |
9717 | RefPtr<Document> document; |
9718 | bool inheritedFromCurrent = false; |
9719 | |
9720 | if (aConsiderCurrentDocument && mDocumentViewer) { |
9721 | document = mDocumentViewer->GetDocument(); |
9722 | inheritedFromCurrent = true; |
9723 | } |
9724 | |
9725 | if (!document) { |
9726 | nsCOMPtr<nsIDocShellTreeItem> parentItem; |
9727 | GetInProcessSameTypeParent(getter_AddRefs(parentItem)); |
9728 | if (parentItem) { |
9729 | document = parentItem->GetDocument(); |
9730 | } |
9731 | } |
9732 | |
9733 | if (!document) { |
9734 | if (!aConsiderCurrentDocument) { |
9735 | return nullptr; |
9736 | } |
9737 | |
9738 | // Make sure we end up with _something_ as the principal no matter |
9739 | // what.If this fails, we'll just get a null docViewer and bail. |
9740 | EnsureDocumentViewer(); |
9741 | if (!mDocumentViewer) { |
9742 | return nullptr; |
9743 | } |
9744 | document = mDocumentViewer->GetDocument(); |
9745 | } |
9746 | |
9747 | //-- Get the document's principal |
9748 | if (document) { |
9749 | nsIPrincipal* docPrincipal = aConsiderPartitionedPrincipal |
9750 | ? document->PartitionedPrincipal() |
9751 | : document->NodePrincipal(); |
9752 | |
9753 | // Don't allow loads in typeContent docShells to inherit the system |
9754 | // principal from existing documents. |
9755 | if (inheritedFromCurrent && mItemType == typeContent && |
9756 | docPrincipal->IsSystemPrincipal()) { |
9757 | return nullptr; |
9758 | } |
9759 | |
9760 | return docPrincipal; |
9761 | } |
9762 | |
9763 | return nullptr; |
9764 | } |
9765 | |
9766 | /* static */ nsresult nsDocShell::CreateRealChannelForDocument( |
9767 | nsIChannel** aChannel, nsIURI* aURI, nsILoadInfo* aLoadInfo, |
9768 | nsIInterfaceRequestor* aCallbacks, nsLoadFlags aLoadFlags, |
9769 | const nsAString& aSrcdoc, nsIURI* aBaseURI) { |
9770 | nsCOMPtr<nsIChannel> channel; |
9771 | if (aSrcdoc.IsVoid()) { |
9772 | 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) |
9773 | 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) |
9774 | 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) |
9775 | 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); |
9776 | |
9777 | if (aBaseURI) { |
9778 | nsCOMPtr<nsIViewSourceChannel> vsc = do_QueryInterface(channel); |
9779 | if (vsc) { |
9780 | 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" , 9780); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false" ") (" "NS_SUCCEEDED(vsc->SetBaseURI(aBaseURI))" ")"); do { *((volatile int*)__null) = 9780; __attribute__((nomerge)) :: abort(); } while (false); } } while (false); } } while (false ); |
9781 | } |
9782 | } |
9783 | } else if (SchemeIsViewSource(aURI)) { |
9784 | // Instantiate view source handler protocol, if it doesn't exist already. |
9785 | nsCOMPtr<nsIIOService> io(do_GetIOService()); |
9786 | 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" , 9786); AnnotateMozCrashReason("MOZ_ASSERT" "(" "io" ")"); do { *((volatile int*)__null) = 9786; __attribute__((nomerge)) :: abort(); } while (false); } } while (false); |
9787 | nsCOMPtr<nsIProtocolHandler> handler; |
9788 | nsresult rv = |
9789 | io->GetProtocolHandler("view-source", getter_AddRefs(handler)); |
9790 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
9791 | return rv; |
9792 | } |
9793 | |
9794 | nsViewSourceHandler* vsh = nsViewSourceHandler::GetInstance(); |
9795 | if (!vsh) { |
9796 | return NS_ERROR_FAILURE; |
9797 | } |
9798 | |
9799 | 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) |
9800 | 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); |
9801 | } else { |
9802 | 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) |
9803 | 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) |
9804 | 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); |
9805 | nsCOMPtr<nsIInputStreamChannel> isc = do_QueryInterface(channel); |
9806 | 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" , 9806); AnnotateMozCrashReason("MOZ_ASSERT" "(" "isc" ")"); do { *((volatile int*)__null) = 9806; __attribute__((nomerge)) :: abort(); } while (false); } } while (false); |
9807 | isc->SetBaseURI(aBaseURI); |
9808 | } |
9809 | |
9810 | if (aLoadFlags != nsIRequest::LOAD_NORMAL) { |
9811 | nsresult rv = channel->SetLoadFlags(aLoadFlags); |
9812 | 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" , 9812); return rv; } } while (false); |
9813 | } |
9814 | |
9815 | channel.forget(aChannel); |
9816 | return NS_OK; |
9817 | } |
9818 | |
9819 | /* static */ bool nsDocShell::CreateAndConfigureRealChannelForLoadState( |
9820 | BrowsingContext* aBrowsingContext, nsDocShellLoadState* aLoadState, |
9821 | LoadInfo* aLoadInfo, nsIInterfaceRequestor* aCallbacks, |
9822 | nsDocShell* aDocShell, const OriginAttributes& aOriginAttributes, |
9823 | nsLoadFlags aLoadFlags, uint32_t aCacheKey, nsresult& aRv, |
9824 | nsIChannel** aChannel) { |
9825 | 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" , 9825); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadInfo" ")" ); do { *((volatile int*)__null) = 9825; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
9826 | |
9827 | nsString srcdoc = VoidString(); |
9828 | bool isSrcdoc = |
9829 | aLoadState->HasInternalLoadFlags(INTERNAL_LOAD_FLAGS_IS_SRCDOC); |
9830 | if (isSrcdoc) { |
9831 | srcdoc = aLoadState->SrcdocData(); |
9832 | } |
9833 | |
9834 | aLoadInfo->SetTriggeringRemoteType( |
9835 | aLoadState->GetEffectiveTriggeringRemoteType()); |
9836 | |
9837 | if (aLoadState->PrincipalToInherit()) { |
9838 | aLoadInfo->SetPrincipalToInherit(aLoadState->PrincipalToInherit()); |
9839 | } |
9840 | aLoadInfo->SetLoadTriggeredFromExternal( |
9841 | aLoadState->HasLoadFlags(LOAD_FLAGS_FROM_EXTERNAL)); |
9842 | aLoadInfo->SetForceAllowDataURI(aLoadState->HasInternalLoadFlags( |
9843 | INTERNAL_LOAD_FLAGS_FORCE_ALLOW_DATA_URI)); |
9844 | aLoadInfo->SetOriginalFrameSrcLoad( |
9845 | aLoadState->HasInternalLoadFlags(INTERNAL_LOAD_FLAGS_ORIGINAL_FRAME_SRC)); |
9846 | |
9847 | bool inheritAttrs = false; |
9848 | if (aLoadState->PrincipalToInherit()) { |
9849 | inheritAttrs = nsContentUtils::ChannelShouldInheritPrincipal( |
9850 | aLoadState->PrincipalToInherit(), aLoadState->URI(), |
9851 | true, // aInheritForAboutBlank |
9852 | isSrcdoc); |
9853 | } |
9854 | |
9855 | // Strip the target query parameters before creating the channel. |
9856 | aLoadState->MaybeStripTrackerQueryStrings(aBrowsingContext); |
9857 | |
9858 | OriginAttributes attrs; |
9859 | |
9860 | // Inherit origin attributes from PrincipalToInherit if inheritAttrs is |
9861 | // true. Otherwise we just use the origin attributes from docshell. |
9862 | if (inheritAttrs) { |
9863 | 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" , 9864); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->PrincipalToInherit()" ") (" "We should have PrincipalToInherit here." ")"); do { * ((volatile int*)__null) = 9864; __attribute__((nomerge)) ::abort (); } while (false); } } while (false) |
9864 | "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" , 9864); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->PrincipalToInherit()" ") (" "We should have PrincipalToInherit here." ")"); do { * ((volatile int*)__null) = 9864; __attribute__((nomerge)) ::abort (); } while (false); } } while (false); |
9865 | attrs = aLoadState->PrincipalToInherit()->OriginAttributesRef(); |
9866 | // If firstPartyIsolation is not enabled, then PrincipalToInherit should |
9867 | // have the same origin attributes with docshell. |
9868 | 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" , 9869); AnnotateMozCrashReason("MOZ_ASSERT" "(" "attrs == aOriginAttributes" ")"); do { *((volatile int*)__null) = 9869; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) |
9869 | 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" , 9869); AnnotateMozCrashReason("MOZ_ASSERT" "(" "attrs == aOriginAttributes" ")"); do { *((volatile int*)__null) = 9869; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); |
9870 | } else { |
9871 | attrs = aOriginAttributes; |
9872 | attrs.SetFirstPartyDomain(IsTopLevelDoc(aBrowsingContext, aLoadInfo), |
9873 | aLoadState->URI()); |
9874 | } |
9875 | |
9876 | aRv = aLoadInfo->SetOriginAttributes(attrs); |
9877 | 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" , 9877)) { |
9878 | return false; |
9879 | } |
9880 | |
9881 | if (aLoadState->GetIsFromProcessingFrameAttributes()) { |
9882 | aLoadInfo->SetIsFromProcessingFrameAttributes(); |
9883 | } |
9884 | |
9885 | // Propagate the IsFormSubmission flag to the loadInfo. |
9886 | if (aLoadState->IsFormSubmission()) { |
9887 | aLoadInfo->SetIsFormSubmission(true); |
9888 | } |
9889 | |
9890 | aLoadInfo->SetUnstrippedURI(aLoadState->GetUnstrippedURI()); |
9891 | |
9892 | nsCOMPtr<nsIChannel> channel; |
9893 | aRv = CreateRealChannelForDocument(getter_AddRefs(channel), aLoadState->URI(), |
9894 | aLoadInfo, aCallbacks, aLoadFlags, srcdoc, |
9895 | aLoadState->BaseURI()); |
9896 | 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" , 9896); return false; } } while (false); |
9897 | |
9898 | if (!channel) { |
9899 | return false; |
9900 | } |
9901 | |
9902 | // If the HTTPS-Only mode is enabled, every insecure request gets upgraded to |
9903 | // HTTPS by default. This behavior can be disabled through the loadinfo flag |
9904 | // HTTPS_ONLY_EXEMPT. |
9905 | nsHTTPSOnlyUtils::TestSitePermissionAndPotentiallyAddExemption(channel); |
9906 | |
9907 | // hack |
9908 | nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(channel)); |
9909 | nsCOMPtr<nsIHttpChannelInternal> httpChannelInternal( |
9910 | do_QueryInterface(channel)); |
9911 | nsCOMPtr<nsIURI> referrer; |
9912 | nsIReferrerInfo* referrerInfo = aLoadState->GetReferrerInfo(); |
9913 | if (referrerInfo) { |
9914 | referrerInfo->GetOriginalReferrer(getter_AddRefs(referrer)); |
9915 | } |
9916 | if (httpChannelInternal) { |
9917 | if (aLoadState->HasInternalLoadFlags( |
9918 | INTERNAL_LOAD_FLAGS_FORCE_ALLOW_COOKIES)) { |
9919 | aRv = httpChannelInternal->SetThirdPartyFlags( |
9920 | nsIHttpChannelInternal::THIRD_PARTY_FORCE_ALLOW); |
9921 | 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" , 9921); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1)))" ")"); do { *((volatile int*)__null) = 9921; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
9922 | } |
9923 | if (aLoadState->FirstParty()) { |
9924 | aRv = httpChannelInternal->SetDocumentURI(aLoadState->URI()); |
9925 | 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" , 9925); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1)))" ")"); do { *((volatile int*)__null) = 9925; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
9926 | } else { |
9927 | aRv = httpChannelInternal->SetDocumentURI(referrer); |
9928 | 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" , 9928); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1)))" ")"); do { *((volatile int*)__null) = 9928; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
9929 | } |
9930 | aRv = httpChannelInternal->SetRedirectMode( |
9931 | nsIHttpChannelInternal::REDIRECT_MODE_MANUAL); |
9932 | 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" , 9932); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1)))" ")"); do { *((volatile int*)__null) = 9932; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
9933 | } |
9934 | |
9935 | if (httpChannel) { |
9936 | if (aLoadState->HeadersStream()) { |
9937 | aRv = AddHeadersToChannel(aLoadState->HeadersStream(), httpChannel); |
9938 | } |
9939 | // Set the referrer explicitly |
9940 | // Referrer is currenly only set for link clicks here. |
9941 | if (referrerInfo) { |
9942 | aRv = httpChannel->SetReferrerInfo(referrerInfo); |
9943 | 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" , 9943); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1)))" ")"); do { *((volatile int*)__null) = 9943; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
9944 | } |
9945 | |
9946 | // Mark the http channel as UrgentStart for top level document loading in |
9947 | // active tab. |
9948 | if (IsUrgentStart(aBrowsingContext, aLoadInfo, aLoadState->LoadType())) { |
9949 | nsCOMPtr<nsIClassOfService> cos(do_QueryInterface(channel)); |
9950 | if (cos) { |
9951 | cos->AddClassFlags(nsIClassOfService::UrgentStart); |
9952 | } |
9953 | } |
9954 | } |
9955 | |
9956 | channel->SetOriginalURI(aLoadState->OriginalURI() ? aLoadState->OriginalURI() |
9957 | : aLoadState->URI()); |
9958 | |
9959 | const nsACString& typeHint = aLoadState->TypeHint(); |
9960 | if (!typeHint.IsVoid()) { |
9961 | channel->SetContentType(typeHint); |
9962 | } |
9963 | |
9964 | const nsAString& fileName = aLoadState->FileName(); |
9965 | if (!fileName.IsVoid()) { |
9966 | aRv = channel->SetContentDisposition(nsIChannel::DISPOSITION_ATTACHMENT); |
9967 | 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" , 9967); return false; } } while (false); |
9968 | if (!fileName.IsEmpty()) { |
9969 | aRv = channel->SetContentDispositionFilename(fileName); |
9970 | 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" , 9970); return false; } } while (false); |
9971 | } |
9972 | } |
9973 | |
9974 | if (nsCOMPtr<nsIWritablePropertyBag2> props = do_QueryInterface(channel)) { |
9975 | nsCOMPtr<nsIURI> referrer; |
9976 | nsIReferrerInfo* referrerInfo = aLoadState->GetReferrerInfo(); |
9977 | if (referrerInfo) { |
9978 | referrerInfo->GetOriginalReferrer(getter_AddRefs(referrer)); |
9979 | } |
9980 | // save true referrer for those who need it (e.g. xpinstall whitelisting) |
9981 | // Currently only http and ftp channels support this. |
9982 | props->SetPropertyAsInterface(u"docshell.internalReferrer"_ns, referrer); |
9983 | |
9984 | if (aLoadState->HasInternalLoadFlags(INTERNAL_LOAD_FLAGS_FIRST_LOAD)) { |
9985 | props->SetPropertyAsBool(u"docshell.newWindowTarget"_ns, true); |
9986 | } |
9987 | } |
9988 | |
9989 | nsCOMPtr<nsICacheInfoChannel> cacheChannel(do_QueryInterface(channel)); |
9990 | auto loadType = aLoadState->LoadType(); |
9991 | |
9992 | if (loadType == LOAD_RELOAD_NORMAL && |
9993 | StaticPrefs:: |
9994 | browser_soft_reload_only_force_validate_top_level_document()) { |
9995 | nsCOMPtr<nsICacheInfoChannel> cachingChannel = do_QueryInterface(channel); |
9996 | if (cachingChannel) { |
9997 | cachingChannel->SetForceValidateCacheContent(true); |
9998 | } |
9999 | } |
10000 | |
10001 | // figure out if we need to set the post data stream on the channel... |
10002 | if (aLoadState->PostDataStream()) { |
10003 | if (nsCOMPtr<nsIFormPOSTActionChannel> postChannel = |
10004 | do_QueryInterface(channel)) { |
10005 | // XXX it's a bit of a hack to rewind the postdata stream here but |
10006 | // it has to be done in case the post data is being reused multiple |
10007 | // times. |
10008 | nsCOMPtr<nsISeekableStream> postDataSeekable = |
10009 | do_QueryInterface(aLoadState->PostDataStream()); |
10010 | if (postDataSeekable) { |
10011 | aRv = postDataSeekable->Seek(nsISeekableStream::NS_SEEK_SET, 0); |
10012 | 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" , 10012); return false; } } while (false); |
10013 | } |
10014 | |
10015 | // we really need to have a content type associated with this stream!! |
10016 | postChannel->SetUploadStream(aLoadState->PostDataStream(), ""_ns, -1); |
10017 | |
10018 | // Ownership of the stream has transferred to the channel, clear our |
10019 | // reference. |
10020 | aLoadState->SetPostDataStream(nullptr); |
10021 | } |
10022 | |
10023 | /* If there is a valid postdata *and* it is a History Load, |
10024 | * set up the cache key on the channel, to retrieve the |
10025 | * data *only* from the cache. If it is a normal reload, the |
10026 | * cache is free to go to the server for updated postdata. |
10027 | */ |
10028 | if (cacheChannel && aCacheKey != 0) { |
10029 | if (loadType == LOAD_HISTORY || loadType == LOAD_RELOAD_CHARSET_CHANGE) { |
10030 | cacheChannel->SetCacheKey(aCacheKey); |
10031 | uint32_t loadFlags; |
10032 | if (NS_SUCCEEDED(channel->GetLoadFlags(&loadFlags))((bool)(__builtin_expect(!!(!NS_FAILED_impl(channel->GetLoadFlags (&loadFlags))), 1)))) { |
10033 | channel->SetLoadFlags(loadFlags | |
10034 | nsICachingChannel::LOAD_ONLY_FROM_CACHE); |
10035 | } |
10036 | } else if (loadType == LOAD_RELOAD_NORMAL) { |
10037 | cacheChannel->SetCacheKey(aCacheKey); |
10038 | } |
10039 | } |
10040 | } else { |
10041 | /* If there is no postdata, set the cache key on the channel, and |
10042 | * do not set the LOAD_ONLY_FROM_CACHE flag, so that the channel |
10043 | * will be free to get it from net if it is not found in cache. |
10044 | * New cache may use it creatively on CGI pages with GET |
10045 | * method and even on those that say "no-cache" |
10046 | */ |
10047 | if (loadType == LOAD_HISTORY || loadType == LOAD_RELOAD_NORMAL || |
10048 | loadType == LOAD_RELOAD_CHARSET_CHANGE || |
10049 | loadType == LOAD_RELOAD_CHARSET_CHANGE_BYPASS_CACHE || |
10050 | loadType == LOAD_RELOAD_CHARSET_CHANGE_BYPASS_PROXY_AND_CACHE) { |
10051 | if (cacheChannel && aCacheKey != 0) { |
10052 | cacheChannel->SetCacheKey(aCacheKey); |
10053 | } |
10054 | } |
10055 | } |
10056 | |
10057 | if (nsCOMPtr<nsIScriptChannel> scriptChannel = do_QueryInterface(channel)) { |
10058 | // Allow execution against our context if the principals match |
10059 | scriptChannel->SetExecutionPolicy(nsIScriptChannel::EXECUTE_NORMAL); |
10060 | } |
10061 | |
10062 | if (nsCOMPtr<nsITimedChannel> timedChannel = do_QueryInterface(channel)) { |
10063 | timedChannel->SetTimingEnabled(true); |
10064 | |
10065 | nsString initiatorType; |
10066 | switch (aLoadInfo->InternalContentPolicyType()) { |
10067 | case nsIContentPolicy::TYPE_INTERNAL_EMBED: |
10068 | initiatorType = u"embed"_ns; |
10069 | break; |
10070 | case nsIContentPolicy::TYPE_INTERNAL_OBJECT: |
10071 | initiatorType = u"object"_ns; |
10072 | break; |
10073 | default: { |
10074 | const auto& embedderElementType = |
10075 | aBrowsingContext->GetEmbedderElementType(); |
10076 | if (embedderElementType) { |
10077 | initiatorType = *embedderElementType; |
10078 | } |
10079 | break; |
10080 | } |
10081 | } |
10082 | |
10083 | if (!initiatorType.IsEmpty()) { |
10084 | timedChannel->SetInitiatorType(initiatorType); |
10085 | } |
10086 | } |
10087 | |
10088 | nsCOMPtr<nsIURI> rpURI; |
10089 | aLoadInfo->GetResultPrincipalURI(getter_AddRefs(rpURI)); |
10090 | Maybe<nsCOMPtr<nsIURI>> originalResultPrincipalURI; |
10091 | aLoadState->GetMaybeResultPrincipalURI(originalResultPrincipalURI); |
10092 | if (originalResultPrincipalURI && |
10093 | (!aLoadState->KeepResultPrincipalURIIfSet() || !rpURI)) { |
10094 | // Unconditionally override, we want the replay to be equal to what has |
10095 | // been captured. |
10096 | aLoadInfo->SetResultPrincipalURI(originalResultPrincipalURI.ref()); |
10097 | } |
10098 | |
10099 | if (aLoadState->OriginalURI() && aLoadState->LoadReplace()) { |
10100 | // The LOAD_REPLACE flag and its handling here will be removed as part |
10101 | // of bug 1319110. For now preserve its restoration here to not break |
10102 | // any code expecting it being set specially on redirected channels. |
10103 | // If the flag has originally been set to change result of |
10104 | // NS_GetFinalChannelURI it won't have any effect and also won't cause |
10105 | // any harm. |
10106 | uint32_t loadFlags; |
10107 | aRv = channel->GetLoadFlags(&loadFlags); |
10108 | 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" , 10108); return false; } } while (false); |
10109 | channel->SetLoadFlags(loadFlags | nsIChannel::LOAD_REPLACE); |
10110 | } |
10111 | |
10112 | nsCOMPtr<nsIContentSecurityPolicy> csp = aLoadState->Csp(); |
10113 | if (csp) { |
10114 | // Navigational requests that are same origin need to be upgraded in case |
10115 | // upgrade-insecure-requests is present. Please note that for document |
10116 | // navigations that bit is re-computed in case we encounter a server |
10117 | // side redirect so the navigation is not same-origin anymore. |
10118 | bool upgradeInsecureRequests = false; |
10119 | csp->GetUpgradeInsecureRequests(&upgradeInsecureRequests); |
10120 | if (upgradeInsecureRequests) { |
10121 | // only upgrade if the navigation is same origin |
10122 | nsCOMPtr<nsIPrincipal> resultPrincipal; |
10123 | aRv = nsContentUtils::GetSecurityManager()->GetChannelResultPrincipal( |
10124 | channel, getter_AddRefs(resultPrincipal)); |
10125 | 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" , 10125); return false; } } while (false); |
10126 | if (nsContentSecurityUtils::IsConsideredSameOriginForUIR( |
10127 | aLoadState->TriggeringPrincipal(), resultPrincipal)) { |
10128 | aLoadInfo->SetUpgradeInsecureRequests(true); |
10129 | } |
10130 | } |
10131 | |
10132 | // For document loads we store the CSP that potentially needs to |
10133 | // be inherited by the new document, e.g. in case we are loading |
10134 | // an opaque origin like a data: URI. The actual inheritance |
10135 | // check happens within Document::InitCSP(). |
10136 | // Please create an actual copy of the CSP (do not share the same |
10137 | // reference) otherwise a Meta CSP of an opaque origin will |
10138 | // incorrectly be propagated to the embedding document. |
10139 | RefPtr<nsCSPContext> cspToInherit = new nsCSPContext(); |
10140 | cspToInherit->InitFromOther(static_cast<nsCSPContext*>(csp.get())); |
10141 | aLoadInfo->SetCSPToInherit(cspToInherit); |
10142 | } |
10143 | |
10144 | channel.forget(aChannel); |
10145 | return true; |
10146 | } |
10147 | |
10148 | bool nsDocShell::IsAboutBlankLoadOntoInitialAboutBlank( |
10149 | nsIURI* aURI, bool aInheritPrincipal, nsIPrincipal* aPrincipalToInherit) { |
10150 | return NS_IsAboutBlank(aURI) && aInheritPrincipal && |
10151 | (aPrincipalToInherit == GetInheritedPrincipal(false)) && |
10152 | (!mDocumentViewer || !mDocumentViewer->GetDocument() || |
10153 | mDocumentViewer->GetDocument()->IsInitialDocument()); |
10154 | } |
10155 | |
10156 | nsresult nsDocShell::DoURILoad(nsDocShellLoadState* aLoadState, |
10157 | Maybe<uint32_t> aCacheKey, |
10158 | nsIRequest** aRequest) { |
10159 | // Double-check that we're still around to load this URI. |
10160 | if (mIsBeingDestroyed) { |
10161 | // Return NS_OK despite not doing anything to avoid throwing exceptions |
10162 | // from nsLocation::SetHref if the unload handler of the existing page |
10163 | // tears us down. |
10164 | return NS_OK; |
10165 | } |
10166 | |
10167 | nsCOMPtr<nsIURILoader> uriLoader = components::URILoader::Service(); |
10168 | if (NS_WARN_IF(!uriLoader)NS_warn_if_impl(!uriLoader, "!uriLoader", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp" , 10168)) { |
10169 | return NS_ERROR_UNEXPECTED; |
10170 | } |
10171 | |
10172 | // Persist and sync layout history state before we load a new uri, as this |
10173 | // might be our last chance to do so, in the content process. |
10174 | PersistLayoutHistoryState(); |
10175 | SynchronizeLayoutHistoryState(); |
10176 | |
10177 | nsresult rv; |
10178 | nsContentPolicyType contentPolicyType = DetermineContentType(); |
10179 | |
10180 | if (IsSubframe()) { |
10181 | 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" , 10183); 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) = 10183; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false) |
10182 | 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" , 10183); 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) = 10183; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false) |
10183 | "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" , 10183); 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) = 10183; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
10184 | |
10185 | if (StaticPrefs::dom_block_external_protocol_in_iframes()) { |
10186 | // Only allow URLs able to return data in iframes. |
10187 | if (nsContentUtils::IsExternalProtocol(aLoadState->URI())) { |
10188 | // The context to check user-interaction with for the purposes of |
10189 | // popup-blocking. |
10190 | // |
10191 | // We generally want to check the context that initiated the navigation. |
10192 | WindowContext* sourceWindowContext = [&] { |
10193 | const MaybeDiscardedBrowsingContext& sourceBC = |
10194 | aLoadState->SourceBrowsingContext(); |
10195 | if (!sourceBC.IsNullOrDiscarded()) { |
10196 | if (WindowContext* wc = sourceBC.get()->GetCurrentWindowContext()) { |
10197 | return wc; |
10198 | } |
10199 | } |
10200 | return mBrowsingContext->GetParentWindowContext(); |
10201 | }(); |
10202 | |
10203 | 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" , 10203); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sourceWindowContext" ")"); do { *((volatile int*)__null) = 10203; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
10204 | // FIXME: We can't check user-interaction against an OOP window. This is |
10205 | // the next best thing we can really do. The load state keeps whether |
10206 | // the navigation had a user interaction in process |
10207 | // (aLoadState->HasValidUserGestureActivation()), but we can't really |
10208 | // consume it, which we want to prevent popup-spamming from the same |
10209 | // click event. |
10210 | WindowContext* context = |
10211 | sourceWindowContext->IsInProcess() |
10212 | ? sourceWindowContext |
10213 | : mBrowsingContext->GetCurrentWindowContext(); |
10214 | const bool popupBlocked = [&] { |
10215 | const bool active = mBrowsingContext->IsActive(); |
10216 | |
10217 | // For same-origin-with-top windows, we grant a single free popup |
10218 | // without user activation, see bug 1680721. |
10219 | // |
10220 | // We consume the flag now even if there's no user activation. |
10221 | const bool hasFreePass = [&] { |
10222 | if (!active || |
10223 | !(context->IsInProcess() && context->SameOriginWithTop())) { |
10224 | return false; |
10225 | } |
10226 | nsGlobalWindowInner* win = |
10227 | context->TopWindowContext()->GetInnerWindow(); |
10228 | return win && win->TryOpenExternalProtocolIframe(); |
10229 | }(); |
10230 | |
10231 | if (context->IsInProcess() && |
10232 | context->ConsumeTransientUserGestureActivation()) { |
10233 | // If the user has interacted with the page, consume it. |
10234 | return false; |
10235 | } |
10236 | |
10237 | // TODO(emilio): Can we remove this check? It seems like what prompted |
10238 | // this code (bug 1514547) should be covered by transient user |
10239 | // activation, see bug 1514547. |
10240 | if (active && |
10241 | PopupBlocker::ConsumeTimerTokenForExternalProtocolIframe()) { |
10242 | return false; |
10243 | } |
10244 | |
10245 | if (sourceWindowContext->CanShowPopup()) { |
10246 | return false; |
10247 | } |
10248 | |
10249 | if (hasFreePass) { |
10250 | return false; |
10251 | } |
10252 | |
10253 | return true; |
10254 | }(); |
10255 | |
10256 | // No error must be returned when iframes are blocked. |
10257 | if (popupBlocked) { |
10258 | nsAutoString message; |
10259 | nsresult rv = nsContentUtils::GetLocalizedString( |
10260 | nsContentUtils::eDOM_PROPERTIES, |
10261 | "ExternalProtocolFrameBlockedNoUserActivation", message); |
10262 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) { |
10263 | nsContentUtils::ReportToConsoleByWindowID( |
10264 | message, nsIScriptError::warningFlag, "DOM"_ns, |
10265 | context->InnerWindowId()); |
10266 | } |
10267 | return NS_OK; |
10268 | } |
10269 | } |
10270 | } |
10271 | |
10272 | // Only allow view-source scheme in top-level docshells. view-source is |
10273 | // the only scheme to which this applies at the moment due to potential |
10274 | // timing attacks to read data from cross-origin iframes. If this widens |
10275 | // we should add a protocol flag for whether the scheme is allowed in |
10276 | // frames and use something like nsNetUtil::NS_URIChainHasFlags. |
10277 | nsCOMPtr<nsIURI> tempURI = aLoadState->URI(); |
10278 | nsCOMPtr<nsINestedURI> nestedURI = do_QueryInterface(tempURI); |
10279 | while (nestedURI) { |
10280 | // view-source should always be an nsINestedURI, loop and check the |
10281 | // scheme on this and all inner URIs that are also nested URIs. |
10282 | if (SchemeIsViewSource(tempURI)) { |
10283 | return NS_ERROR_UNKNOWN_PROTOCOL; |
10284 | } |
10285 | nestedURI->GetInnerURI(getter_AddRefs(tempURI)); |
10286 | nestedURI = do_QueryInterface(tempURI); |
10287 | } |
10288 | } else { |
10289 | 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" , 10290); AnnotateMozCrashReason("MOZ_ASSERT" "(" "contentPolicyType == nsIContentPolicy::TYPE_DOCUMENT" ") (" "DoURILoad thinks this is a document and InternalLoad does not" ")"); do { *((volatile int*)__null) = 10290; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false) |
10290 | "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" , 10290); AnnotateMozCrashReason("MOZ_ASSERT" "(" "contentPolicyType == nsIContentPolicy::TYPE_DOCUMENT" ") (" "DoURILoad thinks this is a document and InternalLoad does not" ")"); do { *((volatile int*)__null) = 10290; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
10291 | } |
10292 | |
10293 | // We want to inherit aLoadState->PrincipalToInherit() when: |
10294 | // 1. ChannelShouldInheritPrincipal returns true. |
10295 | // 2. aLoadState->URI() is not data: URI, or data: URI is not |
10296 | // configured as unique opaque origin. |
10297 | bool inheritPrincipal = false; |
10298 | |
10299 | if (aLoadState->PrincipalToInherit()) { |
10300 | bool isSrcdoc = |
10301 | aLoadState->HasInternalLoadFlags(INTERNAL_LOAD_FLAGS_IS_SRCDOC); |
10302 | bool inheritAttrs = nsContentUtils::ChannelShouldInheritPrincipal( |
10303 | aLoadState->PrincipalToInherit(), aLoadState->URI(), |
10304 | true, // aInheritForAboutBlank |
10305 | isSrcdoc); |
10306 | |
10307 | inheritPrincipal = inheritAttrs && !SchemeIsData(aLoadState->URI()); |
10308 | } |
10309 | |
10310 | // See https://bugzilla.mozilla.org/show_bug.cgi?id=1736570 |
10311 | const bool isAboutBlankLoadOntoInitialAboutBlank = |
10312 | IsAboutBlankLoadOntoInitialAboutBlank(aLoadState->URI(), inheritPrincipal, |
10313 | aLoadState->PrincipalToInherit()); |
10314 | |
10315 | // FIXME We still have a ton of codepaths that don't pass through |
10316 | // DocumentLoadListener, so probably need to create session history info |
10317 | // in more places. |
10318 | if (aLoadState->GetLoadingSessionHistoryInfo()) { |
10319 | SetLoadingSessionHistoryInfo(*aLoadState->GetLoadingSessionHistoryInfo()); |
10320 | } else if (isAboutBlankLoadOntoInitialAboutBlank && |
10321 | mozilla::SessionHistoryInParent()) { |
10322 | // Materialize LoadingSessionHistoryInfo here, because DocumentChannel |
10323 | // loads have it, and later history behavior depends on it existing. |
10324 | UniquePtr<SessionHistoryInfo> entry = MakeUnique<SessionHistoryInfo>( |
10325 | aLoadState->URI(), aLoadState->TriggeringPrincipal(), |
10326 | aLoadState->PrincipalToInherit(), |
10327 | aLoadState->PartitionedPrincipalToInherit(), aLoadState->Csp(), |
10328 | mContentTypeHint); |
10329 | mozilla::dom::LoadingSessionHistoryInfo info(*entry); |
10330 | SetLoadingSessionHistoryInfo(info, true); |
10331 | } |
10332 | |
10333 | // open a channel for the url |
10334 | |
10335 | // If we have a pending channel, use the channel we've already created here. |
10336 | // We don't need to set up load flags for our channel, as it has already been |
10337 | // created. |
10338 | |
10339 | if (nsCOMPtr<nsIChannel> channel = |
10340 | aLoadState->GetPendingRedirectedChannel()) { |
10341 | // If we have a request outparameter, shove our channel into it. |
10342 | if (aRequest) { |
10343 | nsCOMPtr<nsIRequest> outRequest = channel; |
10344 | outRequest.forget(aRequest); |
10345 | } |
10346 | |
10347 | return OpenRedirectedChannel(aLoadState); |
10348 | } |
10349 | |
10350 | // There are two cases we care about: |
10351 | // * Top-level load: In this case, loadingNode is null, but loadingWindow |
10352 | // is our mScriptGlobal. We pass null for loadingPrincipal in this case. |
10353 | // * Subframe load: loadingWindow is null, but loadingNode is the frame |
10354 | // element for the load. loadingPrincipal is the NodePrincipal of the |
10355 | // frame element. |
10356 | nsCOMPtr<nsINode> loadingNode; |
10357 | nsCOMPtr<nsPIDOMWindowOuter> loadingWindow; |
10358 | nsCOMPtr<nsIPrincipal> loadingPrincipal; |
10359 | nsCOMPtr<nsISupports> topLevelLoadingContext; |
10360 | |
10361 | if (contentPolicyType == nsIContentPolicy::TYPE_DOCUMENT) { |
10362 | loadingNode = nullptr; |
10363 | loadingPrincipal = nullptr; |
10364 | loadingWindow = mScriptGlobal; |
10365 | if (XRE_IsContentProcess()) { |
10366 | // In e10s the child process doesn't have access to the element that |
10367 | // contains the browsing context (because that element is in the chrome |
10368 | // process). |
10369 | nsCOMPtr<nsIBrowserChild> browserChild = GetBrowserChild(); |
10370 | topLevelLoadingContext = ToSupports(browserChild); |
10371 | } else { |
10372 | // This is for loading non-e10s tabs and toplevel windows of various |
10373 | // sorts. |
10374 | // For the toplevel window cases, requestingElement will be null. |
10375 | nsCOMPtr<Element> requestingElement = |
10376 | loadingWindow->GetFrameElementInternal(); |
10377 | topLevelLoadingContext = requestingElement; |
10378 | } |
10379 | } else { |
10380 | loadingWindow = nullptr; |
10381 | loadingNode = mScriptGlobal->GetFrameElementInternal(); |
10382 | if (loadingNode) { |
10383 | // If we have a loading node, then use that as our loadingPrincipal. |
10384 | loadingPrincipal = loadingNode->NodePrincipal(); |
10385 | #ifdef DEBUG1 |
10386 | // Get the docshell type for requestingElement. |
10387 | RefPtr<Document> requestingDoc = loadingNode->OwnerDoc(); |
10388 | nsCOMPtr<nsIDocShell> elementDocShell = requestingDoc->GetDocShell(); |
10389 | // requestingElement docshell type = current docshell type. |
10390 | 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" , 10392); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mItemType == elementDocShell->ItemType()" ") (" "subframes should have the same docshell type as their parent" ")"); do { *((volatile int*)__null) = 10392; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false) |
10391 | 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" , 10392); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mItemType == elementDocShell->ItemType()" ") (" "subframes should have the same docshell type as their parent" ")"); do { *((volatile int*)__null) = 10392; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false) |
10392 | "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" , 10392); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mItemType == elementDocShell->ItemType()" ") (" "subframes should have the same docshell type as their parent" ")"); do { *((volatile int*)__null) = 10392; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
10393 | #endif |
10394 | } else { |
10395 | if (mIsBeingDestroyed) { |
10396 | // If this isn't a top-level load and mScriptGlobal's frame element is |
10397 | // null, then the element got removed from the DOM while we were trying |
10398 | // to load this resource. This docshell is scheduled for destruction |
10399 | // already, so bail out here. |
10400 | return NS_OK; |
10401 | } |
10402 | // If we are not being destroyed and we do not have access to the loading |
10403 | // node, then we are a remote subframe. Set the loading principal |
10404 | // to be a null principal and then set it correctly in the parent. |
10405 | loadingPrincipal = NullPrincipal::Create(GetOriginAttributes(), nullptr); |
10406 | } |
10407 | } |
10408 | |
10409 | if (!aLoadState->TriggeringPrincipal()) { |
10410 | 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" , 10410); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "DoURILoad needs a valid triggeringPrincipal" ")"); do { *(( volatile int*)__null) = 10410; __attribute__((nomerge)) ::abort (); } while (false); } } while (false); |
10411 | return NS_ERROR_FAILURE; |
10412 | } |
10413 | |
10414 | uint32_t sandboxFlags = mBrowsingContext->GetSandboxFlags(); |
10415 | nsSecurityFlags securityFlags = |
10416 | nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL; |
10417 | |
10418 | if (mLoadType == LOAD_ERROR_PAGE) { |
10419 | securityFlags |= nsILoadInfo::SEC_LOAD_ERROR_PAGE; |
10420 | } |
10421 | |
10422 | if (inheritPrincipal) { |
10423 | securityFlags |= nsILoadInfo::SEC_FORCE_INHERIT_PRINCIPAL; |
10424 | } |
10425 | |
10426 | // Must never have a parent for TYPE_DOCUMENT loads |
10427 | 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" , 10428); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mBrowsingContext->GetParent()" ")"); do { *((volatile int*)__null) = 10428; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); } } while (false) |
10428 | !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" , 10428); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mBrowsingContext->GetParent()" ")"); do { *((volatile int*)__null) = 10428; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); } } while (false); |
10429 | // Subdocuments must have a parent |
10430 | 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" , 10431); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mBrowsingContext->GetParent()" ")"); do { *((volatile int*)__null) = 10431; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); } } while (false) |
10431 | 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" , 10431); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mBrowsingContext->GetParent()" ")"); do { *((volatile int*)__null) = 10431; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); } } while (false); |
10432 | mBrowsingContext->SetTriggeringAndInheritPrincipals( |
10433 | aLoadState->TriggeringPrincipal(), aLoadState->PrincipalToInherit(), |
10434 | aLoadState->GetLoadIdentifier()); |
10435 | RefPtr<LoadInfo> loadInfo = |
10436 | (contentPolicyType == nsIContentPolicy::TYPE_DOCUMENT) |
10437 | ? new LoadInfo(loadingWindow, aLoadState->URI(), |
10438 | aLoadState->TriggeringPrincipal(), |
10439 | topLevelLoadingContext, securityFlags, sandboxFlags) |
10440 | : new LoadInfo(loadingPrincipal, aLoadState->TriggeringPrincipal(), |
10441 | loadingNode, securityFlags, contentPolicyType, |
10442 | Maybe<mozilla::dom::ClientInfo>(), |
10443 | Maybe<mozilla::dom::ServiceWorkerDescriptor>(), |
10444 | sandboxFlags); |
10445 | RefPtr<WindowContext> context = mBrowsingContext->GetCurrentWindowContext(); |
10446 | |
10447 | if (isAboutBlankLoadOntoInitialAboutBlank) { |
10448 | // Match the DocumentChannel case where the default for third-partiness |
10449 | // differs from the default in LoadInfo construction here. |
10450 | // toolkit/components/antitracking/test/browser/browser_aboutblank.js |
10451 | // fails without this. |
10452 | BrowsingContext* top = mBrowsingContext->Top(); |
10453 | if (top == mBrowsingContext) { |
10454 | // If we're at the top, this must be a window.open()ed |
10455 | // window, and we can't be third-party relative to ourselves. |
10456 | loadInfo->SetIsThirdPartyContextToTopWindow(false); |
10457 | } else { |
10458 | if (Document* topDoc = top->GetDocument()) { |
10459 | bool thirdParty = false; |
10460 | mozilla::Unused << topDoc->GetPrincipal()->IsThirdPartyPrincipal( |
10461 | aLoadState->PrincipalToInherit(), &thirdParty); |
10462 | loadInfo->SetIsThirdPartyContextToTopWindow(thirdParty); |
10463 | } else { |
10464 | // If top is in a different process, we have to be third-party relative |
10465 | // to it. |
10466 | loadInfo->SetIsThirdPartyContextToTopWindow(true); |
10467 | } |
10468 | } |
10469 | } |
10470 | |
10471 | if (mLoadType != LOAD_ERROR_PAGE && context && context->IsInProcess()) { |
10472 | if (context->HasValidTransientUserGestureActivation()) { |
10473 | aLoadState->SetHasValidUserGestureActivation(true); |
10474 | } |
10475 | if (!aLoadState->TriggeringWindowId()) { |
10476 | aLoadState->SetTriggeringWindowId(context->Id()); |
10477 | } |
10478 | if (!aLoadState->TriggeringStorageAccess()) { |
10479 | Document* contextDoc = context->GetExtantDoc(); |
10480 | if (contextDoc) { |
10481 | aLoadState->SetTriggeringStorageAccess( |
10482 | contextDoc->UsingStorageAccess()); |
10483 | } |
10484 | } |
10485 | } |
10486 | |
10487 | // in case this docshell load was triggered by a valid transient user gesture, |
10488 | // or also the load originates from external, then we pass that information on |
10489 | // to the loadinfo, which allows e.g. setting Sec-Fetch-User request headers. |
10490 | if (aLoadState->HasValidUserGestureActivation() || |
10491 | aLoadState->HasLoadFlags(LOAD_FLAGS_FROM_EXTERNAL)) { |
10492 | loadInfo->SetHasValidUserGestureActivation(true); |
10493 | } |
10494 | |
10495 | loadInfo->SetTriggeringWindowId(aLoadState->TriggeringWindowId()); |
10496 | loadInfo->SetTriggeringStorageAccess(aLoadState->TriggeringStorageAccess()); |
10497 | loadInfo->SetTriggeringSandboxFlags(aLoadState->TriggeringSandboxFlags()); |
10498 | loadInfo->SetIsMetaRefresh(aLoadState->IsMetaRefresh()); |
10499 | |
10500 | uint32_t cacheKey = 0; |
10501 | if (aCacheKey) { |
10502 | cacheKey = *aCacheKey; |
10503 | } else if (mozilla::SessionHistoryInParent()) { |
10504 | if (mLoadingEntry) { |
10505 | cacheKey = mLoadingEntry->mInfo.GetCacheKey(); |
10506 | } else if (mActiveEntry) { // for reload cases |
10507 | cacheKey = mActiveEntry->GetCacheKey(); |
10508 | } |
10509 | } else { |
10510 | if (mLSHE) { |
10511 | cacheKey = mLSHE->GetCacheKey(); |
10512 | } else if (mOSHE) { // for reload cases |
10513 | cacheKey = mOSHE->GetCacheKey(); |
10514 | } |
10515 | } |
10516 | |
10517 | bool uriModified; |
10518 | if (mLSHE || mLoadingEntry) { |
10519 | if (mLoadingEntry) { |
10520 | uriModified = mLoadingEntry->mInfo.GetURIWasModified(); |
10521 | } else { |
10522 | uriModified = mLSHE->GetURIWasModified(); |
10523 | } |
10524 | } else { |
10525 | uriModified = false; |
10526 | } |
10527 | |
10528 | bool isEmbeddingBlockedError = false; |
10529 | if (mFailedChannel) { |
10530 | nsresult status; |
10531 | mFailedChannel->GetStatus(&status); |
10532 | isEmbeddingBlockedError = status == NS_ERROR_XFO_VIOLATION || |
10533 | status == NS_ERROR_CSP_FRAME_ANCESTOR_VIOLATION; |
10534 | } |
10535 | |
10536 | nsLoadFlags loadFlags = aLoadState->CalculateChannelLoadFlags( |
10537 | mBrowsingContext, Some(uriModified), Some(isEmbeddingBlockedError)); |
10538 | |
10539 | nsCOMPtr<nsIChannel> channel; |
10540 | if (DocumentChannel::CanUseDocumentChannel(aLoadState->URI()) && |
10541 | !isAboutBlankLoadOntoInitialAboutBlank) { |
10542 | channel = DocumentChannel::CreateForDocument( |
10543 | aLoadState, loadInfo, loadFlags, this, cacheKey, uriModified, |
10544 | isEmbeddingBlockedError); |
10545 | 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" , 10545); AnnotateMozCrashReason("MOZ_ASSERT" "(" "channel" ")" ); do { *((volatile int*)__null) = 10545; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
10546 | |
10547 | // Disable keyword fixup when using DocumentChannel, since |
10548 | // DocumentLoadListener will handle this for us (in the parent process). |
10549 | mAllowKeywordFixup = false; |
10550 | } else if (!CreateAndConfigureRealChannelForLoadState( |
10551 | mBrowsingContext, aLoadState, loadInfo, this, this, |
10552 | GetOriginAttributes(), loadFlags, cacheKey, rv, |
10553 | getter_AddRefs(channel))) { |
10554 | return rv; |
10555 | } |
10556 | |
10557 | // Make sure to give the caller a channel if we managed to create one |
10558 | // This is important for correct error page/session history interaction |
10559 | if (aRequest) { |
10560 | NS_ADDREF(*aRequest = channel)(*aRequest = channel)->AddRef(); |
10561 | } |
10562 | |
10563 | nsCOMPtr<nsIContentSecurityPolicy> csp = aLoadState->Csp(); |
10564 | if (csp) { |
10565 | // Check CSP navigate-to |
10566 | bool allowsNavigateTo = false; |
10567 | rv = csp->GetAllowsNavigateTo(aLoadState->URI(), |
10568 | aLoadState->IsFormSubmission(), |
10569 | false, /* aWasRedirected */ |
10570 | false, /* aEnforceWhitelist */ |
10571 | &allowsNavigateTo); |
10572 | 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" , 10572); return rv; } } while (false); |
10573 | |
10574 | if (!allowsNavigateTo) { |
10575 | return NS_ERROR_CSP_NAVIGATE_TO_VIOLATION; |
10576 | } |
10577 | } |
10578 | |
10579 | const nsACString& typeHint = aLoadState->TypeHint(); |
10580 | if (!typeHint.IsVoid()) { |
10581 | mContentTypeHint = typeHint; |
10582 | } else { |
10583 | mContentTypeHint.Truncate(); |
10584 | } |
10585 | |
10586 | // Load attributes depend on load type... |
10587 | if (mLoadType == LOAD_RELOAD_CHARSET_CHANGE) { |
10588 | // Use SetAllowStaleCacheContent (not LOAD_FROM_CACHE flag) since we |
10589 | // only want to force cache load for this channel, not the whole |
10590 | // loadGroup. |
10591 | nsCOMPtr<nsICacheInfoChannel> cachingChannel = do_QueryInterface(channel); |
10592 | if (cachingChannel) { |
10593 | cachingChannel->SetAllowStaleCacheContent(true); |
10594 | } |
10595 | } |
10596 | |
10597 | uint32_t openFlags = |
10598 | nsDocShell::ComputeURILoaderFlags(mBrowsingContext, mLoadType); |
10599 | return OpenInitializedChannel(channel, uriLoader, openFlags); |
10600 | } |
10601 | |
10602 | static nsresult AppendSegmentToString(nsIInputStream* aIn, void* aClosure, |
10603 | const char* aFromRawSegment, |
10604 | uint32_t aToOffset, uint32_t aCount, |
10605 | uint32_t* aWriteCount) { |
10606 | // aFromSegment now contains aCount bytes of data. |
10607 | |
10608 | nsAutoCString* buf = static_cast<nsAutoCString*>(aClosure); |
10609 | buf->Append(aFromRawSegment, aCount); |
10610 | |
10611 | // Indicate that we have consumed all of aFromSegment |
10612 | *aWriteCount = aCount; |
10613 | return NS_OK; |
10614 | } |
10615 | |
10616 | /* static */ nsresult nsDocShell::AddHeadersToChannel( |
10617 | nsIInputStream* aHeadersData, nsIChannel* aGenericChannel) { |
10618 | nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aGenericChannel); |
10619 | 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" , 10619); return NS_ERROR_UNEXPECTED; } } while (false); |
10620 | |
10621 | uint32_t numRead; |
10622 | nsAutoCString headersString; |
10623 | nsresult rv = aHeadersData->ReadSegments( |
10624 | AppendSegmentToString, &headersString, UINT32_MAX(4294967295U), &numRead); |
10625 | 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" , 10625); return rv; } } while (false); |
10626 | |
10627 | // used during the manipulation of the String from the InputStream |
10628 | nsAutoCString headerName; |
10629 | nsAutoCString headerValue; |
10630 | int32_t crlf; |
10631 | int32_t colon; |
10632 | |
10633 | // |
10634 | // Iterate over the headersString: for each "\r\n" delimited chunk, |
10635 | // add the value as a header to the nsIHttpChannel |
10636 | // |
10637 | |
10638 | static const char kWhitespace[] = "\b\t\r\n "; |
10639 | while (true) { |
10640 | crlf = headersString.Find("\r\n"); |
10641 | if (crlf == kNotFound) { |
10642 | return NS_OK; |
10643 | } |
10644 | |
10645 | const nsACString& oneHeader = StringHead(headersString, crlf); |
10646 | |
10647 | colon = oneHeader.FindChar(':'); |
10648 | if (colon == kNotFound) { |
10649 | return NS_ERROR_UNEXPECTED; |
10650 | } |
10651 | |
10652 | headerName = StringHead(oneHeader, colon); |
10653 | headerValue = Substring(oneHeader, colon + 1); |
10654 | |
10655 | headerName.Trim(kWhitespace); |
10656 | headerValue.Trim(kWhitespace); |
10657 | |
10658 | headersString.Cut(0, crlf + 2); |
10659 | |
10660 | // |
10661 | // FINALLY: we can set the header! |
10662 | // |
10663 | |
10664 | rv = httpChannel->SetRequestHeader(headerName, headerValue, true); |
10665 | 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" , 10665); return rv; } } while (false); |
10666 | } |
10667 | |
10668 | 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" , 10668); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: " "oops" ")"); do { *((volatile int *)__null) = 10668; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
10669 | return NS_ERROR_UNEXPECTED; |
10670 | } |
10671 | |
10672 | /* static */ uint32_t nsDocShell::ComputeURILoaderFlags( |
10673 | BrowsingContext* aBrowsingContext, uint32_t aLoadType) { |
10674 | 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" , 10674); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aBrowsingContext" ")"); do { *((volatile int*)__null) = 10674; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
10675 | |
10676 | uint32_t openFlags = 0; |
10677 | if (aLoadType == LOAD_LINK) { |
10678 | openFlags |= nsIURILoader::IS_CONTENT_PREFERRED; |
10679 | } |
10680 | if (!aBrowsingContext->GetAllowContentRetargeting()) { |
10681 | openFlags |= nsIURILoader::DONT_RETARGET; |
10682 | } |
10683 | |
10684 | return openFlags; |
10685 | } |
10686 | |
10687 | nsresult nsDocShell::OpenInitializedChannel(nsIChannel* aChannel, |
10688 | nsIURILoader* aURILoader, |
10689 | uint32_t aOpenFlags) { |
10690 | nsresult rv = NS_OK; |
10691 | |
10692 | // If anything fails here, make sure to clear our initial ClientSource. |
10693 | auto cleanupInitialClient = |
10694 | MakeScopeExit([&] { mInitialClientSource.reset(); }); |
10695 | |
10696 | nsCOMPtr<nsPIDOMWindowOuter> win = GetWindow(); |
10697 | 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" , 10697); return NS_ERROR_FAILURE; } } while (false); |
10698 | |
10699 | MaybeCreateInitialClientSource(); |
10700 | |
10701 | // Let the client channel helper know if we are using DocumentChannel, |
10702 | // since redirects get handled in the parent process in that case. |
10703 | RefPtr<net::DocumentChannel> docChannel = do_QueryObject(aChannel); |
10704 | if (docChannel && XRE_IsContentProcess()) { |
10705 | // Tell the content process nsDocumentOpenInfo to not try to do |
10706 | // any sort of targeting. |
10707 | aOpenFlags |= nsIURILoader::DONT_RETARGET; |
10708 | } |
10709 | |
10710 | // Since we are loading a document we need to make sure the proper reserved |
10711 | // and initial client data is stored on the nsILoadInfo. The |
10712 | // ClientChannelHelper does this and ensures that it is propagated properly |
10713 | // on redirects. We pass no reserved client here so that the helper will |
10714 | // create the reserved ClientSource if necessary. |
10715 | Maybe<ClientInfo> noReservedClient; |
10716 | if (docChannel) { |
10717 | // When using DocumentChannel, all redirect handling is done in the parent, |
10718 | // so we just need the child variant to watch for the internal redirect |
10719 | // to the final channel. |
10720 | rv = AddClientChannelHelperInChild(aChannel, |
10721 | GetMainThreadSerialEventTarget()); |
10722 | docChannel->SetInitialClientInfo(GetInitialClientInfo()); |
10723 | } else { |
10724 | rv = AddClientChannelHelper(aChannel, std::move(noReservedClient), |
10725 | GetInitialClientInfo(), |
10726 | GetMainThreadSerialEventTarget()); |
10727 | } |
10728 | 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" , 10728); return rv; } } while (false); |
10729 | |
10730 | rv = aURILoader->OpenURI(aChannel, aOpenFlags, this); |
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 | // We're about to load a new page and it may take time before necko |
10734 | // gives back any data, so main thread might have a chance to process a |
10735 | // collector slice |
10736 | nsJSContext::MaybeRunNextCollectorSlice(this, JS::GCReason::DOCSHELL); |
10737 | |
10738 | // Success. Keep the initial ClientSource if it exists. |
10739 | cleanupInitialClient.release(); |
10740 | |
10741 | return NS_OK; |
10742 | } |
10743 | |
10744 | nsresult nsDocShell::OpenRedirectedChannel(nsDocShellLoadState* aLoadState) { |
10745 | nsCOMPtr<nsIChannel> channel = aLoadState->GetPendingRedirectedChannel(); |
10746 | 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" , 10746); AnnotateMozCrashReason("MOZ_ASSERT" "(" "channel" ")" ); do { *((volatile int*)__null) = 10746; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
10747 | |
10748 | // If anything fails here, make sure to clear our initial ClientSource. |
10749 | auto cleanupInitialClient = |
10750 | MakeScopeExit([&] { mInitialClientSource.reset(); }); |
10751 | |
10752 | nsCOMPtr<nsPIDOMWindowOuter> win = GetWindow(); |
10753 | 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" , 10753); return NS_ERROR_FAILURE; } } while (false); |
10754 | |
10755 | MaybeCreateInitialClientSource(); |
10756 | |
10757 | nsCOMPtr<nsILoadInfo> loadInfo = channel->LoadInfo(); |
10758 | |
10759 | LoadInfo* li = static_cast<LoadInfo*>(loadInfo.get()); |
10760 | if (loadInfo->GetExternalContentPolicyType() == |
10761 | ExtContentPolicy::TYPE_DOCUMENT) { |
10762 | li->UpdateBrowsingContextID(mBrowsingContext->Id()); |
10763 | } else if (loadInfo->GetExternalContentPolicyType() == |
10764 | ExtContentPolicy::TYPE_SUBDOCUMENT) { |
10765 | li->UpdateFrameBrowsingContextID(mBrowsingContext->Id()); |
10766 | } |
10767 | // TODO: more attributes need to be updated on the LoadInfo (bug 1561706) |
10768 | |
10769 | // If we did a process switch, then we should have an existing allocated |
10770 | // ClientInfo, so we just need to allocate a corresponding ClientSource. |
10771 | CreateReservedSourceIfNeeded(channel, GetMainThreadSerialEventTarget()); |
10772 | |
10773 | RefPtr<nsDocumentOpenInfo> loader = |
10774 | new nsDocumentOpenInfo(this, nsIURILoader::DONT_RETARGET, nullptr); |
10775 | channel->SetLoadGroup(mLoadGroup); |
10776 | |
10777 | 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" , 10777); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false" ") (" "NS_SUCCEEDED(loader->Prepare())" ")"); do { *((volatile int*)__null) = 10777; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); } } while (false); |
10778 | |
10779 | nsresult rv = NS_OK; |
10780 | if (XRE_IsParentProcess()) { |
10781 | // If we're in the parent, the we don't have an nsIChildChannel, just |
10782 | // the original channel, which is already open in this process. |
10783 | |
10784 | // DocumentLoadListener expects to get an nsIParentChannel, so |
10785 | // we create a wrapper around the channel and nsIStreamListener |
10786 | // that forwards functionality as needed, and then we register |
10787 | // it under the provided identifier. |
10788 | RefPtr<ParentChannelWrapper> wrapper = |
10789 | new ParentChannelWrapper(channel, loader); |
10790 | wrapper->Register(aLoadState->GetPendingRedirectChannelRegistrarId()); |
10791 | |
10792 | mLoadGroup->AddRequest(channel, nullptr); |
10793 | } else if (nsCOMPtr<nsIChildChannel> childChannel = |
10794 | do_QueryInterface(channel)) { |
10795 | // Our channel was redirected from another process, so doesn't need to |
10796 | // be opened again. However, it does need its listener hooked up |
10797 | // correctly. |
10798 | rv = childChannel->CompleteRedirectSetup(loader); |
10799 | } else { |
10800 | // It's possible for the redirected channel to not implement |
10801 | // nsIChildChannel and be entirely local (like srcdoc). In that case we |
10802 | // can just open the local instance and it will work. |
10803 | rv = channel->AsyncOpen(loader); |
10804 | } |
10805 | if (rv == NS_ERROR_NO_CONTENT) { |
10806 | return NS_OK; |
10807 | } |
10808 | 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" , 10808); return rv; } } while (false); |
10809 | |
10810 | // Success. Keep the initial ClientSource if it exists. |
10811 | cleanupInitialClient.release(); |
10812 | return NS_OK; |
10813 | } |
10814 | |
10815 | // https://html.spec.whatwg.org/#scrolling-to-a-fragment |
10816 | nsresult nsDocShell::ScrollToAnchor(bool aCurHasRef, bool aNewHasRef, |
10817 | nsACString& aNewHash, uint32_t aLoadType) { |
10818 | if (!mCurrentURI) { |
10819 | return NS_OK; |
10820 | } |
10821 | |
10822 | RefPtr<PresShell> presShell = GetPresShell(); |
10823 | if (!presShell) { |
10824 | // If we failed to get the shell, or if there is no shell, |
10825 | // nothing left to do here. |
10826 | return NS_OK; |
10827 | } |
10828 | |
10829 | nsIScrollableFrame* rootScroll = presShell->GetRootScrollFrameAsScrollable(); |
10830 | if (rootScroll) { |
10831 | rootScroll->ClearDidHistoryRestore(); |
10832 | } |
10833 | |
10834 | // If we have no new anchor, we do not want to scroll, unless there is a |
10835 | // current anchor and we are doing a history load. So return if we have no |
10836 | // new anchor, and there is no current anchor or the load is not a history |
10837 | // load. |
10838 | if ((!aCurHasRef || aLoadType != LOAD_HISTORY) && !aNewHasRef) { |
10839 | return NS_OK; |
10840 | } |
10841 | |
10842 | // Both the new and current URIs refer to the same page. We can now |
10843 | // browse to the hash stored in the new URI. |
10844 | |
10845 | // If it's a load from history, we don't have any anchor jumping to do. |
10846 | // Scrollbar position will be restored by the caller based on positions stored |
10847 | // in session history. |
10848 | bool scroll = aLoadType != LOAD_HISTORY && aLoadType != LOAD_RELOAD_NORMAL; |
10849 | |
10850 | if (aNewHash.IsEmpty()) { |
10851 | // 2. If fragment is the empty string, then return the special value top of |
10852 | // the document. |
10853 | // |
10854 | // Tell the shell it's at an anchor without scrolling. |
10855 | presShell->GoToAnchor(u""_ns, false); |
10856 | |
10857 | if (scroll) { |
10858 | // Scroll to the top of the page. Ignore the return value; failure to |
10859 | // scroll here (e.g. if there is no root scrollframe) is not grounds for |
10860 | // canceling the load! |
10861 | SetCurScrollPosEx(0, 0); |
10862 | } |
10863 | |
10864 | return NS_OK; |
10865 | } |
10866 | |
10867 | // 3. Let potentialIndicatedElement be the result of finding a potential |
10868 | // indicated element given document and fragment. |
10869 | NS_ConvertUTF8toUTF16 uStr(aNewHash); |
10870 | auto rv = presShell->GoToAnchor(uStr, scroll, ScrollFlags::ScrollSmoothAuto); |
10871 | |
10872 | // 4. If potentialIndicatedElement is not null, then return |
10873 | // potentialIndicatedElement. |
10874 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) { |
10875 | return NS_OK; |
10876 | } |
10877 | |
10878 | // 5. Let fragmentBytes be the result of percent-decoding fragment. |
10879 | nsAutoCString fragmentBytes; |
10880 | const bool unescaped = NS_UnescapeURL(aNewHash.Data(), aNewHash.Length(), |
10881 | /* aFlags = */ 0, fragmentBytes); |
10882 | |
10883 | if (!unescaped) { |
10884 | // Another attempt is only necessary if characters were unescaped. |
10885 | return NS_OK; |
10886 | } |
10887 | |
10888 | if (fragmentBytes.IsEmpty()) { |
10889 | // When aNewHash contains "%00", the unescaped string may be empty, and |
10890 | // GoToAnchor asserts if we ask it to scroll to an empty ref. |
10891 | presShell->GoToAnchor(u""_ns, false); |
10892 | return NS_OK; |
10893 | } |
10894 | |
10895 | // 6. Let decodedFragment be the result of running UTF-8 decode without BOM on |
10896 | // fragmentBytes. |
10897 | nsAutoString decodedFragment; |
10898 | rv = UTF_8_ENCODING->DecodeWithoutBOMHandling(fragmentBytes, decodedFragment); |
10899 | 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" , 10899); return rv; } } while (false); |
10900 | |
10901 | // 7. Set potentialIndicatedElement to the result of finding a potential |
10902 | // indicated element given document and decodedFragment. |
10903 | // |
10904 | // Ignore the return value of GoToAnchor, since it will return an error if |
10905 | // there is no such anchor in the document, which is actually a success |
10906 | // condition for us (we want to update the session history with the new URI no |
10907 | // matter whether we actually scrolled somewhere). |
10908 | presShell->GoToAnchor(decodedFragment, scroll, ScrollFlags::ScrollSmoothAuto); |
10909 | |
10910 | return NS_OK; |
10911 | } |
10912 | |
10913 | bool nsDocShell::OnNewURI(nsIURI* aURI, nsIChannel* aChannel, |
10914 | nsIPrincipal* aTriggeringPrincipal, |
10915 | nsIPrincipal* aPrincipalToInherit, |
10916 | nsIPrincipal* aPartitionedPrincipalToInherit, |
10917 | nsIContentSecurityPolicy* aCsp, |
10918 | bool aAddToGlobalHistory, bool aCloneSHChildren) { |
10919 | 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" , 10919); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aURI" ") (" "uri is null" ")"); do { *((volatile int*)__null) = 10919; __attribute__ ((nomerge)) ::abort(); } while (false); } } while (false); |
10920 | 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" , 10920); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aChannel || !aTriggeringPrincipal" ") (" "Shouldn't have both set" ")"); do { *((volatile int*) __null) = 10920; __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); |
10921 | |
10922 | 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" , 10923); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aPrincipalToInherit || (aPrincipalToInherit && aTriggeringPrincipal)" ")"); do { *((volatile int*)__null) = 10923; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false) |
10923 | (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" , 10923); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aPrincipalToInherit || (aPrincipalToInherit && aTriggeringPrincipal)" ")"); do { *((volatile int*)__null) = 10923; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
10924 | |
10925 | #if defined(DEBUG1) |
10926 | if (MOZ_LOG_TEST(gDocShellLog, LogLevel::Debug)(__builtin_expect(!!(mozilla::detail::log_test(gDocShellLog, LogLevel ::Debug)), 0))) { |
10927 | nsAutoCString chanName; |
10928 | if (aChannel) { |
10929 | aChannel->GetName(chanName); |
10930 | } else { |
10931 | chanName.AssignLiteral("<no channel>"); |
10932 | } |
10933 | |
10934 | 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) |
10935 | ("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) |
10936 | 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); |
10937 | } |
10938 | #endif |
10939 | |
10940 | bool equalUri = false; |
10941 | |
10942 | // Get the post data and the HTTP response code from the channel. |
10943 | uint32_t responseStatus = 0; |
10944 | nsCOMPtr<nsIInputStream> inputStream; |
10945 | if (aChannel) { |
10946 | nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(aChannel)); |
10947 | |
10948 | // Check if the HTTPChannel is hiding under a multiPartChannel |
10949 | if (!httpChannel) { |
10950 | GetHttpChannel(aChannel, getter_AddRefs(httpChannel)); |
10951 | } |
10952 | |
10953 | if (httpChannel) { |
10954 | nsCOMPtr<nsIUploadChannel> uploadChannel(do_QueryInterface(httpChannel)); |
10955 | if (uploadChannel) { |
10956 | uploadChannel->GetUploadStream(getter_AddRefs(inputStream)); |
10957 | } |
10958 | |
10959 | // If the response status indicates an error, unlink this session |
10960 | // history entry from any entries sharing its document. |
10961 | nsresult rv = httpChannel->GetResponseStatus(&responseStatus); |
10962 | if (mLSHE && NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && responseStatus >= 400) { |
10963 | mLSHE->AbandonBFCacheEntry(); |
10964 | // FIXME Do the same for mLoadingEntry |
10965 | } |
10966 | } |
10967 | } |
10968 | |
10969 | // Determine if this type of load should update history. |
10970 | bool updateGHistory = ShouldUpdateGlobalHistory(mLoadType); |
10971 | |
10972 | // We don't update session history on reload unless we're loading |
10973 | // an iframe in shift-reload case. |
10974 | bool updateSHistory = mBrowsingContext->ShouldUpdateSessionHistory(mLoadType); |
10975 | |
10976 | // Create SH Entry (mLSHE) only if there is a SessionHistory object in the |
10977 | // root browsing context. |
10978 | // FIXME If session history in the parent is enabled then we only do this if |
10979 | // the session history object is in process, otherwise we can't really |
10980 | // use the mLSHE anyway. Once session history is only stored in the |
10981 | // parent then this code will probably be removed anyway. |
10982 | RefPtr<ChildSHistory> rootSH = GetRootSessionHistory(); |
10983 | if (!rootSH) { |
10984 | updateSHistory = false; |
10985 | updateGHistory = false; // XXX Why global history too? |
10986 | } |
10987 | |
10988 | // Check if the url to be loaded is the same as the one already loaded. |
10989 | if (mCurrentURI) { |
10990 | aURI->Equals(mCurrentURI, &equalUri); |
10991 | } |
10992 | |
10993 | #ifdef DEBUG1 |
10994 | bool shAvailable = (rootSH != nullptr); |
10995 | |
10996 | // XXX This log message is almost useless because |updateSHistory| |
10997 | // and |updateGHistory| are not correct at this point. |
10998 | |
10999 | 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) |
11000 | (" 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) |
11001 | " 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) |
11002 | 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); |
11003 | #endif |
11004 | |
11005 | /* If the url to be loaded is the same as the one already there, |
11006 | * and the original loadType is LOAD_NORMAL, LOAD_LINK, or |
11007 | * LOAD_STOP_CONTENT, set loadType to LOAD_NORMAL_REPLACE so that |
11008 | * AddToSessionHistory() won't mess with the current SHEntry and |
11009 | * if this page has any frame children, it also will be handled |
11010 | * properly. see bug 83684 |
11011 | * |
11012 | * NB: If mOSHE is null but we have a current URI, then it probably |
11013 | * means that we must be at the transient about:blank content viewer; |
11014 | * we should let the normal load continue, since there's nothing to |
11015 | * replace. Sometimes this happens after a session restore (eg process |
11016 | * switch) and mCurrentURI is not about:blank; we assume we can let the load |
11017 | * continue (Bug 1301399). |
11018 | * |
11019 | * XXX Hopefully changing the loadType at this time will not hurt |
11020 | * anywhere. The other way to take care of sequentially repeating |
11021 | * frameset pages is to add new methods to nsIDocShellTreeItem. |
11022 | * Hopefully I don't have to do that. |
11023 | */ |
11024 | if (equalUri && |
11025 | (mozilla::SessionHistoryInParent() ? !!mActiveEntry : !!mOSHE) && |
11026 | (mLoadType == LOAD_NORMAL || mLoadType == LOAD_LINK || |
11027 | mLoadType == LOAD_STOP_CONTENT) && |
11028 | !inputStream) { |
11029 | mLoadType = LOAD_NORMAL_REPLACE; |
11030 | } |
11031 | |
11032 | // If this is a refresh to the currently loaded url, we don't |
11033 | // have to update session or global history. |
11034 | if (mLoadType == LOAD_REFRESH && !inputStream && equalUri) { |
11035 | SetHistoryEntryAndUpdateBC(Some<nsISHEntry*>(mOSHE), Nothing()); |
11036 | } |
11037 | |
11038 | /* If the user pressed shift-reload, cache will create a new cache key |
11039 | * for the page. Save the new cacheKey in Session History. |
11040 | * see bug 90098 |
11041 | */ |
11042 | if (aChannel && IsForceReloadType(mLoadType)) { |
11043 | 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" , 11045); 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) = 11045; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false) |
11044 | "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" , 11045); 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) = 11045; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false) |
11045 | " 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" , 11045); 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) = 11045; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
11046 | |
11047 | nsCOMPtr<nsICacheInfoChannel> cacheChannel(do_QueryInterface(aChannel)); |
11048 | uint32_t cacheKey = 0; |
11049 | // Get the Cache Key and store it in SH. |
11050 | if (cacheChannel) { |
11051 | cacheChannel->GetCacheKey(&cacheKey); |
11052 | } |
11053 | // If we already have a loading history entry, store the new cache key |
11054 | // in it. Otherwise, since we're doing a reload and won't be updating |
11055 | // our history entry, store the cache key in our current history entry. |
11056 | SetCacheKeyOnHistoryEntry(mLSHE ? mLSHE : mOSHE, cacheKey); |
11057 | |
11058 | if (!mozilla::SessionHistoryInParent()) { |
11059 | // Since we're force-reloading, clear all the sub frame history. |
11060 | ClearFrameHistory(mLSHE); |
11061 | ClearFrameHistory(mOSHE); |
11062 | } |
11063 | } |
11064 | |
11065 | if (!mozilla::SessionHistoryInParent()) { |
11066 | // Clear subframe history on refresh. |
11067 | // XXX: history.go(0) won't go this path as mLoadType is LOAD_HISTORY in |
11068 | // this case. One should re-validate after bug 1331865 fixed. |
11069 | if (mLoadType == LOAD_REFRESH) { |
11070 | ClearFrameHistory(mLSHE); |
11071 | ClearFrameHistory(mOSHE); |
11072 | } |
11073 | |
11074 | if (updateSHistory) { |
11075 | // Update session history if necessary... |
11076 | if (!mLSHE && (mItemType == typeContent) && mURIResultedInDocument) { |
11077 | /* This is a fresh page getting loaded for the first time |
11078 | *.Create a Entry for it and add it to SH, if this is the |
11079 | * rootDocShell |
11080 | */ |
11081 | (void)AddToSessionHistory(aURI, aChannel, aTriggeringPrincipal, |
11082 | aPrincipalToInherit, |
11083 | aPartitionedPrincipalToInherit, aCsp, |
11084 | aCloneSHChildren, getter_AddRefs(mLSHE)); |
11085 | } |
11086 | } else if (GetSessionHistory() && mLSHE && mURIResultedInDocument) { |
11087 | // Even if we don't add anything to SHistory, ensure the current index |
11088 | // points to the same SHEntry as our mLSHE. |
11089 | |
11090 | GetSessionHistory()->LegacySHistory()->EnsureCorrectEntryAtCurrIndex( |
11091 | mLSHE); |
11092 | } |
11093 | } |
11094 | |
11095 | // If this is a POST request, we do not want to include this in global |
11096 | // history. |
11097 | if (ShouldAddURIVisit(aChannel) && updateGHistory && aAddToGlobalHistory && |
11098 | !net::ChannelIsPost(aChannel)) { |
11099 | nsCOMPtr<nsIURI> previousURI; |
11100 | uint32_t previousFlags = 0; |
11101 | |
11102 | if (mLoadType & LOAD_CMD_RELOAD) { |
11103 | // On a reload request, we don't set redirecting flags. |
11104 | previousURI = aURI; |
11105 | } else { |
11106 | ExtractLastVisit(aChannel, getter_AddRefs(previousURI), &previousFlags); |
11107 | } |
11108 | |
11109 | AddURIVisit(aURI, previousURI, previousFlags, responseStatus); |
11110 | } |
11111 | |
11112 | // If this was a history load or a refresh, or it was a history load but |
11113 | // later changed to LOAD_NORMAL_REPLACE due to redirection, update the index |
11114 | // in session history. |
11115 | if (!mozilla::SessionHistoryInParent() && rootSH && |
11116 | ((mLoadType & (LOAD_CMD_HISTORY | LOAD_CMD_RELOAD)) || |
11117 | mLoadType == LOAD_NORMAL_REPLACE || mLoadType == LOAD_REFRESH_REPLACE)) { |
11118 | mPreviousEntryIndex = rootSH->Index(); |
11119 | if (!mozilla::SessionHistoryInParent()) { |
11120 | rootSH->LegacySHistory()->UpdateIndex(); |
11121 | } |
11122 | mLoadedEntryIndex = rootSH->Index(); |
11123 | 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) |
11124 | ("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) |
11125 | 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); |
11126 | } |
11127 | |
11128 | // aCloneSHChildren exactly means "we are not loading a new document". |
11129 | uint32_t locationFlags = |
11130 | aCloneSHChildren ? uint32_t(LOCATION_CHANGE_SAME_DOCUMENT) : 0; |
11131 | |
11132 | bool onLocationChangeNeeded = |
11133 | SetCurrentURI(aURI, aChannel, false, |
11134 | /* aIsInitialAboutBlank */ false, locationFlags); |
11135 | // Make sure to store the referrer from the channel, if any |
11136 | nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(aChannel)); |
11137 | if (httpChannel) { |
11138 | mReferrerInfo = httpChannel->GetReferrerInfo(); |
11139 | } |
11140 | return onLocationChangeNeeded; |
11141 | } |
11142 | |
11143 | Maybe<Wireframe> nsDocShell::GetWireframe() { |
11144 | const bool collectWireFrame = |
11145 | mozilla::SessionHistoryInParent() && |
11146 | StaticPrefs::browser_history_collectWireframes() && |
11147 | mBrowsingContext->IsTopContent() && mActiveEntry; |
11148 | |
11149 | if (!collectWireFrame) { |
11150 | return Nothing(); |
11151 | } |
11152 | |
11153 | RefPtr<Document> doc = mDocumentViewer->GetDocument(); |
11154 | Nullable<Wireframe> wireframe; |
11155 | doc->GetWireframeWithoutFlushing(false, wireframe); |
11156 | if (wireframe.IsNull()) { |
11157 | return Nothing(); |
11158 | } |
11159 | return Some(wireframe.Value()); |
11160 | } |
11161 | |
11162 | bool nsDocShell::CollectWireframe() { |
11163 | Maybe<Wireframe> wireframe = GetWireframe(); |
11164 | if (wireframe.isNothing()) { |
11165 | return false; |
11166 | } |
11167 | |
11168 | if (XRE_IsParentProcess()) { |
11169 | SessionHistoryEntry* entry = |
11170 | mBrowsingContext->Canonical()->GetActiveSessionHistoryEntry(); |
11171 | if (entry) { |
11172 | entry->SetWireframe(wireframe); |
11173 | } |
11174 | } else { |
11175 | mozilla::Unused |
11176 | << ContentChild::GetSingleton()->SendSessionHistoryEntryWireframe( |
11177 | mBrowsingContext, wireframe.ref()); |
11178 | } |
11179 | |
11180 | return true; |
11181 | } |
11182 | |
11183 | //***************************************************************************** |
11184 | // nsDocShell: Session History |
11185 | //***************************************************************************** |
11186 | |
11187 | NS_IMETHODIMPnsresult |
11188 | nsDocShell::AddState(JS::Handle<JS::Value> aData, const nsAString& aTitle, |
11189 | const nsAString& aURL, bool aReplace, JSContext* aCx) { |
11190 | 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) |
11191 | ("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) |
11192 | 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) |
11193 | 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); |
11194 | // Implements History.pushState and History.replaceState |
11195 | |
11196 | // Here's what we do, roughly in the order specified by HTML5. The specific |
11197 | // steps we are executing are at |
11198 | // <https://html.spec.whatwg.org/multipage/history.html#dom-history-pushstate> |
11199 | // and |
11200 | // <https://html.spec.whatwg.org/multipage/history.html#url-and-history-update-steps>. |
11201 | // This function basically implements #dom-history-pushstate and |
11202 | // UpdateURLAndHistory implements #url-and-history-update-steps. |
11203 | // |
11204 | // A. Serialize aData using structured clone. This is #dom-history-pushstate |
11205 | // step 5. |
11206 | // B. If the third argument is present, #dom-history-pushstate step 7. |
11207 | // 7.1. Resolve the url, relative to our document. |
11208 | // 7.2. If (a) fails, raise a SECURITY_ERR |
11209 | // 7.4. Compare the resulting absolute URL to the document's address. If |
11210 | // any part of the URLs difer other than the <path>, <query>, and |
11211 | // <fragment> components, raise a SECURITY_ERR and abort. |
11212 | // C. If !aReplace, #url-and-history-update-steps steps 2.1-2.3: |
11213 | // Remove from the session history all entries after the current entry, |
11214 | // as we would after a regular navigation, and save the current |
11215 | // entry's scroll position (bug 590573). |
11216 | // D. #url-and-history-update-steps step 2.4 or step 3. As apropriate, |
11217 | // either add a state object entry to the session history after the |
11218 | // current entry with the following properties, or modify the current |
11219 | // session history entry to set |
11220 | // a. cloned data as the state object, |
11221 | // b. if the third argument was present, the absolute URL found in |
11222 | // step 2 |
11223 | // Also clear the new history entry's POST data (see bug 580069). |
11224 | // E. If aReplace is false (i.e. we're doing a pushState instead of a |
11225 | // replaceState), notify bfcache that we've navigated to a new page. |
11226 | // F. If the third argument is present, set the document's current address |
11227 | // to the absolute URL found in step B. This is |
11228 | // #url-and-history-update-steps step 4. |
11229 | // |
11230 | // It's important that this function not run arbitrary scripts after step A |
11231 | // and before completing step E. For example, if a script called |
11232 | // history.back() before we completed step E, bfcache might destroy an |
11233 | // active content viewer. Since EvictOutOfRangeDocumentViewers at the end of |
11234 | // step E might run script, we can't just put a script blocker around the |
11235 | // critical section. |
11236 | // |
11237 | // Note that we completely ignore the aTitle parameter. |
11238 | |
11239 | nsresult rv; |
11240 | |
11241 | // Don't clobber the load type of an existing network load. |
11242 | AutoRestore<uint32_t> loadTypeResetter(mLoadType); |
11243 | |
11244 | // pushState effectively becomes replaceState when we've started a network |
11245 | // load but haven't adopted its document yet. This mirrors what we do with |
11246 | // changes to the hash at this stage of the game. |
11247 | if (JustStartedNetworkLoad()) { |
11248 | aReplace = true; |
11249 | } |
11250 | |
11251 | RefPtr<Document> document = GetDocument(); |
11252 | 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" , 11252); return NS_ERROR_FAILURE; } } while (false); |
11253 | |
11254 | // Step A: Serialize aData using structured clone. |
11255 | // https://html.spec.whatwg.org/multipage/history.html#dom-history-pushstate |
11256 | // step 5. |
11257 | nsCOMPtr<nsIStructuredCloneContainer> scContainer; |
11258 | |
11259 | // scContainer->Init might cause arbitrary JS to run, and this code might |
11260 | // navigate the page we're on, potentially to a different origin! (bug |
11261 | // 634834) To protect against this, we abort if our principal changes due |
11262 | // to the InitFromJSVal() call. |
11263 | { |
11264 | RefPtr<Document> origDocument = GetDocument(); |
11265 | if (!origDocument) { |
11266 | return NS_ERROR_DOM_SECURITY_ERR; |
11267 | } |
11268 | nsCOMPtr<nsIPrincipal> origPrincipal = origDocument->NodePrincipal(); |
11269 | |
11270 | scContainer = new nsStructuredCloneContainer(); |
11271 | rv = scContainer->InitFromJSVal(aData, aCx); |
11272 | 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" , 11272); return rv; } } while (false); |
11273 | |
11274 | RefPtr<Document> newDocument = GetDocument(); |
11275 | if (!newDocument) { |
11276 | return NS_ERROR_DOM_SECURITY_ERR; |
11277 | } |
11278 | nsCOMPtr<nsIPrincipal> newPrincipal = newDocument->NodePrincipal(); |
11279 | |
11280 | bool principalsEqual = false; |
11281 | origPrincipal->Equals(newPrincipal, &principalsEqual); |
11282 | 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" , 11282); return NS_ERROR_DOM_SECURITY_ERR; } } while (false); |
11283 | } |
11284 | |
11285 | // Check that the state object isn't too long. |
11286 | int32_t maxStateObjSize = StaticPrefs::browser_history_maxStateObjectSize(); |
11287 | if (maxStateObjSize < 0) { |
11288 | maxStateObjSize = 0; |
11289 | } |
11290 | |
11291 | uint64_t scSize; |
11292 | rv = scContainer->GetSerializedNBytes(&scSize); |
11293 | 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" , 11293); return rv; } } while (false); |
11294 | |
11295 | 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" , 11295); return NS_ERROR_ILLEGAL_VALUE; } } while (false); |
11296 | |
11297 | // Step B: Resolve aURL. |
11298 | // https://html.spec.whatwg.org/multipage/history.html#dom-history-pushstate |
11299 | // step 7. |
11300 | bool equalURIs = true; |
11301 | nsCOMPtr<nsIURI> currentURI; |
11302 | if (mCurrentURI) { |
11303 | currentURI = nsIOService::CreateExposableURI(mCurrentURI); |
11304 | } else { |
11305 | currentURI = mCurrentURI; |
11306 | } |
11307 | nsCOMPtr<nsIURI> newURI; |
11308 | if (aURL.Length() == 0) { |
11309 | newURI = currentURI; |
11310 | } else { |
11311 | // 7.1: Resolve aURL relative to mURI |
11312 | |
11313 | nsIURI* docBaseURI = document->GetDocBaseURI(); |
11314 | if (!docBaseURI) { |
11315 | return NS_ERROR_FAILURE; |
11316 | } |
11317 | |
11318 | nsAutoCString spec; |
11319 | docBaseURI->GetSpec(spec); |
11320 | |
11321 | rv = NS_NewURI(getter_AddRefs(newURI), aURL, |
11322 | document->GetDocumentCharacterSet(), docBaseURI); |
11323 | |
11324 | // 7.2: If 2a fails, raise a SECURITY_ERR |
11325 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
11326 | return NS_ERROR_DOM_SECURITY_ERR; |
11327 | } |
11328 | |
11329 | // 7.4 and 7.5: Same-origin check. |
11330 | if (!nsContentUtils::URIIsLocalFile(newURI)) { |
11331 | // In addition to checking that the security manager says that |
11332 | // the new URI has the same origin as our current URI, we also |
11333 | // check that the two URIs have the same userpass. (The |
11334 | // security manager says that |http://foo.com| and |
11335 | // |http://me@foo.com| have the same origin.) currentURI |
11336 | // won't contain the password part of the userpass, so this |
11337 | // means that it's never valid to specify a password in a |
11338 | // pushState or replaceState URI. |
11339 | |
11340 | nsCOMPtr<nsIScriptSecurityManager> secMan = |
11341 | do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID"@mozilla.org/scriptsecuritymanager;1"); |
11342 | 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" , 11342); return NS_ERROR_FAILURE; } } while (false); |
11343 | |
11344 | // It's very important that we check that newURI is of the same |
11345 | // origin as currentURI, not docBaseURI, because a page can |
11346 | // set docBaseURI arbitrarily to any domain. |
11347 | nsAutoCString currentUserPass, newUserPass; |
11348 | 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" , 11349); return NS_ERROR_FAILURE; } } while (false) |
11349 | 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" , 11349); return NS_ERROR_FAILURE; } } while (false); |
11350 | 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" , 11350); return NS_ERROR_FAILURE; } } while (false); |
11351 | bool isPrivateWin = |
11352 | document->NodePrincipal()->OriginAttributesRef().mPrivateBrowsingId > |
11353 | 0; |
11354 | if (NS_FAILED(secMan->CheckSameOriginURI(currentURI, newURI, true,((bool)(__builtin_expect(!!(NS_FAILED_impl(secMan->CheckSameOriginURI (currentURI, newURI, true, isPrivateWin))), 0))) |
11355 | isPrivateWin))((bool)(__builtin_expect(!!(NS_FAILED_impl(secMan->CheckSameOriginURI (currentURI, newURI, true, isPrivateWin))), 0))) || |
11356 | !currentUserPass.Equals(newUserPass)) { |
11357 | return NS_ERROR_DOM_SECURITY_ERR; |
11358 | } |
11359 | } else { |
11360 | // It's a file:// URI |
11361 | nsCOMPtr<nsIPrincipal> principal = document->GetPrincipal(); |
11362 | |
11363 | if (!principal || NS_FAILED(principal->CheckMayLoadWithReporting(((bool)(__builtin_expect(!!(NS_FAILED_impl(principal->CheckMayLoadWithReporting ( newURI, false, document->InnerWindowID()))), 0))) |
11364 | newURI, false, document->InnerWindowID()))((bool)(__builtin_expect(!!(NS_FAILED_impl(principal->CheckMayLoadWithReporting ( newURI, false, document->InnerWindowID()))), 0)))) { |
11365 | return NS_ERROR_DOM_SECURITY_ERR; |
11366 | } |
11367 | } |
11368 | |
11369 | if (currentURI) { |
11370 | currentURI->Equals(newURI, &equalURIs); |
11371 | } else { |
11372 | equalURIs = false; |
11373 | } |
11374 | |
11375 | } // end of same-origin check |
11376 | |
11377 | // Step 8: call "URL and history update steps" |
11378 | rv = UpdateURLAndHistory(document, newURI, scContainer, aTitle, aReplace, |
11379 | currentURI, equalURIs); |
11380 | 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" , 11380); return rv; } } while (false); |
11381 | |
11382 | return NS_OK; |
11383 | } |
11384 | |
11385 | nsresult nsDocShell::UpdateURLAndHistory(Document* aDocument, nsIURI* aNewURI, |
11386 | nsIStructuredCloneContainer* aData, |
11387 | const nsAString& aTitle, bool aReplace, |
11388 | nsIURI* aCurrentURI, bool aEqualURIs) { |
11389 | // Implements |
11390 | // https://html.spec.whatwg.org/multipage/history.html#url-and-history-update-steps |
11391 | |
11392 | // If we have a pending title change, handle it before creating a new entry. |
11393 | aDocument->DoNotifyPossibleTitleChange(); |
11394 | |
11395 | // Step 2, if aReplace is false: Create a new entry in the session |
11396 | // history. This will erase all SHEntries after the new entry and make this |
11397 | // entry the current one. This operation may modify mOSHE, which we need |
11398 | // later, so we keep a reference here. |
11399 | 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" , 11399); return NS_ERROR_FAILURE; } } while (false); |
11400 | nsCOMPtr<nsISHEntry> oldOSHE = mOSHE; |
11401 | |
11402 | // If this push/replaceState changed the document's current URI and the new |
11403 | // URI differs from the old URI in more than the hash, or if the old |
11404 | // SHEntry's URI was modified in this way by a push/replaceState call |
11405 | // set URIWasModified to true for the current SHEntry (bug 669671). |
11406 | bool sameExceptHashes = true; |
11407 | aNewURI->EqualsExceptRef(aCurrentURI, &sameExceptHashes); |
11408 | bool uriWasModified; |
11409 | if (sameExceptHashes) { |
11410 | if (mozilla::SessionHistoryInParent()) { |
11411 | uriWasModified = mActiveEntry && mActiveEntry->GetURIWasModified(); |
11412 | } else { |
11413 | uriWasModified = oldOSHE && oldOSHE->GetURIWasModified(); |
11414 | } |
11415 | } else { |
11416 | uriWasModified = true; |
11417 | } |
11418 | |
11419 | mLoadType = LOAD_PUSHSTATE; |
11420 | |
11421 | nsCOMPtr<nsISHEntry> newSHEntry; |
11422 | if (!aReplace) { |
11423 | // Step 2. |
11424 | |
11425 | // Step 2.2, "Remove any tasks queued by the history traversal task |
11426 | // source that are associated with any Document objects in the |
11427 | // top-level browsing context's document family." This is very hard in |
11428 | // SessionHistoryInParent since we can't synchronously access the |
11429 | // pending navigations that are already sent to the parent. We can |
11430 | // abort any AsyncGo navigations that are waiting to be sent. If we |
11431 | // send a message to the parent, it would be processed after any |
11432 | // navigations previously sent. So long as we consider the "history |
11433 | // traversal task source" to be the list in this process we match the |
11434 | // spec. If we move the entire list to the parent, we can handle the |
11435 | // aborting of loads there, but we don't have a way to synchronously |
11436 | // remove entries as we do here for non-SHIP. |
11437 | RefPtr<ChildSHistory> shistory = GetRootSessionHistory(); |
11438 | if (shistory) { |
11439 | shistory->RemovePendingHistoryNavigations(); |
11440 | } |
11441 | |
11442 | nsPoint scrollPos = GetCurScrollPos(); |
11443 | |
11444 | bool scrollRestorationIsManual; |
11445 | if (mozilla::SessionHistoryInParent()) { |
11446 | // FIXME Need to save the current scroll position on mActiveEntry. |
11447 | scrollRestorationIsManual = mActiveEntry->GetScrollRestorationIsManual(); |
11448 | } else { |
11449 | // Save the current scroll position (bug 590573). Step 2.3. |
11450 | mOSHE->SetScrollPosition(scrollPos.x, scrollPos.y); |
11451 | |
11452 | scrollRestorationIsManual = mOSHE->GetScrollRestorationIsManual(); |
11453 | } |
11454 | |
11455 | nsCOMPtr<nsIContentSecurityPolicy> csp = aDocument->GetCsp(); |
11456 | |
11457 | if (mozilla::SessionHistoryInParent()) { |
11458 | 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) |
11459 | ("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); |
11460 | nsString title(mActiveEntry->GetTitle()); |
11461 | UpdateActiveEntry(false, |
11462 | /* aPreviousScrollPos = */ Some(scrollPos), aNewURI, |
11463 | /* aOriginalURI = */ nullptr, |
11464 | /* aReferrerInfo = */ nullptr, |
11465 | /* aTriggeringPrincipal = */ aDocument->NodePrincipal(), |
11466 | csp, title, scrollRestorationIsManual, aData, |
11467 | uriWasModified); |
11468 | } else { |
11469 | // Since we're not changing which page we have loaded, pass |
11470 | // true for aCloneChildren. |
11471 | nsresult rv = AddToSessionHistory( |
11472 | aNewURI, nullptr, |
11473 | aDocument->NodePrincipal(), // triggeringPrincipal |
11474 | nullptr, nullptr, csp, true, getter_AddRefs(newSHEntry)); |
11475 | 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" , 11475); return rv; } } while (false); |
11476 | |
11477 | 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" , 11477); return NS_ERROR_FAILURE; } } while (false); |
11478 | |
11479 | // Session history entries created by pushState inherit scroll restoration |
11480 | // mode from the current entry. |
11481 | newSHEntry->SetScrollRestorationIsManual(scrollRestorationIsManual); |
11482 | |
11483 | nsString title; |
11484 | mOSHE->GetTitle(title); |
11485 | |
11486 | // Set the new SHEntry's title (bug 655273). |
11487 | newSHEntry->SetTitle(title); |
11488 | |
11489 | // Link the new SHEntry to the old SHEntry's BFCache entry, since the |
11490 | // two entries correspond to the same document. |
11491 | 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" , 11492); return NS_ERROR_FAILURE; } } while (false) |
11492 | 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" , 11492); return NS_ERROR_FAILURE; } } while (false); |
11493 | |
11494 | // AddToSessionHistory may not modify mOSHE. In case it doesn't, |
11495 | // we'll just set mOSHE here. |
11496 | mOSHE = newSHEntry; |
11497 | } |
11498 | } else if (mozilla::SessionHistoryInParent()) { |
11499 | 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) |
11500 | ("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) |
11501 | 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); |
11502 | // Setting the resultPrincipalURI to nullptr is fine here: it will cause |
11503 | // NS_GetFinalChannelURI to use the originalURI as the URI, which is aNewURI |
11504 | // in our case. We could also set it to aNewURI, with the same result. |
11505 | // We don't use aTitle here, see bug 544535. |
11506 | nsString title; |
11507 | nsCOMPtr<nsIReferrerInfo> referrerInfo; |
11508 | if (mActiveEntry) { |
11509 | title = mActiveEntry->GetTitle(); |
11510 | referrerInfo = mActiveEntry->GetReferrerInfo(); |
11511 | } else { |
11512 | referrerInfo = nullptr; |
11513 | } |
11514 | UpdateActiveEntry( |
11515 | true, /* aPreviousScrollPos = */ Nothing(), aNewURI, aNewURI, |
11516 | /* aReferrerInfo = */ referrerInfo, aDocument->NodePrincipal(), |
11517 | aDocument->GetCsp(), title, |
11518 | mActiveEntry && mActiveEntry->GetScrollRestorationIsManual(), aData, |
11519 | uriWasModified); |
11520 | } else { |
11521 | // Step 3. |
11522 | newSHEntry = mOSHE; |
11523 | |
11524 | 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); |
11525 | // Since we're not changing which page we have loaded, pass |
11526 | // true for aCloneChildren. |
11527 | if (!newSHEntry) { |
11528 | nsresult rv = AddToSessionHistory( |
11529 | aNewURI, nullptr, |
11530 | aDocument->NodePrincipal(), // triggeringPrincipal |
11531 | nullptr, nullptr, aDocument->GetCsp(), true, |
11532 | getter_AddRefs(newSHEntry)); |
11533 | 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" , 11533); return rv; } } while (false); |
11534 | mOSHE = newSHEntry; |
11535 | } |
11536 | |
11537 | newSHEntry->SetURI(aNewURI); |
11538 | newSHEntry->SetOriginalURI(aNewURI); |
11539 | // We replaced the URI of the entry, clear the unstripped URI as it |
11540 | // shouldn't be used for reloads anymore. |
11541 | newSHEntry->SetUnstrippedURI(nullptr); |
11542 | // Setting the resultPrincipalURI to nullptr is fine here: it will cause |
11543 | // NS_GetFinalChannelURI to use the originalURI as the URI, which is aNewURI |
11544 | // in our case. We could also set it to aNewURI, with the same result. |
11545 | newSHEntry->SetResultPrincipalURI(nullptr); |
11546 | newSHEntry->SetLoadReplace(false); |
11547 | } |
11548 | |
11549 | if (!mozilla::SessionHistoryInParent()) { |
11550 | // Step 2.4 and 3: Modify new/original session history entry and clear its |
11551 | // POST data, if there is any. |
11552 | newSHEntry->SetStateData(aData); |
11553 | newSHEntry->SetPostData(nullptr); |
11554 | |
11555 | newSHEntry->SetURIWasModified(uriWasModified); |
11556 | |
11557 | // Step E as described at the top of AddState: If aReplace is false, |
11558 | // indicating that we're doing a pushState rather than a replaceState, |
11559 | // notify bfcache that we've added a page to the history so it can evict |
11560 | // content viewers if appropriate. Otherwise call ReplaceEntry so that we |
11561 | // notify nsIHistoryListeners that an entry was replaced. We may not have a |
11562 | // root session history if this call is coming from a document.open() in a |
11563 | // docshell subtree that disables session history. |
11564 | RefPtr<ChildSHistory> rootSH = GetRootSessionHistory(); |
11565 | if (rootSH) { |
11566 | rootSH->LegacySHistory()->EvictDocumentViewersOrReplaceEntry(newSHEntry, |
11567 | aReplace); |
11568 | } |
11569 | } |
11570 | |
11571 | // Step 4: If the document's URI changed, update document's URI and update |
11572 | // global history. |
11573 | // |
11574 | // We need to call FireOnLocationChange so that the browser's address bar |
11575 | // gets updated and the back button is enabled, but we only need to |
11576 | // explicitly call FireOnLocationChange if we're not calling SetCurrentURI, |
11577 | // since SetCurrentURI will call FireOnLocationChange for us. |
11578 | // |
11579 | // Both SetCurrentURI(...) and FireDummyOnLocationChange() pass |
11580 | // nullptr for aRequest param to FireOnLocationChange(...). Such an update |
11581 | // notification is allowed only when we know docshell is not loading a new |
11582 | // document and it requires LOCATION_CHANGE_SAME_DOCUMENT flag. Otherwise, |
11583 | // FireOnLocationChange(...) breaks security UI. |
11584 | // |
11585 | // If the docshell is shutting down, don't update the document URI, as we |
11586 | // can't load into a docshell that is being destroyed. |
11587 | if (!aEqualURIs && !mIsBeingDestroyed) { |
11588 | aDocument->SetDocumentURI(aNewURI); |
11589 | SetCurrentURI(aNewURI, nullptr, /* aFireLocationChange */ true, |
11590 | /* aIsInitialAboutBlank */ false, |
11591 | GetSameDocumentNavigationFlags(aNewURI)); |
11592 | |
11593 | AddURIVisit(aNewURI, aCurrentURI, 0); |
11594 | |
11595 | // AddURIVisit doesn't set the title for the new URI in global history, |
11596 | // so do that here. |
11597 | UpdateGlobalHistoryTitle(aNewURI); |
11598 | |
11599 | // Inform the favicon service that our old favicon applies to this new |
11600 | // URI. |
11601 | CopyFavicon(aCurrentURI, aNewURI, UsePrivateBrowsing()); |
11602 | } else { |
11603 | FireDummyOnLocationChange(); |
11604 | } |
11605 | aDocument->SetStateObject(aData); |
11606 | |
11607 | return NS_OK; |
11608 | } |
11609 | |
11610 | NS_IMETHODIMPnsresult |
11611 | nsDocShell::GetCurrentScrollRestorationIsManual(bool* aIsManual) { |
11612 | if (mozilla::SessionHistoryInParent()) { |
11613 | *aIsManual = mActiveEntry && mActiveEntry->GetScrollRestorationIsManual(); |
11614 | return NS_OK; |
11615 | } |
11616 | |
11617 | *aIsManual = false; |
11618 | if (mOSHE) { |
11619 | return mOSHE->GetScrollRestorationIsManual(aIsManual); |
11620 | } |
11621 | |
11622 | return NS_OK; |
11623 | } |
11624 | |
11625 | NS_IMETHODIMPnsresult |
11626 | nsDocShell::SetCurrentScrollRestorationIsManual(bool aIsManual) { |
11627 | SetScrollRestorationIsManualOnHistoryEntry(mOSHE, aIsManual); |
11628 | |
11629 | return NS_OK; |
11630 | } |
11631 | |
11632 | void nsDocShell::SetScrollRestorationIsManualOnHistoryEntry( |
11633 | nsISHEntry* aSHEntry, bool aIsManual) { |
11634 | if (aSHEntry) { |
11635 | aSHEntry->SetScrollRestorationIsManual(aIsManual); |
11636 | } |
11637 | |
11638 | if (mActiveEntry && mBrowsingContext) { |
11639 | mActiveEntry->SetScrollRestorationIsManual(aIsManual); |
11640 | if (XRE_IsParentProcess()) { |
11641 | SessionHistoryEntry* entry = |
11642 | mBrowsingContext->Canonical()->GetActiveSessionHistoryEntry(); |
11643 | if (entry) { |
11644 | entry->SetScrollRestorationIsManual(aIsManual); |
11645 | } |
11646 | } else { |
11647 | mozilla::Unused << ContentChild::GetSingleton() |
11648 | ->SendSessionHistoryEntryScrollRestorationIsManual( |
11649 | mBrowsingContext, aIsManual); |
11650 | } |
11651 | } |
11652 | } |
11653 | |
11654 | void nsDocShell::SetCacheKeyOnHistoryEntry(nsISHEntry* aSHEntry, |
11655 | uint32_t aCacheKey) { |
11656 | if (aSHEntry) { |
11657 | aSHEntry->SetCacheKey(aCacheKey); |
11658 | } |
11659 | |
11660 | if (mActiveEntry && mBrowsingContext) { |
11661 | mActiveEntry->SetCacheKey(aCacheKey); |
11662 | if (XRE_IsParentProcess()) { |
11663 | SessionHistoryEntry* entry = |
11664 | mBrowsingContext->Canonical()->GetActiveSessionHistoryEntry(); |
11665 | if (entry) { |
11666 | entry->SetCacheKey(aCacheKey); |
11667 | } |
11668 | } else { |
11669 | mozilla::Unused |
11670 | << ContentChild::GetSingleton()->SendSessionHistoryEntryCacheKey( |
11671 | mBrowsingContext, aCacheKey); |
11672 | } |
11673 | } |
11674 | } |
11675 | |
11676 | /* static */ |
11677 | bool nsDocShell::ShouldAddToSessionHistory(nsIURI* aURI, nsIChannel* aChannel) { |
11678 | // I believe none of the about: urls should go in the history. But then |
11679 | // that could just be me... If the intent is only deny about:blank then we |
11680 | // should just do a spec compare, rather than two gets of the scheme and |
11681 | // then the path. -Gagan |
11682 | nsresult rv; |
11683 | nsAutoCString buf; |
11684 | |
11685 | rv = aURI->GetScheme(buf); |
11686 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
11687 | return false; |
11688 | } |
11689 | |
11690 | if (buf.EqualsLiteral("about")) { |
11691 | rv = aURI->GetPathQueryRef(buf); |
11692 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
11693 | return false; |
11694 | } |
11695 | |
11696 | if (buf.EqualsLiteral("blank")) { |
11697 | return false; |
11698 | } |
11699 | // We only want to add about:newtab if it's not privileged, and |
11700 | // if it is not configured to show the blank page. |
11701 | if (buf.EqualsLiteral("newtab")) { |
11702 | if (!StaticPrefs::browser_newtabpage_enabled()) { |
11703 | return false; |
11704 | } |
11705 | |
11706 | 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" , 11706); return false; } } while (false); |
11707 | nsCOMPtr<nsIPrincipal> resultPrincipal; |
11708 | rv = nsContentUtils::GetSecurityManager()->GetChannelResultPrincipal( |
11709 | aChannel, getter_AddRefs(resultPrincipal)); |
11710 | 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" , 11710); return false; } } while (false); |
11711 | return !resultPrincipal->IsSystemPrincipal(); |
11712 | } |
11713 | } |
11714 | |
11715 | return true; |
11716 | } |
11717 | |
11718 | nsresult nsDocShell::AddToSessionHistory( |
11719 | nsIURI* aURI, nsIChannel* aChannel, nsIPrincipal* aTriggeringPrincipal, |
11720 | nsIPrincipal* aPrincipalToInherit, |
11721 | nsIPrincipal* aPartitionedPrincipalToInherit, |
11722 | nsIContentSecurityPolicy* aCsp, bool aCloneChildren, |
11723 | nsISHEntry** aNewEntry) { |
11724 | 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" , 11724); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aURI" ") (" "uri is null" ")"); do { *((volatile int*)__null) = 11724; __attribute__ ((nomerge)) ::abort(); } while (false); } } while (false); |
11725 | 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" , 11725); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aChannel || !aTriggeringPrincipal" ") (" "Shouldn't have both set" ")"); do { *((volatile int*) __null) = 11725; __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); |
11726 | 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" , 11726); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "!mozilla::SessionHistoryInParent()" ")"); do { *((volatile int*)__null) = 11726; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
11727 | |
11728 | #if defined(DEBUG1) |
11729 | if (MOZ_LOG_TEST(gDocShellLog, LogLevel::Debug)(__builtin_expect(!!(mozilla::detail::log_test(gDocShellLog, LogLevel ::Debug)), 0))) { |
11730 | nsAutoCString chanName; |
11731 | if (aChannel) { |
11732 | aChannel->GetName(chanName); |
11733 | } else { |
11734 | chanName.AssignLiteral("<no channel>"); |
11735 | } |
11736 | |
11737 | 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) |
11738 | ("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) |
11739 | 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); |
11740 | } |
11741 | #endif |
11742 | |
11743 | nsresult rv = NS_OK; |
11744 | nsCOMPtr<nsISHEntry> entry; |
11745 | |
11746 | /* |
11747 | * If this is a LOAD_FLAGS_REPLACE_HISTORY in a subframe, we use |
11748 | * the existing SH entry in the page and replace the url and |
11749 | * other vitalities. |
11750 | */ |
11751 | if (LOAD_TYPE_HAS_FLAGS(mLoadType, LOAD_FLAGS_REPLACE_HISTORY)((mLoadType) & ((LOAD_FLAGS_REPLACE_HISTORY) << 16) ) && |
11752 | !mBrowsingContext->IsTop()) { |
11753 | // This is a subframe |
11754 | entry = mOSHE; |
11755 | if (entry) { |
11756 | entry->ClearEntry(); |
11757 | } |
11758 | } |
11759 | |
11760 | // Create a new entry if necessary. |
11761 | if (!entry) { |
11762 | entry = new nsSHEntry(); |
11763 | } |
11764 | |
11765 | // Get the post data & referrer |
11766 | nsCOMPtr<nsIInputStream> inputStream; |
11767 | nsCOMPtr<nsIURI> originalURI; |
11768 | nsCOMPtr<nsIURI> resultPrincipalURI; |
11769 | nsCOMPtr<nsIURI> unstrippedURI; |
11770 | bool loadReplace = false; |
11771 | nsCOMPtr<nsIReferrerInfo> referrerInfo; |
11772 | uint32_t cacheKey = 0; |
11773 | nsCOMPtr<nsIPrincipal> triggeringPrincipal = aTriggeringPrincipal; |
11774 | nsCOMPtr<nsIPrincipal> principalToInherit = aPrincipalToInherit; |
11775 | nsCOMPtr<nsIPrincipal> partitionedPrincipalToInherit = |
11776 | aPartitionedPrincipalToInherit; |
11777 | nsCOMPtr<nsIContentSecurityPolicy> csp = aCsp; |
11778 | bool expired = false; // by default the page is not expired |
11779 | bool discardLayoutState = false; |
11780 | nsCOMPtr<nsICacheInfoChannel> cacheChannel; |
11781 | bool userActivation = false; |
11782 | |
11783 | if (aChannel) { |
11784 | cacheChannel = do_QueryInterface(aChannel); |
11785 | |
11786 | /* If there is a caching channel, get the Cache Key and store it |
11787 | * in SH. |
11788 | */ |
11789 | if (cacheChannel) { |
11790 | cacheChannel->GetCacheKey(&cacheKey); |
11791 | } |
11792 | nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(aChannel)); |
11793 | |
11794 | // Check if the httpChannel is hiding under a multipartChannel |
11795 | if (!httpChannel) { |
11796 | GetHttpChannel(aChannel, getter_AddRefs(httpChannel)); |
11797 | } |
11798 | if (httpChannel) { |
11799 | nsCOMPtr<nsIUploadChannel> uploadChannel(do_QueryInterface(httpChannel)); |
11800 | if (uploadChannel) { |
11801 | uploadChannel->GetUploadStream(getter_AddRefs(inputStream)); |
11802 | } |
11803 | httpChannel->GetOriginalURI(getter_AddRefs(originalURI)); |
11804 | uint32_t loadFlags; |
11805 | aChannel->GetLoadFlags(&loadFlags); |
11806 | loadReplace = loadFlags & nsIChannel::LOAD_REPLACE; |
11807 | rv = httpChannel->GetReferrerInfo(getter_AddRefs(referrerInfo)); |
11808 | 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" , 11808); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))" ")"); do { *((volatile int*)__null) = 11808; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
11809 | |
11810 | discardLayoutState = ShouldDiscardLayoutState(httpChannel); |
11811 | } |
11812 | |
11813 | nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo(); |
11814 | if (!triggeringPrincipal) { |
11815 | triggeringPrincipal = loadInfo->TriggeringPrincipal(); |
11816 | } |
11817 | if (!csp) { |
11818 | csp = loadInfo->GetCspToInherit(); |
11819 | } |
11820 | |
11821 | loadInfo->GetResultPrincipalURI(getter_AddRefs(resultPrincipalURI)); |
11822 | |
11823 | loadInfo->GetUnstrippedURI(getter_AddRefs(unstrippedURI)); |
11824 | |
11825 | userActivation = loadInfo->GetHasValidUserGestureActivation(); |
11826 | |
11827 | // For now keep storing just the principal in the SHEntry. |
11828 | if (!principalToInherit) { |
11829 | if (loadInfo->GetLoadingSandboxed()) { |
11830 | if (loadInfo->GetLoadingPrincipal()) { |
11831 | principalToInherit = NullPrincipal::CreateWithInheritedAttributes( |
11832 | loadInfo->GetLoadingPrincipal()); |
11833 | } else { |
11834 | // get the OriginAttributes |
11835 | OriginAttributes attrs; |
11836 | loadInfo->GetOriginAttributes(&attrs); |
11837 | principalToInherit = NullPrincipal::Create(attrs); |
11838 | } |
11839 | } else { |
11840 | principalToInherit = loadInfo->PrincipalToInherit(); |
11841 | } |
11842 | } |
11843 | |
11844 | if (!partitionedPrincipalToInherit) { |
11845 | // XXXehsan is it correct to fall back to the principal to inherit in all |
11846 | // cases? For example, what about the cases where we are using the load |
11847 | // info's principal to inherit? Do we need to add a similar concept to |
11848 | // load info for partitioned principal? |
11849 | partitionedPrincipalToInherit = principalToInherit; |
11850 | } |
11851 | } |
11852 | |
11853 | nsAutoString srcdoc; |
11854 | bool srcdocEntry = false; |
11855 | nsCOMPtr<nsIURI> baseURI; |
11856 | |
11857 | nsCOMPtr<nsIInputStreamChannel> inStrmChan = do_QueryInterface(aChannel); |
11858 | if (inStrmChan) { |
11859 | bool isSrcdocChannel; |
11860 | inStrmChan->GetIsSrcdocChannel(&isSrcdocChannel); |
11861 | if (isSrcdocChannel) { |
11862 | inStrmChan->GetSrcdocData(srcdoc); |
11863 | srcdocEntry = true; |
11864 | inStrmChan->GetBaseURI(getter_AddRefs(baseURI)); |
11865 | } else { |
11866 | srcdoc.SetIsVoid(true); |
11867 | } |
11868 | } |
11869 | /* If cache got a 'no-store', ask SH not to store |
11870 | * HistoryLayoutState. By default, SH will set this |
11871 | * flag to true and save HistoryLayoutState. |
11872 | */ |
11873 | bool saveLayoutState = !discardLayoutState; |
11874 | |
11875 | if (cacheChannel) { |
11876 | // Check if the page has expired from cache |
11877 | uint32_t expTime = 0; |
11878 | cacheChannel->GetCacheTokenExpirationTime(&expTime); |
11879 | uint32_t now = PRTimeToSeconds(PR_Now()); |
11880 | if (expTime <= now) { |
11881 | expired = true; |
11882 | } |
11883 | } |
11884 | |
11885 | // Title is set in nsDocShell::SetTitle() |
11886 | entry->Create(aURI, // uri |
11887 | u""_ns, // Title |
11888 | inputStream, // Post data stream |
11889 | cacheKey, // CacheKey |
11890 | mContentTypeHint, // Content-type |
11891 | triggeringPrincipal, // Channel or provided principal |
11892 | principalToInherit, partitionedPrincipalToInherit, csp, |
11893 | HistoryID(), GetCreatedDynamically(), originalURI, |
11894 | resultPrincipalURI, unstrippedURI, loadReplace, referrerInfo, |
11895 | srcdoc, srcdocEntry, baseURI, saveLayoutState, expired, |
11896 | userActivation); |
11897 | |
11898 | if (mBrowsingContext->IsTop() && GetSessionHistory()) { |
11899 | bool shouldPersist = ShouldAddToSessionHistory(aURI, aChannel); |
11900 | Maybe<int32_t> previousEntryIndex; |
11901 | Maybe<int32_t> loadedEntryIndex; |
11902 | rv = GetSessionHistory()->LegacySHistory()->AddToRootSessionHistory( |
11903 | aCloneChildren, mOSHE, mBrowsingContext, entry, mLoadType, |
11904 | shouldPersist, &previousEntryIndex, &loadedEntryIndex); |
11905 | |
11906 | 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" , 11906); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))" ") (" "Could not add entry to root session history" ")"); do { *((volatile int*)__null) = 11906; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
11907 | if (previousEntryIndex.isSome()) { |
11908 | mPreviousEntryIndex = previousEntryIndex.value(); |
11909 | } |
11910 | if (loadedEntryIndex.isSome()) { |
11911 | mLoadedEntryIndex = loadedEntryIndex.value(); |
11912 | } |
11913 | |
11914 | // aCloneChildren implies that we are retaining the same document, thus we |
11915 | // need to signal to the top WC that the new SHEntry may receive a fresh |
11916 | // user interaction flag. |
11917 | if (aCloneChildren) { |
11918 | WindowContext* topWc = mBrowsingContext->GetTopWindowContext(); |
11919 | if (topWc && !topWc->IsDiscarded()) { |
11920 | 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" , 11920); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false" ") (" "NS_SUCCEEDED(topWc->SetSHEntryHasUserInteraction(false))" ")"); do { *((volatile int*)__null) = 11920; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); } } while (false); |
11921 | } |
11922 | } |
11923 | } else { |
11924 | // This is a subframe, make sure that this new SHEntry will be |
11925 | // marked with user interaction. |
11926 | WindowContext* topWc = mBrowsingContext->GetTopWindowContext(); |
11927 | if (topWc && !topWc->IsDiscarded()) { |
11928 | 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" , 11928); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false" ") (" "NS_SUCCEEDED(topWc->SetSHEntryHasUserInteraction(false))" ")"); do { *((volatile int*)__null) = 11928; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); } } while (false); |
11929 | } |
11930 | if (!mOSHE || !LOAD_TYPE_HAS_FLAGS(mLoadType, LOAD_FLAGS_REPLACE_HISTORY)((mLoadType) & ((LOAD_FLAGS_REPLACE_HISTORY) << 16) )) { |
11931 | rv = AddChildSHEntryToParent(entry, mBrowsingContext->ChildOffset(), |
11932 | aCloneChildren); |
11933 | } |
11934 | } |
11935 | |
11936 | // Return the new SH entry... |
11937 | if (aNewEntry) { |
11938 | *aNewEntry = nullptr; |
11939 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) { |
11940 | entry.forget(aNewEntry); |
11941 | } |
11942 | } |
11943 | |
11944 | return rv; |
11945 | } |
11946 | |
11947 | void nsDocShell::UpdateActiveEntry( |
11948 | bool aReplace, const Maybe<nsPoint>& aPreviousScrollPos, nsIURI* aURI, |
11949 | nsIURI* aOriginalURI, nsIReferrerInfo* aReferrerInfo, |
11950 | nsIPrincipal* aTriggeringPrincipal, nsIContentSecurityPolicy* aCsp, |
11951 | const nsAString& aTitle, bool aScrollRestorationIsManual, |
11952 | nsIStructuredCloneContainer* aData, bool aURIWasModified) { |
11953 | 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" , 11953); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mozilla::SessionHistoryInParent()" ")"); do { *((volatile int*)__null) = 11953; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
11954 | 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" , 11954); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aURI" ") (" "uri is null" ")"); do { *((volatile int*)__null) = 11954; __attribute__ ((nomerge)) ::abort(); } while (false); } } while (false); |
11955 | 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" , 11956); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLoadType == LOAD_PUSHSTATE" ") (" "This code only deals with pushState" ")"); do { *((volatile int*)__null) = 11956; __attribute__((nomerge)) ::abort(); } while (false); } } while (false) |
11956 | "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" , 11956); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLoadType == LOAD_PUSHSTATE" ") (" "This code only deals with pushState" ")"); do { *((volatile int*)__null) = 11956; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
11957 | 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" , 11957); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aReplace" ")"); do { *((volatile int*)__null) = 11957; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); } } while (false); |
11958 | |
11959 | 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) |
11960 | ("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) |
11961 | 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); |
11962 | |
11963 | // Even if we're replacing an existing entry we create new a |
11964 | // SessionHistoryInfo. In the parent process we'll keep the existing |
11965 | // SessionHistoryEntry, but just replace its SessionHistoryInfo, that way the |
11966 | // entry keeps identity but its data is replaced. |
11967 | bool replace = aReplace && mActiveEntry; |
11968 | |
11969 | if (!replace) { |
11970 | CollectWireframe(); |
11971 | } |
11972 | |
11973 | if (mActiveEntry) { |
11974 | // Link this entry to the previous active entry. |
11975 | mActiveEntry = MakeUnique<SessionHistoryInfo>(*mActiveEntry, aURI); |
11976 | } else { |
11977 | mActiveEntry = MakeUnique<SessionHistoryInfo>( |
11978 | aURI, aTriggeringPrincipal, nullptr, nullptr, aCsp, mContentTypeHint); |
11979 | } |
11980 | mActiveEntry->SetOriginalURI(aOriginalURI); |
11981 | mActiveEntry->SetUnstrippedURI(nullptr); |
11982 | mActiveEntry->SetReferrerInfo(aReferrerInfo); |
11983 | mActiveEntry->SetTitle(aTitle); |
11984 | mActiveEntry->SetStateData(static_cast<nsStructuredCloneContainer*>(aData)); |
11985 | mActiveEntry->SetURIWasModified(aURIWasModified); |
11986 | mActiveEntry->SetScrollRestorationIsManual(aScrollRestorationIsManual); |
11987 | |
11988 | if (replace) { |
11989 | mBrowsingContext->ReplaceActiveSessionHistoryEntry(mActiveEntry.get()); |
11990 | } else { |
11991 | mBrowsingContext->IncrementHistoryEntryCountForBrowsingContext(); |
11992 | // FIXME We should probably just compute mChildOffset in the parent |
11993 | // instead of passing it over IPC here. |
11994 | mBrowsingContext->SetActiveSessionHistoryEntry( |
11995 | aPreviousScrollPos, mActiveEntry.get(), mLoadType, |
11996 | /* aCacheKey = */ 0); |
11997 | // FIXME Do we need to update mPreviousEntryIndex and mLoadedEntryIndex? |
11998 | } |
11999 | } |
12000 | |
12001 | nsresult nsDocShell::LoadHistoryEntry(nsISHEntry* aEntry, uint32_t aLoadType, |
12002 | bool aUserActivation) { |
12003 | 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" , 12003); return NS_ERROR_FAILURE; } } while (false); |
12004 | |
12005 | nsresult rv; |
12006 | RefPtr<nsDocShellLoadState> loadState; |
12007 | rv = aEntry->CreateLoadInfo(getter_AddRefs(loadState)); |
12008 | 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" , 12008); return rv; } } while (false); |
12009 | |
12010 | // Calling CreateAboutBlankDocumentViewer can set mOSHE to null, and if |
12011 | // that's the only thing holding a ref to aEntry that will cause aEntry to |
12012 | // die while we're loading it. So hold a strong ref to aEntry here, just |
12013 | // in case. |
12014 | nsCOMPtr<nsISHEntry> kungFuDeathGrip(aEntry); |
12015 | |
12016 | loadState->SetHasValidUserGestureActivation( |
12017 | loadState->HasValidUserGestureActivation() || aUserActivation); |
12018 | |
12019 | return LoadHistoryEntry(loadState, aLoadType, aEntry == mOSHE); |
12020 | } |
12021 | |
12022 | nsresult nsDocShell::LoadHistoryEntry(const LoadingSessionHistoryInfo& aEntry, |
12023 | uint32_t aLoadType, |
12024 | bool aUserActivation) { |
12025 | RefPtr<nsDocShellLoadState> loadState = aEntry.CreateLoadInfo(); |
12026 | loadState->SetHasValidUserGestureActivation( |
12027 | loadState->HasValidUserGestureActivation() || aUserActivation); |
12028 | |
12029 | return LoadHistoryEntry(loadState, aLoadType, aEntry.mLoadingCurrentEntry); |
12030 | } |
12031 | |
12032 | nsresult nsDocShell::LoadHistoryEntry(nsDocShellLoadState* aLoadState, |
12033 | uint32_t aLoadType, |
12034 | bool aLoadingCurrentEntry) { |
12035 | if (!IsNavigationAllowed()) { |
12036 | return NS_OK; |
12037 | } |
12038 | |
12039 | // We are setting load type afterwards so we don't have to |
12040 | // send it in an IPC message |
12041 | aLoadState->SetLoadType(aLoadType); |
12042 | |
12043 | nsresult rv; |
12044 | if (SchemeIsJavascript(aLoadState->URI())) { |
12045 | // We're loading a URL that will execute script from inside asyncOpen. |
12046 | // Replace the current document with about:blank now to prevent |
12047 | // anything from the current document from leaking into any JavaScript |
12048 | // code in the URL. |
12049 | // Don't cache the presentation if we're going to just reload the |
12050 | // current entry. Caching would lead to trying to save the different |
12051 | // content viewers in the same nsISHEntry object. |
12052 | rv = CreateAboutBlankDocumentViewer( |
12053 | aLoadState->PrincipalToInherit(), |
12054 | aLoadState->PartitionedPrincipalToInherit(), nullptr, nullptr, |
12055 | /* aIsInitialDocument */ false, Nothing(), !aLoadingCurrentEntry); |
12056 | |
12057 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
12058 | // The creation of the intermittent about:blank content |
12059 | // viewer failed for some reason (potentially because the |
12060 | // user prevented it). Interrupt the history load. |
12061 | return NS_OK; |
12062 | } |
12063 | |
12064 | if (!aLoadState->TriggeringPrincipal()) { |
12065 | // Ensure that we have a triggeringPrincipal. Otherwise javascript: |
12066 | // URIs will pick it up from the about:blank page we just loaded, |
12067 | // and we don't really want even that in this case. |
12068 | nsCOMPtr<nsIPrincipal> principal = |
12069 | NullPrincipal::Create(GetOriginAttributes()); |
12070 | aLoadState->SetTriggeringPrincipal(principal); |
12071 | } |
12072 | } |
12073 | |
12074 | /* If there is a valid postdata *and* the user pressed |
12075 | * reload or shift-reload, take user's permission before we |
12076 | * repost the data to the server. |
12077 | */ |
12078 | if ((aLoadType & LOAD_CMD_RELOAD) && aLoadState->PostDataStream()) { |
12079 | bool repost; |
12080 | rv = ConfirmRepost(&repost); |
12081 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
12082 | return rv; |
12083 | } |
12084 | |
12085 | // If the user pressed cancel in the dialog, return. We're done here. |
12086 | if (!repost) { |
12087 | return NS_BINDING_ABORTED; |
12088 | } |
12089 | } |
12090 | |
12091 | // If there is no valid triggeringPrincipal, we deny the load |
12092 | 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" , 12093); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->TriggeringPrincipal()" ") (" "need a valid triggeringPrincipal to load from history" ")"); do { *((volatile int*)__null) = 12093; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false) |
12093 | "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" , 12093); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->TriggeringPrincipal()" ") (" "need a valid triggeringPrincipal to load from history" ")"); do { *((volatile int*)__null) = 12093; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
12094 | if (!aLoadState->TriggeringPrincipal()) { |
12095 | return NS_ERROR_FAILURE; |
12096 | } |
12097 | |
12098 | return InternalLoad(aLoadState); // No nsIRequest |
12099 | } |
12100 | |
12101 | NS_IMETHODIMPnsresult |
12102 | nsDocShell::PersistLayoutHistoryState() { |
12103 | nsresult rv = NS_OK; |
12104 | |
12105 | if (mozilla::SessionHistoryInParent() ? !!mActiveEntry : !!mOSHE) { |
12106 | bool scrollRestorationIsManual; |
12107 | if (mozilla::SessionHistoryInParent()) { |
12108 | scrollRestorationIsManual = mActiveEntry->GetScrollRestorationIsManual(); |
12109 | } else { |
12110 | scrollRestorationIsManual = mOSHE->GetScrollRestorationIsManual(); |
12111 | } |
12112 | nsCOMPtr<nsILayoutHistoryState> layoutState; |
12113 | if (RefPtr<PresShell> presShell = GetPresShell()) { |
12114 | rv = presShell->CaptureHistoryState(getter_AddRefs(layoutState)); |
12115 | } else if (scrollRestorationIsManual) { |
12116 | // Even if we don't have layout anymore, we may want to reset the |
12117 | // current scroll state in layout history. |
12118 | GetLayoutHistoryState(getter_AddRefs(layoutState)); |
12119 | } |
12120 | |
12121 | if (scrollRestorationIsManual && layoutState) { |
12122 | layoutState->ResetScrollState(); |
12123 | } |
12124 | } |
12125 | |
12126 | return rv; |
12127 | } |
12128 | |
12129 | void nsDocShell::SwapHistoryEntries(nsISHEntry* aOldEntry, |
12130 | nsISHEntry* aNewEntry) { |
12131 | if (aOldEntry == mOSHE) { |
12132 | mOSHE = aNewEntry; |
12133 | } |
12134 | |
12135 | if (aOldEntry == mLSHE) { |
12136 | mLSHE = aNewEntry; |
12137 | } |
12138 | } |
12139 | |
12140 | void nsDocShell::SetHistoryEntryAndUpdateBC(const Maybe<nsISHEntry*>& aLSHE, |
12141 | const Maybe<nsISHEntry*>& aOSHE) { |
12142 | // We want to hold on to the reference in mLSHE before we update it. |
12143 | // Otherwise, SetHistoryEntry could release the last reference to |
12144 | // the entry while aOSHE is pointing to it. |
12145 | nsCOMPtr<nsISHEntry> deathGripOldLSHE; |
12146 | if (aLSHE.isSome()) { |
12147 | deathGripOldLSHE = SetHistoryEntry(&mLSHE, aLSHE.value()); |
12148 | 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" , 12148); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLSHE.get() == aLSHE.value()" ")"); do { *((volatile int*)__null) = 12148; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
12149 | } |
12150 | nsCOMPtr<nsISHEntry> deathGripOldOSHE; |
12151 | if (aOSHE.isSome()) { |
12152 | deathGripOldOSHE = SetHistoryEntry(&mOSHE, aOSHE.value()); |
12153 | 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" , 12153); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mOSHE.get() == aOSHE.value()" ")"); do { *((volatile int*)__null) = 12153; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
12154 | } |
12155 | } |
12156 | |
12157 | already_AddRefed<nsISHEntry> nsDocShell::SetHistoryEntry( |
12158 | nsCOMPtr<nsISHEntry>* aPtr, nsISHEntry* aEntry) { |
12159 | // We need to sync up the docshell and session history trees for |
12160 | // subframe navigation. If the load was in a subframe, we forward up to |
12161 | // the root docshell, which will then recursively sync up all docshells |
12162 | // to their corresponding entries in the new session history tree. |
12163 | // If we don't do this, then we can cache a content viewer on the wrong |
12164 | // cloned entry, and subsequently restore it at the wrong time. |
12165 | RefPtr<BrowsingContext> topBC = mBrowsingContext->Top(); |
12166 | if (topBC->IsDiscarded()) { |
12167 | topBC = nullptr; |
12168 | } |
12169 | RefPtr<BrowsingContext> currBC = |
12170 | mBrowsingContext->IsDiscarded() ? nullptr : mBrowsingContext; |
12171 | if (topBC && *aPtr) { |
12172 | (*aPtr)->SyncTreesForSubframeNavigation(aEntry, topBC, currBC); |
12173 | } |
12174 | nsCOMPtr<nsISHEntry> entry(aEntry); |
12175 | entry.swap(*aPtr); |
12176 | return entry.forget(); |
12177 | } |
12178 | |
12179 | already_AddRefed<ChildSHistory> nsDocShell::GetRootSessionHistory() { |
12180 | RefPtr<ChildSHistory> childSHistory = |
12181 | mBrowsingContext->Top()->GetChildSessionHistory(); |
12182 | return childSHistory.forget(); |
12183 | } |
12184 | |
12185 | nsresult nsDocShell::GetHttpChannel(nsIChannel* aChannel, |
12186 | nsIHttpChannel** aReturn) { |
12187 | 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" , 12187); return NS_ERROR_INVALID_POINTER; } } while (false); |
12188 | if (!aChannel) { |
12189 | return NS_ERROR_FAILURE; |
12190 | } |
12191 | |
12192 | nsCOMPtr<nsIMultiPartChannel> multiPartChannel(do_QueryInterface(aChannel)); |
12193 | if (multiPartChannel) { |
12194 | nsCOMPtr<nsIChannel> baseChannel; |
12195 | multiPartChannel->GetBaseChannel(getter_AddRefs(baseChannel)); |
12196 | nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(baseChannel)); |
12197 | *aReturn = httpChannel; |
12198 | NS_IF_ADDREF(*aReturn)ns_if_addref(*aReturn); |
12199 | } |
12200 | return NS_OK; |
12201 | } |
12202 | |
12203 | bool nsDocShell::ShouldDiscardLayoutState(nsIHttpChannel* aChannel) { |
12204 | // By default layout State will be saved. |
12205 | if (!aChannel) { |
12206 | return false; |
12207 | } |
12208 | |
12209 | // figure out if SH should be saving layout state |
12210 | bool noStore = false; |
12211 | Unused << aChannel->IsNoStoreResponse(&noStore); |
12212 | return noStore; |
12213 | } |
12214 | |
12215 | NS_IMETHODIMPnsresult |
12216 | nsDocShell::GetEditor(nsIEditor** aEditor) { |
12217 | 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" , 12217); return NS_ERROR_INVALID_POINTER; } } while (false); |
12218 | RefPtr<HTMLEditor> htmlEditor = GetHTMLEditorInternal(); |
12219 | htmlEditor.forget(aEditor); |
12220 | return NS_OK; |
12221 | } |
12222 | |
12223 | NS_IMETHODIMPnsresult |
12224 | nsDocShell::SetEditor(nsIEditor* aEditor) { |
12225 | HTMLEditor* htmlEditor = aEditor ? aEditor->GetAsHTMLEditor() : nullptr; |
12226 | // If TextEditor comes, throw an error. |
12227 | if (aEditor && !htmlEditor) { |
12228 | return NS_ERROR_INVALID_ARG; |
12229 | } |
12230 | return SetHTMLEditorInternal(htmlEditor); |
12231 | } |
12232 | |
12233 | HTMLEditor* nsDocShell::GetHTMLEditorInternal() { |
12234 | return mEditorData ? mEditorData->GetHTMLEditor() : nullptr; |
12235 | } |
12236 | |
12237 | nsresult nsDocShell::SetHTMLEditorInternal(HTMLEditor* aHTMLEditor) { |
12238 | if (!aHTMLEditor && !mEditorData) { |
12239 | return NS_OK; |
12240 | } |
12241 | |
12242 | nsresult rv = EnsureEditorData(); |
12243 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
12244 | return rv; |
12245 | } |
12246 | |
12247 | return mEditorData->SetHTMLEditor(aHTMLEditor); |
12248 | } |
12249 | |
12250 | NS_IMETHODIMPnsresult |
12251 | nsDocShell::GetEditable(bool* aEditable) { |
12252 | 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" , 12252); return NS_ERROR_INVALID_POINTER; } } while (false); |
12253 | *aEditable = mEditorData && mEditorData->GetEditable(); |
12254 | return NS_OK; |
12255 | } |
12256 | |
12257 | NS_IMETHODIMPnsresult |
12258 | nsDocShell::GetHasEditingSession(bool* aHasEditingSession) { |
12259 | 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" , 12259); return NS_ERROR_INVALID_POINTER; } } while (false); |
12260 | |
12261 | if (mEditorData) { |
12262 | *aHasEditingSession = !!mEditorData->GetEditingSession(); |
12263 | } else { |
12264 | *aHasEditingSession = false; |
12265 | } |
12266 | |
12267 | return NS_OK; |
12268 | } |
12269 | |
12270 | NS_IMETHODIMPnsresult |
12271 | nsDocShell::MakeEditable(bool aInWaitForUriLoad) { |
12272 | nsresult rv = EnsureEditorData(); |
12273 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
12274 | return rv; |
12275 | } |
12276 | |
12277 | return mEditorData->MakeEditable(aInWaitForUriLoad); |
12278 | } |
12279 | |
12280 | /* static */ bool nsDocShell::ShouldAddURIVisit(nsIChannel* aChannel) { |
12281 | bool needToAddURIVisit = true; |
12282 | nsCOMPtr<nsIPropertyBag2> props(do_QueryInterface(aChannel)); |
12283 | if (props) { |
12284 | mozilla::Unused << props->GetPropertyAsBool( |
12285 | u"docshell.needToAddURIVisit"_ns, &needToAddURIVisit); |
12286 | } |
12287 | |
12288 | return needToAddURIVisit; |
12289 | } |
12290 | |
12291 | /* static */ void nsDocShell::ExtractLastVisit( |
12292 | nsIChannel* aChannel, nsIURI** aURI, uint32_t* aChannelRedirectFlags) { |
12293 | nsCOMPtr<nsIPropertyBag2> props(do_QueryInterface(aChannel)); |
12294 | if (!props) { |
12295 | return; |
12296 | } |
12297 | |
12298 | nsresult rv; |
12299 | nsCOMPtr<nsIURI> uri(do_GetProperty(props, u"docshell.previousURI"_ns, &rv)); |
12300 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) { |
12301 | uri.forget(aURI); |
12302 | |
12303 | rv = props->GetPropertyAsUint32(u"docshell.previousFlags"_ns, |
12304 | aChannelRedirectFlags); |
12305 | |
12306 | 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" , 12308); } } while (false) |
12307 | 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" , 12308); } } while (false) |
12308 | "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" , 12308); } } while (false); |
12309 | |
12310 | } else { |
12311 | // There is no last visit for this channel, so this must be the first |
12312 | // link. Link the visit to the referrer of this request, if any. |
12313 | // Treat referrer as null if there is an error getting it. |
12314 | NS_GetReferrerFromChannel(aChannel, aURI); |
12315 | } |
12316 | } |
12317 | |
12318 | void nsDocShell::SaveLastVisit(nsIChannel* aChannel, nsIURI* aURI, |
12319 | uint32_t aChannelRedirectFlags) { |
12320 | nsCOMPtr<nsIWritablePropertyBag2> props(do_QueryInterface(aChannel)); |
12321 | if (!props || !aURI) { |
12322 | return; |
12323 | } |
12324 | |
12325 | props->SetPropertyAsInterface(u"docshell.previousURI"_ns, aURI); |
12326 | props->SetPropertyAsUint32(u"docshell.previousFlags"_ns, |
12327 | aChannelRedirectFlags); |
12328 | } |
12329 | |
12330 | /* static */ void nsDocShell::InternalAddURIVisit( |
12331 | nsIURI* aURI, nsIURI* aPreviousURI, uint32_t aChannelRedirectFlags, |
12332 | uint32_t aResponseStatus, BrowsingContext* aBrowsingContext, |
12333 | nsIWidget* aWidget, uint32_t aLoadType, bool aWasUpgraded) { |
12334 | 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" , 12334); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aURI" ") (" "Visited URI is null!" ")"); do { *((volatile int*)__null) = 12334; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
12335 | 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" , 12336); 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) = 12336; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
12336 | "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" , 12336); 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) = 12336; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
12337 | |
12338 | bool usePrivateBrowsing = false; |
12339 | aBrowsingContext->GetUsePrivateBrowsing(&usePrivateBrowsing); |
12340 | |
12341 | // Only content-type docshells save URI visits. Also don't do |
12342 | // anything here if we're not supposed to use global history. |
12343 | if (!aBrowsingContext->IsContent() || |
12344 | !aBrowsingContext->GetUseGlobalHistory() || usePrivateBrowsing) { |
12345 | return; |
12346 | } |
12347 | |
12348 | nsCOMPtr<IHistory> history = components::History::Service(); |
12349 | |
12350 | if (history) { |
12351 | uint32_t visitURIFlags = 0; |
12352 | |
12353 | if (aBrowsingContext->IsTop()) { |
12354 | visitURIFlags |= IHistory::TOP_LEVEL; |
12355 | } |
12356 | |
12357 | if (aChannelRedirectFlags & nsIChannelEventSink::REDIRECT_TEMPORARY) { |
12358 | visitURIFlags |= IHistory::REDIRECT_TEMPORARY; |
12359 | } else if (aChannelRedirectFlags & |
12360 | nsIChannelEventSink::REDIRECT_PERMANENT) { |
12361 | visitURIFlags |= IHistory::REDIRECT_PERMANENT; |
12362 | } else { |
12363 | 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" , 12365); 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) = 12365; __attribute__((nomerge)) ::abort (); } while (false); } } while (false) |
12364 | "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" , 12365); 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) = 12365; __attribute__((nomerge)) ::abort (); } while (false); } } while (false) |
12365 | "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" , 12365); 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) = 12365; __attribute__((nomerge)) ::abort (); } while (false); } } while (false); |
12366 | } |
12367 | |
12368 | if (aResponseStatus >= 300 && aResponseStatus < 400) { |
12369 | visitURIFlags |= IHistory::REDIRECT_SOURCE; |
12370 | if (aResponseStatus == 301 || aResponseStatus == 308) { |
12371 | visitURIFlags |= IHistory::REDIRECT_SOURCE_PERMANENT; |
12372 | } |
12373 | } |
12374 | // Errors 400-501 and 505 are considered unrecoverable, in the sense a |
12375 | // simple retry attempt by the user is unlikely to solve them. |
12376 | // 408 is special cased, since may actually indicate a temporary |
12377 | // connection problem. |
12378 | else if (aResponseStatus != 408 && |
12379 | ((aResponseStatus >= 400 && aResponseStatus <= 501) || |
12380 | aResponseStatus == 505)) { |
12381 | visitURIFlags |= IHistory::UNRECOVERABLE_ERROR; |
12382 | } |
12383 | |
12384 | if (aWasUpgraded) { |
12385 | visitURIFlags |= |
12386 | IHistory::REDIRECT_SOURCE | IHistory::REDIRECT_SOURCE_UPGRADED; |
12387 | } |
12388 | |
12389 | mozilla::Unused << history->VisitURI(aWidget, aURI, aPreviousURI, |
12390 | visitURIFlags, |
12391 | aBrowsingContext->BrowserId()); |
12392 | } |
12393 | } |
12394 | |
12395 | void nsDocShell::AddURIVisit(nsIURI* aURI, nsIURI* aPreviousURI, |
12396 | uint32_t aChannelRedirectFlags, |
12397 | uint32_t aResponseStatus) { |
12398 | nsPIDOMWindowOuter* outer = GetWindow(); |
12399 | nsCOMPtr<nsIWidget> widget = widget::WidgetUtils::DOMWindowToWidget(outer); |
12400 | |
12401 | InternalAddURIVisit(aURI, aPreviousURI, aChannelRedirectFlags, |
12402 | aResponseStatus, mBrowsingContext, widget, mLoadType, |
12403 | false); |
12404 | } |
12405 | |
12406 | //***************************************************************************** |
12407 | // nsDocShell: Helper Routines |
12408 | //***************************************************************************** |
12409 | |
12410 | NS_IMETHODIMPnsresult |
12411 | nsDocShell::SetLoadType(uint32_t aLoadType) { |
12412 | mLoadType = aLoadType; |
12413 | return NS_OK; |
12414 | } |
12415 | |
12416 | NS_IMETHODIMPnsresult |
12417 | nsDocShell::GetLoadType(uint32_t* aLoadType) { |
12418 | *aLoadType = mLoadType; |
12419 | return NS_OK; |
12420 | } |
12421 | |
12422 | nsresult nsDocShell::ConfirmRepost(bool* aRepost) { |
12423 | if (StaticPrefs::dom_confirm_repost_testing_always_accept()) { |
12424 | *aRepost = true; |
12425 | return NS_OK; |
12426 | } |
12427 | |
12428 | nsCOMPtr<nsIPromptCollection> prompter = |
12429 | do_GetService("@mozilla.org/embedcomp/prompt-collection;1"); |
12430 | if (!prompter) { |
12431 | return NS_ERROR_NOT_AVAILABLE; |
12432 | } |
12433 | |
12434 | return prompter->ConfirmRepost(mBrowsingContext, aRepost); |
12435 | } |
12436 | |
12437 | nsresult nsDocShell::GetPromptAndStringBundle(nsIPrompt** aPrompt, |
12438 | nsIStringBundle** aStringBundle) { |
12439 | 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" , 12440); return NS_ERROR_FAILURE; } } while (false) |
12440 | 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" , 12440); return NS_ERROR_FAILURE; } } while (false); |
12441 | |
12442 | nsCOMPtr<nsIStringBundleService> stringBundleService = |
12443 | mozilla::components::StringBundle::Service(); |
12444 | 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" , 12444); return NS_ERROR_FAILURE; } } while (false); |
12445 | |
12446 | 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" , 12448); return NS_ERROR_FAILURE; } } while (false) |
12447 | 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" , 12448); return NS_ERROR_FAILURE; } } while (false) |
12448 | 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" , 12448); return NS_ERROR_FAILURE; } } while (false); |
12449 | |
12450 | return NS_OK; |
12451 | } |
12452 | |
12453 | nsIScrollableFrame* nsDocShell::GetRootScrollFrame() { |
12454 | PresShell* presShell = GetPresShell(); |
12455 | 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" , 12455); return nullptr; } } while (false); |
12456 | |
12457 | return presShell->GetRootScrollFrameAsScrollable(); |
12458 | } |
12459 | |
12460 | nsresult nsDocShell::EnsureScriptEnvironment() { |
12461 | if (mScriptGlobal) { |
12462 | return NS_OK; |
12463 | } |
12464 | |
12465 | if (mIsBeingDestroyed) { |
12466 | return NS_ERROR_NOT_AVAILABLE; |
12467 | } |
12468 | |
12469 | #ifdef DEBUG1 |
12470 | 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" , 12472); MOZ_PretendNoReturn(); } } while (0) |
12471 | "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" , 12472); MOZ_PretendNoReturn(); } } while (0) |
12472 | "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" , 12472); MOZ_PretendNoReturn(); } } while (0); |
12473 | |
12474 | // Yeah, this isn't re-entrant safe, but that's ok since if we |
12475 | // re-enter this method, we'll infinitely loop... |
12476 | AutoRestore<bool> boolSetter(mInEnsureScriptEnv); |
12477 | mInEnsureScriptEnv = true; |
12478 | #endif |
12479 | |
12480 | nsCOMPtr<nsIWebBrowserChrome> browserChrome(do_GetInterface(mTreeOwner)); |
12481 | 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" , 12481); return NS_ERROR_NOT_AVAILABLE; } } while (false); |
12482 | |
12483 | uint32_t chromeFlags; |
12484 | browserChrome->GetChromeFlags(&chromeFlags); |
12485 | |
12486 | // If our window is modal and we're not opened as chrome, make |
12487 | // this window a modal content window. |
12488 | mScriptGlobal = nsGlobalWindowOuter::Create(this, mItemType == typeChrome); |
12489 | 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" , 12489); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mScriptGlobal" ")"); do { *((volatile int*)__null) = 12489; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
12490 | |
12491 | // Ensure the script object is set up to run script. |
12492 | return mScriptGlobal->EnsureScriptEnvironment(); |
12493 | } |
12494 | |
12495 | nsresult nsDocShell::EnsureEditorData() { |
12496 | 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" , 12496); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mIsBeingDestroyed" ")"); do { *((volatile int*)__null) = 12496; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
12497 | |
12498 | bool openDocHasDetachedEditor = mOSHE && mOSHE->HasDetachedEditor(); |
12499 | if (!mEditorData && !mIsBeingDestroyed && !openDocHasDetachedEditor) { |
12500 | // We shouldn't recreate the editor data if it already exists, or |
12501 | // we're shutting down, or we already have a detached editor data |
12502 | // stored in the session history. We should only have one editordata |
12503 | // per docshell. |
12504 | mEditorData = MakeUnique<nsDocShellEditorData>(this); |
12505 | } |
12506 | |
12507 | return mEditorData ? NS_OK : NS_ERROR_NOT_AVAILABLE; |
12508 | } |
12509 | |
12510 | nsresult nsDocShell::EnsureFind() { |
12511 | if (!mFind) { |
12512 | mFind = new nsWebBrowserFind(); |
12513 | } |
12514 | |
12515 | // we promise that the nsIWebBrowserFind that we return has been set |
12516 | // up to point to the focused, or content window, so we have to |
12517 | // set that up each time. |
12518 | |
12519 | nsIScriptGlobalObject* scriptGO = GetScriptGlobalObject(); |
12520 | 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" , 12520); return NS_ERROR_UNEXPECTED; } } while (false); |
12521 | |
12522 | // default to our window |
12523 | nsCOMPtr<nsPIDOMWindowOuter> ourWindow = do_QueryInterface(scriptGO); |
12524 | nsCOMPtr<nsPIDOMWindowOuter> windowToSearch; |
12525 | nsFocusManager::GetFocusedDescendant(ourWindow, |
12526 | nsFocusManager::eIncludeAllDescendants, |
12527 | getter_AddRefs(windowToSearch)); |
12528 | |
12529 | nsCOMPtr<nsIWebBrowserFindInFrames> findInFrames = do_QueryInterface(mFind); |
12530 | if (!findInFrames) { |
12531 | return NS_ERROR_NO_INTERFACE; |
12532 | } |
12533 | |
12534 | nsresult rv = findInFrames->SetRootSearchFrame(ourWindow); |
12535 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
12536 | return rv; |
12537 | } |
12538 | rv = findInFrames->SetCurrentSearchFrame(windowToSearch); |
12539 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
12540 | return rv; |
12541 | } |
12542 | |
12543 | return NS_OK; |
12544 | } |
12545 | |
12546 | NS_IMETHODIMPnsresult |
12547 | nsDocShell::IsBeingDestroyed(bool* aDoomed) { |
12548 | 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" , 12548); return NS_ERROR_INVALID_ARG; } } while (false); |
12549 | *aDoomed = mIsBeingDestroyed; |
12550 | return NS_OK; |
12551 | } |
12552 | |
12553 | NS_IMETHODIMPnsresult |
12554 | nsDocShell::GetIsExecutingOnLoadHandler(bool* aResult) { |
12555 | 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" , 12555); return NS_ERROR_INVALID_ARG; } } while (false); |
12556 | *aResult = mIsExecutingOnLoadHandler; |
12557 | return NS_OK; |
12558 | } |
12559 | |
12560 | NS_IMETHODIMPnsresult |
12561 | nsDocShell::GetLayoutHistoryState(nsILayoutHistoryState** aLayoutHistoryState) { |
12562 | nsCOMPtr<nsILayoutHistoryState> state; |
12563 | if (mozilla::SessionHistoryInParent()) { |
12564 | if (mActiveEntry) { |
12565 | state = mActiveEntry->GetLayoutHistoryState(); |
12566 | } |
12567 | } else { |
12568 | if (mOSHE) { |
12569 | state = mOSHE->GetLayoutHistoryState(); |
12570 | } |
12571 | } |
12572 | state.forget(aLayoutHistoryState); |
12573 | return NS_OK; |
12574 | } |
12575 | |
12576 | NS_IMETHODIMPnsresult |
12577 | nsDocShell::SetLayoutHistoryState(nsILayoutHistoryState* aLayoutHistoryState) { |
12578 | if (mOSHE) { |
12579 | mOSHE->SetLayoutHistoryState(aLayoutHistoryState); |
12580 | } |
12581 | if (mActiveEntry) { |
12582 | mActiveEntry->SetLayoutHistoryState(aLayoutHistoryState); |
12583 | } |
12584 | return NS_OK; |
12585 | } |
12586 | |
12587 | nsDocShell::InterfaceRequestorProxy::InterfaceRequestorProxy( |
12588 | nsIInterfaceRequestor* aRequestor) { |
12589 | if (aRequestor) { |
12590 | mWeakPtr = do_GetWeakReference(aRequestor); |
12591 | } |
12592 | } |
12593 | |
12594 | nsDocShell::InterfaceRequestorProxy::~InterfaceRequestorProxy() { |
12595 | mWeakPtr = nullptr; |
12596 | } |
12597 | |
12598 | 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" , 12598); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0" ") (" "illegal refcnt" ")"); do { *((volatile int*)__null) = 12598; __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" , 12598); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsDocShell::InterfaceRequestorProxy\" != nullptr" ") (" "Must specify a name" ")"); do { *((volatile int*)__null ) = 12598; __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" , 12598); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0" ") (" "dup release" ")"); do { *((volatile int*)__null) = 12598 ; __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" , 12598); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsDocShell::InterfaceRequestorProxy\" != nullptr" ") (" "Must specify a name" ")"); do { *((volatile int*)__null ) = 12598; __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" , 12598); 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; } |
12599 | |
12600 | NS_IMETHODIMPnsresult |
12601 | nsDocShell::InterfaceRequestorProxy::GetInterface(const nsIID& aIID, |
12602 | void** aSink) { |
12603 | 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" , 12603); return NS_ERROR_INVALID_POINTER; } } while (false); |
12604 | nsCOMPtr<nsIInterfaceRequestor> ifReq = do_QueryReferent(mWeakPtr); |
12605 | if (ifReq) { |
12606 | return ifReq->GetInterface(aIID, aSink); |
12607 | } |
12608 | *aSink = nullptr; |
12609 | return NS_NOINTERFACE; |
12610 | } |
12611 | |
12612 | //***************************************************************************** |
12613 | // nsDocShell::nsIAuthPromptProvider |
12614 | //***************************************************************************** |
12615 | |
12616 | NS_IMETHODIMPnsresult |
12617 | nsDocShell::GetAuthPrompt(uint32_t aPromptReason, const nsIID& aIID, |
12618 | void** aResult) { |
12619 | // a priority prompt request will override a false mAllowAuth setting |
12620 | bool priorityPrompt = (aPromptReason == PROMPT_PROXY); |
12621 | |
12622 | if (!mAllowAuth && !priorityPrompt) { |
12623 | return NS_ERROR_NOT_AVAILABLE; |
12624 | } |
12625 | |
12626 | // we're either allowing auth, or it's a proxy request |
12627 | nsresult rv; |
12628 | nsCOMPtr<nsIPromptFactory> wwatch = |
12629 | do_GetService(NS_WINDOWWATCHER_CONTRACTID"@mozilla.org/embedcomp/window-watcher;1", &rv); |
12630 | 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" , 12630); return rv; } } while (false); |
12631 | |
12632 | rv = EnsureScriptEnvironment(); |
12633 | 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" , 12633); return rv; } } while (false); |
12634 | |
12635 | // Get the an auth prompter for our window so that the parenting |
12636 | // of the dialogs works as it should when using tabs. |
12637 | |
12638 | return wwatch->GetPrompt(mScriptGlobal, aIID, |
12639 | reinterpret_cast<void**>(aResult)); |
12640 | } |
12641 | |
12642 | //***************************************************************************** |
12643 | // nsDocShell::nsILoadContext |
12644 | //***************************************************************************** |
12645 | |
12646 | NS_IMETHODIMPnsresult |
12647 | nsDocShell::GetAssociatedWindow(mozIDOMWindowProxy** aWindow) { |
12648 | CallGetInterface(this, aWindow); |
12649 | return NS_OK; |
12650 | } |
12651 | |
12652 | NS_IMETHODIMPnsresult |
12653 | nsDocShell::GetTopWindow(mozIDOMWindowProxy** aWindow) { |
12654 | return mBrowsingContext->GetTopWindow(aWindow); |
12655 | } |
12656 | |
12657 | NS_IMETHODIMPnsresult |
12658 | nsDocShell::GetTopFrameElement(Element** aElement) { |
12659 | return mBrowsingContext->GetTopFrameElement(aElement); |
12660 | } |
12661 | |
12662 | NS_IMETHODIMPnsresult |
12663 | nsDocShell::GetUseTrackingProtection(bool* aUseTrackingProtection) { |
12664 | return mBrowsingContext->GetUseTrackingProtection(aUseTrackingProtection); |
12665 | } |
12666 | |
12667 | NS_IMETHODIMPnsresult |
12668 | nsDocShell::SetUseTrackingProtection(bool aUseTrackingProtection) { |
12669 | return mBrowsingContext->SetUseTrackingProtection(aUseTrackingProtection); |
12670 | } |
12671 | |
12672 | NS_IMETHODIMPnsresult |
12673 | nsDocShell::GetIsContent(bool* aIsContent) { |
12674 | *aIsContent = (mItemType == typeContent); |
12675 | return NS_OK; |
12676 | } |
12677 | |
12678 | bool nsDocShell::IsOKToLoadURI(nsIURI* aURI) { |
12679 | 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" , 12679); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aURI" ") (" "Must have a URI!" ")"); do { *((volatile int*)__null) = 12679 ; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
12680 | |
12681 | if (!mFiredUnloadEvent) { |
12682 | return true; |
12683 | } |
12684 | |
12685 | if (!mLoadingURI) { |
12686 | return false; |
12687 | } |
12688 | |
12689 | bool isPrivateWin = false; |
12690 | Document* doc = GetDocument(); |
12691 | if (doc) { |
12692 | isPrivateWin = |
12693 | doc->NodePrincipal()->OriginAttributesRef().mPrivateBrowsingId > 0; |
12694 | } |
12695 | |
12696 | nsCOMPtr<nsIScriptSecurityManager> secMan = |
12697 | do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID"@mozilla.org/scriptsecuritymanager;1"); |
12698 | return secMan && NS_SUCCEEDED(secMan->CheckSameOriginURI(((bool)(__builtin_expect(!!(!NS_FAILED_impl(secMan->CheckSameOriginURI ( aURI, mLoadingURI, false, isPrivateWin))), 1))) |
12699 | aURI, mLoadingURI, false, isPrivateWin))((bool)(__builtin_expect(!!(!NS_FAILED_impl(secMan->CheckSameOriginURI ( aURI, mLoadingURI, false, isPrivateWin))), 1))); |
12700 | } |
12701 | |
12702 | // |
12703 | // Routines for selection and clipboard |
12704 | // |
12705 | nsresult nsDocShell::GetControllerForCommand(const char* aCommand, |
12706 | nsIController** aResult) { |
12707 | 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" , 12707); return NS_ERROR_INVALID_POINTER; } } while (false); |
12708 | *aResult = nullptr; |
12709 | |
12710 | 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" , 12710); return NS_ERROR_FAILURE; } } while (false); |
12711 | |
12712 | nsCOMPtr<nsPIWindowRoot> root = mScriptGlobal->GetTopWindowRoot(); |
12713 | 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" , 12713); return NS_ERROR_FAILURE; } } while (false); |
12714 | |
12715 | return root->GetControllerForCommand(aCommand, false /* for any window */, |
12716 | aResult); |
12717 | } |
12718 | |
12719 | NS_IMETHODIMPnsresult |
12720 | nsDocShell::IsCommandEnabled(const char* aCommand, bool* aResult) { |
12721 | 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" , 12721); return NS_ERROR_INVALID_POINTER; } } while (false); |
12722 | *aResult = false; |
12723 | |
12724 | nsresult rv = NS_ERROR_FAILURE; |
12725 | |
12726 | nsCOMPtr<nsIController> controller; |
12727 | rv = GetControllerForCommand(aCommand, getter_AddRefs(controller)); |
12728 | if (controller) { |
12729 | rv = controller->IsCommandEnabled(aCommand, aResult); |
12730 | } |
12731 | |
12732 | return rv; |
12733 | } |
12734 | |
12735 | NS_IMETHODIMPnsresult |
12736 | nsDocShell::DoCommand(const char* aCommand) { |
12737 | nsresult rv = NS_ERROR_FAILURE; |
12738 | |
12739 | nsCOMPtr<nsIController> controller; |
12740 | rv = GetControllerForCommand(aCommand, getter_AddRefs(controller)); |
12741 | if (controller) { |
12742 | rv = controller->DoCommand(aCommand); |
12743 | } |
12744 | |
12745 | return rv; |
12746 | } |
12747 | |
12748 | NS_IMETHODIMPnsresult |
12749 | nsDocShell::DoCommandWithParams(const char* aCommand, |
12750 | nsICommandParams* aParams) { |
12751 | nsCOMPtr<nsIController> controller; |
12752 | nsresult rv = GetControllerForCommand(aCommand, getter_AddRefs(controller)); |
12753 | 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" , 12753)) { |
12754 | return rv; |
12755 | } |
12756 | |
12757 | nsCOMPtr<nsICommandController> commandController = |
12758 | do_QueryInterface(controller, &rv); |
12759 | 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" , 12759)) { |
12760 | return rv; |
12761 | } |
12762 | |
12763 | return commandController->DoCommandWithParams(aCommand, aParams); |
12764 | } |
12765 | |
12766 | nsresult nsDocShell::EnsureCommandHandler() { |
12767 | if (!mCommandManager) { |
12768 | if (nsCOMPtr<nsPIDOMWindowOuter> domWindow = GetWindow()) { |
12769 | mCommandManager = new nsCommandManager(domWindow); |
12770 | } |
12771 | } |
12772 | return mCommandManager ? NS_OK : NS_ERROR_FAILURE; |
12773 | } |
12774 | |
12775 | // link handling |
12776 | |
12777 | class OnLinkClickEvent : public Runnable { |
12778 | public: |
12779 | OnLinkClickEvent(nsDocShell* aHandler, nsIContent* aContent, |
12780 | nsDocShellLoadState* aLoadState, bool aNoOpenerImplied, |
12781 | bool aIsTrusted, nsIPrincipal* aTriggeringPrincipal); |
12782 | |
12783 | NS_IMETHODvirtual nsresult Run() override { |
12784 | AutoPopupStatePusherAutoPopupStatePusherInternal popupStatePusher(mPopupState); |
12785 | |
12786 | // We need to set up an AutoJSAPI here for the following reason: When we |
12787 | // do OnLinkClickSync we'll eventually end up in |
12788 | // nsGlobalWindow::OpenInternal which only does popup blocking if |
12789 | // !LegacyIsCallerChromeOrNativeCode(). So we need to fake things so that |
12790 | // we don't look like native code as far as LegacyIsCallerNativeCode() is |
12791 | // concerned. |
12792 | AutoJSAPI jsapi; |
12793 | if (mIsTrusted || jsapi.Init(mContent->OwnerDoc()->GetScopeObject())) { |
12794 | mHandler->OnLinkClickSync(mContent, mLoadState, mNoOpenerImplied, |
12795 | mTriggeringPrincipal); |
12796 | } |
12797 | return NS_OK; |
12798 | } |
12799 | |
12800 | private: |
12801 | RefPtr<nsDocShell> mHandler; |
12802 | nsCOMPtr<nsIContent> mContent; |
12803 | RefPtr<nsDocShellLoadState> mLoadState; |
12804 | nsCOMPtr<nsIPrincipal> mTriggeringPrincipal; |
12805 | PopupBlocker::PopupControlState mPopupState; |
12806 | bool mNoOpenerImplied; |
12807 | bool mIsTrusted; |
12808 | }; |
12809 | |
12810 | OnLinkClickEvent::OnLinkClickEvent(nsDocShell* aHandler, nsIContent* aContent, |
12811 | nsDocShellLoadState* aLoadState, |
12812 | bool aNoOpenerImplied, bool aIsTrusted, |
12813 | nsIPrincipal* aTriggeringPrincipal) |
12814 | : mozilla::Runnable("OnLinkClickEvent"), |
12815 | mHandler(aHandler), |
12816 | mContent(aContent), |
12817 | mLoadState(aLoadState), |
12818 | mTriggeringPrincipal(aTriggeringPrincipal), |
12819 | mPopupState(PopupBlocker::GetPopupControlState()), |
12820 | mNoOpenerImplied(aNoOpenerImplied), |
12821 | mIsTrusted(aIsTrusted) {} |
12822 | |
12823 | nsresult nsDocShell::OnLinkClick( |
12824 | nsIContent* aContent, nsIURI* aURI, const nsAString& aTargetSpec, |
12825 | const nsAString& aFileName, nsIInputStream* aPostDataStream, |
12826 | nsIInputStream* aHeadersDataStream, bool aIsUserTriggered, bool aIsTrusted, |
12827 | nsIPrincipal* aTriggeringPrincipal, nsIContentSecurityPolicy* aCsp) { |
12828 | #ifndef ANDROID |
12829 | 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" , 12829); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aTriggeringPrincipal" ") (" "Need a valid triggeringPrincipal" ")"); do { *((volatile int*)__null) = 12829; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
12830 | #endif |
12831 | 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" , 12831); MOZ_PretendNoReturn(); } } while (0); |
12832 | |
12833 | if (!IsNavigationAllowed() || !IsOKToLoadURI(aURI)) { |
12834 | return NS_OK; |
12835 | } |
12836 | |
12837 | // On history navigation through Back/Forward buttons, don't execute |
12838 | // automatic JavaScript redirection such as |anchorElement.click()| or |
12839 | // |formElement.submit()|. |
12840 | // |
12841 | // XXX |formElement.submit()| bypasses this checkpoint because it calls |
12842 | // nsDocShell::OnLinkClickSync(...) instead. |
12843 | if (ShouldBlockLoadingForBackButton()) { |
12844 | return NS_OK; |
12845 | } |
12846 | |
12847 | if (aContent->IsEditable()) { |
12848 | return NS_OK; |
12849 | } |
12850 | |
12851 | Document* ownerDoc = aContent->OwnerDoc(); |
12852 | if (nsContentUtils::IsExternalProtocol(aURI)) { |
12853 | ownerDoc->EnsureNotEnteringAndExitFullscreen(); |
12854 | } |
12855 | |
12856 | bool noOpenerImplied = false; |
12857 | nsAutoString target(aTargetSpec); |
12858 | if (aFileName.IsVoid() && |
12859 | ShouldOpenInBlankTarget(aTargetSpec, aURI, aContent, aIsUserTriggered)) { |
12860 | target = u"_blank"; |
12861 | if (!aTargetSpec.Equals(target)) { |
12862 | noOpenerImplied = true; |
12863 | } |
12864 | } |
12865 | |
12866 | RefPtr<nsDocShellLoadState> loadState = new nsDocShellLoadState(aURI); |
12867 | loadState->SetTarget(target); |
12868 | loadState->SetFileName(aFileName); |
12869 | loadState->SetPostDataStream(aPostDataStream); |
12870 | loadState->SetHeadersStream(aHeadersDataStream); |
12871 | loadState->SetFirstParty(true); |
12872 | loadState->SetTriggeringPrincipal( |
12873 | aTriggeringPrincipal ? aTriggeringPrincipal : aContent->NodePrincipal()); |
12874 | loadState->SetPrincipalToInherit(aContent->NodePrincipal()); |
12875 | loadState->SetCsp(aCsp ? aCsp : aContent->GetCsp()); |
12876 | loadState->SetAllowFocusMove(UserActivation::IsHandlingUserInput()); |
12877 | |
12878 | nsCOMPtr<nsIRunnable> ev = |
12879 | new OnLinkClickEvent(this, aContent, loadState, noOpenerImplied, |
12880 | aIsTrusted, aTriggeringPrincipal); |
12881 | return Dispatch(ev.forget()); |
12882 | } |
12883 | |
12884 | bool nsDocShell::ShouldOpenInBlankTarget(const nsAString& aOriginalTarget, |
12885 | nsIURI* aLinkURI, nsIContent* aContent, |
12886 | bool aIsUserTriggered) { |
12887 | if (net::SchemeIsJavascript(aLinkURI)) { |
12888 | return false; |
12889 | } |
12890 | |
12891 | // External links from within app tabs should always open in new tabs |
12892 | // instead of replacing the app tab's page (Bug 575561) |
12893 | // nsIURI.host can throw for non-nsStandardURL nsIURIs. If we fail to |
12894 | // get either host, just return false to use the original target. |
12895 | nsAutoCString linkHost; |
12896 | if (NS_FAILED(aLinkURI->GetHost(linkHost))((bool)(__builtin_expect(!!(NS_FAILED_impl(aLinkURI->GetHost (linkHost))), 0)))) { |
12897 | return false; |
12898 | } |
12899 | |
12900 | // The targetTopLevelLinkClicksToBlank property on BrowsingContext allows |
12901 | // privileged code to change the default targeting behaviour. In particular, |
12902 | // if a user-initiated link click for the (or targetting the) top-level frame |
12903 | // is detected, we default the target to "_blank" to give it a new |
12904 | // top-level BrowsingContext. |
12905 | if (mBrowsingContext->TargetTopLevelLinkClicksToBlank() && aIsUserTriggered && |
12906 | ((aOriginalTarget.IsEmpty() && mBrowsingContext->IsTop()) || |
12907 | aOriginalTarget == u"_top"_ns)) { |
12908 | return true; |
12909 | } |
12910 | |
12911 | // Don't modify non-default targets. |
12912 | if (!aOriginalTarget.IsEmpty()) { |
12913 | return false; |
12914 | } |
12915 | |
12916 | // Only check targets that are in extension panels or app tabs. |
12917 | // (isAppTab will be false for app tab subframes). |
12918 | nsString mmGroup = mBrowsingContext->Top()->GetMessageManagerGroup(); |
12919 | if (!mmGroup.EqualsLiteral("webext-browsers") && |
12920 | !mBrowsingContext->IsAppTab()) { |
12921 | return false; |
12922 | } |
12923 | |
12924 | nsCOMPtr<nsIURI> docURI = aContent->OwnerDoc()->GetDocumentURIObject(); |
12925 | if (!docURI) { |
12926 | return false; |
12927 | } |
12928 | |
12929 | nsAutoCString docHost; |
12930 | if (NS_FAILED(docURI->GetHost(docHost))((bool)(__builtin_expect(!!(NS_FAILED_impl(docURI->GetHost (docHost))), 0)))) { |
12931 | return false; |
12932 | } |
12933 | |
12934 | if (linkHost.Equals(docHost)) { |
12935 | return false; |
12936 | } |
12937 | |
12938 | // Special case: ignore "www" prefix if it is part of host string |
12939 | return linkHost.Length() < docHost.Length() |
12940 | ? !docHost.Equals("www."_ns + linkHost) |
12941 | : !linkHost.Equals("www."_ns + docHost); |
12942 | } |
12943 | |
12944 | static bool ElementCanHaveNoopener(nsIContent* aContent) { |
12945 | // Make sure we are dealing with either an <A>, <AREA>, or <FORM> element in |
12946 | // the HTML, XHTML, or SVG namespace. |
12947 | return aContent->IsAnyOfHTMLElements(nsGkAtoms::a, nsGkAtoms::area, |
12948 | nsGkAtoms::form) || |
12949 | aContent->IsSVGElement(nsGkAtoms::a); |
12950 | } |
12951 | |
12952 | nsresult nsDocShell::OnLinkClickSync(nsIContent* aContent, |
12953 | nsDocShellLoadState* aLoadState, |
12954 | bool aNoOpenerImplied, |
12955 | nsIPrincipal* aTriggeringPrincipal) { |
12956 | if (!IsNavigationAllowed() || !IsOKToLoadURI(aLoadState->URI())) { |
12957 | return NS_OK; |
12958 | } |
12959 | |
12960 | // XXX When the linking node was HTMLFormElement, it is synchronous event. |
12961 | // That is, the caller of this method is not |OnLinkClickEvent::Run()| |
12962 | // but |HTMLFormElement::SubmitSubmission(...)|. |
12963 | if (aContent->IsHTMLElement(nsGkAtoms::form) && |
12964 | ShouldBlockLoadingForBackButton()) { |
12965 | return NS_OK; |
12966 | } |
12967 | |
12968 | if (aContent->IsEditable()) { |
12969 | return NS_OK; |
12970 | } |
12971 | |
12972 | // if the triggeringPrincipal is not passed explicitly, then we |
12973 | // fall back to using doc->NodePrincipal() as the triggeringPrincipal. |
12974 | nsCOMPtr<nsIPrincipal> triggeringPrincipal = |
12975 | aTriggeringPrincipal ? aTriggeringPrincipal : aContent->NodePrincipal(); |
12976 | |
12977 | { |
12978 | // defer to an external protocol handler if necessary... |
12979 | nsCOMPtr<nsIExternalProtocolService> extProtService = |
12980 | do_GetService(NS_EXTERNALPROTOCOLSERVICE_CONTRACTID"@mozilla.org/uriloader/external-protocol-service;1"); |
12981 | if (extProtService) { |
12982 | nsAutoCString scheme; |
12983 | aLoadState->URI()->GetScheme(scheme); |
12984 | if (!scheme.IsEmpty()) { |
12985 | // if the URL scheme does not correspond to an exposed protocol, then |
12986 | // we need to hand this link click over to the external protocol |
12987 | // handler. |
12988 | bool isExposed; |
12989 | nsresult rv = |
12990 | extProtService->IsExposedProtocol(scheme.get(), &isExposed); |
12991 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && !isExposed) { |
12992 | return extProtService->LoadURI( |
12993 | aLoadState->URI(), triggeringPrincipal, nullptr, mBrowsingContext, |
12994 | /* aTriggeredExternally */ |
12995 | false, |
12996 | /* aHasValidUserGestureActivation */ |
12997 | aContent->OwnerDoc()->HasValidTransientUserGestureActivation()); |
12998 | } |
12999 | } |
13000 | } |
13001 | } |
13002 | uint32_t triggeringSandboxFlags = 0; |
13003 | uint64_t triggeringWindowId = 0; |
13004 | bool triggeringStorageAccess = false; |
13005 | if (mBrowsingContext) { |
13006 | triggeringSandboxFlags = aContent->OwnerDoc()->GetSandboxFlags(); |
13007 | triggeringWindowId = aContent->OwnerDoc()->InnerWindowID(); |
13008 | triggeringStorageAccess = aContent->OwnerDoc()->UsingStorageAccess(); |
13009 | } |
13010 | |
13011 | uint32_t flags = INTERNAL_LOAD_FLAGS_NONE; |
13012 | bool elementCanHaveNoopener = ElementCanHaveNoopener(aContent); |
13013 | bool triggeringPrincipalIsSystemPrincipal = |
13014 | aLoadState->TriggeringPrincipal()->IsSystemPrincipal(); |
13015 | if (elementCanHaveNoopener) { |
13016 | 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" , 13016); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aContent->IsHTMLElement() || aContent->IsSVGElement()" ")"); do { *((volatile int*)__null) = 13016; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
13017 | nsAutoString relString; |
13018 | aContent->AsElement()->GetAttr(nsGkAtoms::rel, relString); |
13019 | nsWhitespaceTokenizerTemplate<nsContentUtils::IsHTMLWhitespace> tok( |
13020 | relString); |
13021 | |
13022 | bool targetBlank = aLoadState->Target().LowerCaseEqualsLiteral("_blank"); |
13023 | bool explicitOpenerSet = false; |
13024 | |
13025 | // The opener behaviour follows a hierarchy, such that if a higher |
13026 | // priority behaviour is specified, it always takes priority. That |
13027 | // priority is currently: norefrerer > noopener > opener > default |
13028 | |
13029 | while (tok.hasMoreTokens()) { |
13030 | const nsAString& token = tok.nextToken(); |
13031 | if (token.LowerCaseEqualsLiteral("noreferrer")) { |
13032 | flags |= INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER | |
13033 | INTERNAL_LOAD_FLAGS_NO_OPENER; |
13034 | // noreferrer cannot be overwritten by a 'rel=opener'. |
13035 | explicitOpenerSet = true; |
13036 | break; |
13037 | } |
13038 | |
13039 | if (token.LowerCaseEqualsLiteral("noopener")) { |
13040 | flags |= INTERNAL_LOAD_FLAGS_NO_OPENER; |
13041 | explicitOpenerSet = true; |
13042 | } |
13043 | |
13044 | if (targetBlank && StaticPrefs::dom_targetBlankNoOpener_enabled() && |
13045 | token.LowerCaseEqualsLiteral("opener") && !explicitOpenerSet) { |
13046 | explicitOpenerSet = true; |
13047 | } |
13048 | } |
13049 | |
13050 | if (targetBlank && StaticPrefs::dom_targetBlankNoOpener_enabled() && |
13051 | !explicitOpenerSet && !triggeringPrincipalIsSystemPrincipal) { |
13052 | flags |= INTERNAL_LOAD_FLAGS_NO_OPENER; |
13053 | } |
13054 | |
13055 | if (aNoOpenerImplied) { |
13056 | flags |= INTERNAL_LOAD_FLAGS_NO_OPENER; |
13057 | } |
13058 | } |
13059 | |
13060 | // Get the owner document of the link that was clicked, this will be |
13061 | // the document that the link is in, or the last document that the |
13062 | // link was in. From that document, we'll get the URI to use as the |
13063 | // referrer, since the current URI in this docshell may be a |
13064 | // new document that we're in the process of loading. |
13065 | RefPtr<Document> referrerDoc = aContent->OwnerDoc(); |
13066 | |
13067 | // Now check that the referrerDoc's inner window is the current inner |
13068 | // window for mScriptGlobal. If it's not, then we don't want to |
13069 | // follow this link. |
13070 | nsPIDOMWindowInner* referrerInner = referrerDoc->GetInnerWindow(); |
13071 | if (!mScriptGlobal || !referrerInner || |
13072 | mScriptGlobal->GetCurrentInnerWindow() != referrerInner) { |
13073 | // We're no longer the current inner window |
13074 | return NS_OK; |
13075 | } |
13076 | |
13077 | // referrer could be null here in some odd cases, but that's ok, |
13078 | // we'll just load the link w/o sending a referrer in those cases. |
13079 | |
13080 | // If this is an anchor element, grab its type property to use as a hint |
13081 | nsAutoString typeHint; |
13082 | RefPtr<HTMLAnchorElement> anchor = HTMLAnchorElement::FromNode(aContent); |
13083 | if (anchor) { |
13084 | anchor->GetType(typeHint); |
13085 | NS_ConvertUTF16toUTF8 utf8Hint(typeHint); |
13086 | nsAutoCString type, dummy; |
13087 | NS_ParseRequestContentType(utf8Hint, type, dummy); |
13088 | CopyUTF8toUTF16(type, typeHint); |
13089 | } |
13090 | |
13091 | uint32_t loadType = LOAD_LINK; |
13092 | if (aLoadState->IsFormSubmission()) { |
13093 | if (aLoadState->Target().IsEmpty()) { |
13094 | // We set the right load type here for form submissions with an empty |
13095 | // target. Form submission with a non-empty target are handled in |
13096 | // nsDocShell::PerformRetargeting after we've selected the correct target |
13097 | // BC. |
13098 | loadType = GetLoadTypeForFormSubmission(GetBrowsingContext(), aLoadState); |
13099 | } |
13100 | } else { |
13101 | // Link click can be triggered inside an onload handler, and we don't want |
13102 | // to add history entry in this case. |
13103 | bool inOnLoadHandler = false; |
13104 | GetIsExecutingOnLoadHandler(&inOnLoadHandler); |
13105 | if (inOnLoadHandler) { |
13106 | loadType = LOAD_NORMAL_REPLACE; |
13107 | } |
13108 | } |
13109 | |
13110 | nsCOMPtr<nsIReferrerInfo> referrerInfo = |
13111 | elementCanHaveNoopener ? new ReferrerInfo(*aContent->AsElement()) |
13112 | : new ReferrerInfo(*referrerDoc); |
13113 | RefPtr<WindowContext> context = mBrowsingContext->GetCurrentWindowContext(); |
13114 | |
13115 | aLoadState->SetTriggeringSandboxFlags(triggeringSandboxFlags); |
13116 | aLoadState->SetTriggeringWindowId(triggeringWindowId); |
13117 | aLoadState->SetTriggeringStorageAccess(triggeringStorageAccess); |
13118 | aLoadState->SetReferrerInfo(referrerInfo); |
13119 | aLoadState->SetInternalLoadFlags(flags); |
13120 | aLoadState->SetTypeHint(NS_ConvertUTF16toUTF8(typeHint)); |
13121 | aLoadState->SetLoadType(loadType); |
13122 | aLoadState->SetSourceBrowsingContext(mBrowsingContext); |
13123 | aLoadState->SetHasValidUserGestureActivation( |
13124 | context && context->HasValidTransientUserGestureActivation()); |
13125 | |
13126 | nsresult rv = InternalLoad(aLoadState); |
13127 | |
13128 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) { |
13129 | nsPingListener::DispatchPings(this, aContent, aLoadState->URI(), |
13130 | referrerInfo); |
13131 | } |
13132 | |
13133 | return rv; |
13134 | } |
13135 | |
13136 | nsresult nsDocShell::OnOverLink(nsIContent* aContent, nsIURI* aURI, |
13137 | const nsAString& aTargetSpec) { |
13138 | if (aContent->IsEditable()) { |
13139 | return NS_OK; |
13140 | } |
13141 | |
13142 | nsresult rv = NS_ERROR_FAILURE; |
13143 | |
13144 | nsCOMPtr<nsIWebBrowserChrome> browserChrome = do_GetInterface(mTreeOwner); |
13145 | if (!browserChrome) { |
13146 | return rv; |
13147 | } |
13148 | |
13149 | nsCOMPtr<nsIURI> exposableURI = nsIOService::CreateExposableURI(aURI); |
13150 | nsAutoCString spec; |
13151 | rv = exposableURI->GetDisplaySpec(spec); |
13152 | 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" , 13152); return rv; } } while (false); |
13153 | |
13154 | NS_ConvertUTF8toUTF16 uStr(spec); |
13155 | |
13156 | PredictorPredict(aURI, mCurrentURI, nsINetworkPredictor::PREDICT_LINK, |
13157 | aContent->NodePrincipal()->OriginAttributesRef(), nullptr); |
13158 | |
13159 | rv = browserChrome->SetLinkStatus(uStr); |
13160 | return rv; |
13161 | } |
13162 | |
13163 | nsresult nsDocShell::OnLeaveLink() { |
13164 | nsCOMPtr<nsIWebBrowserChrome> browserChrome(do_GetInterface(mTreeOwner)); |
13165 | nsresult rv = NS_ERROR_FAILURE; |
13166 | |
13167 | if (browserChrome) { |
13168 | rv = browserChrome->SetLinkStatus(u""_ns); |
13169 | } |
13170 | return rv; |
13171 | } |
13172 | |
13173 | bool nsDocShell::ShouldBlockLoadingForBackButton() { |
13174 | if (!(mLoadType & LOAD_CMD_HISTORY) || |
13175 | UserActivation::IsHandlingUserInput() || |
13176 | !Preferences::GetBool("accessibility.blockjsredirection")) { |
13177 | return false; |
13178 | } |
13179 | |
13180 | bool canGoForward = false; |
13181 | GetCanGoForward(&canGoForward); |
13182 | return canGoForward; |
13183 | } |
13184 | |
13185 | bool nsDocShell::PluginsAllowedInCurrentDoc() { |
13186 | if (!mDocumentViewer) { |
13187 | return false; |
13188 | } |
13189 | |
13190 | Document* doc = mDocumentViewer->GetDocument(); |
13191 | if (!doc) { |
13192 | return false; |
13193 | } |
13194 | |
13195 | return doc->GetAllowPlugins(); |
13196 | } |
13197 | |
13198 | //---------------------------------------------------------------------- |
13199 | // Web Shell Services API |
13200 | |
13201 | // This functions is only called when a new charset is detected in loading a |
13202 | // document. |
13203 | nsresult nsDocShell::CharsetChangeReloadDocument( |
13204 | mozilla::NotNull<const mozilla::Encoding*> aEncoding, int32_t aSource) { |
13205 | // XXX hack. keep the aCharset and aSource wait to pick it up |
13206 | nsCOMPtr<nsIDocumentViewer> viewer; |
13207 | 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" , 13207); return NS_ERROR_FAILURE; } } while (false); |
13208 | if (viewer) { |
13209 | int32_t source; |
13210 | Unused << viewer->GetReloadEncodingAndSource(&source); |
13211 | if (aSource > source) { |
13212 | viewer->SetReloadEncodingAndSource(aEncoding, aSource); |
13213 | if (eCharsetReloadRequested != mCharsetReloadState) { |
13214 | mCharsetReloadState = eCharsetReloadRequested; |
13215 | switch (mLoadType) { |
13216 | case LOAD_RELOAD_BYPASS_PROXY_AND_CACHE: |
13217 | return Reload(LOAD_FLAGS_CHARSET_CHANGE | LOAD_FLAGS_BYPASS_CACHE | |
13218 | LOAD_FLAGS_BYPASS_PROXY); |
13219 | case LOAD_RELOAD_BYPASS_CACHE: |
13220 | return Reload(LOAD_FLAGS_CHARSET_CHANGE | LOAD_FLAGS_BYPASS_CACHE); |
13221 | default: |
13222 | return Reload(LOAD_FLAGS_CHARSET_CHANGE); |
13223 | } |
13224 | } |
13225 | } |
13226 | } |
13227 | // return failure if this request is not accepted due to mCharsetReloadState |
13228 | return NS_ERROR_DOCSHELL_REQUEST_REJECTED; |
13229 | } |
13230 | |
13231 | nsresult nsDocShell::CharsetChangeStopDocumentLoad() { |
13232 | if (eCharsetReloadRequested != mCharsetReloadState) { |
13233 | Stop(nsIWebNavigation::STOP_ALL); |
13234 | return NS_OK; |
13235 | } |
13236 | // return failer if this request is not accepted due to mCharsetReloadState |
13237 | return NS_ERROR_DOCSHELL_REQUEST_REJECTED; |
13238 | } |
13239 | |
13240 | NS_IMETHODIMPnsresult nsDocShell::ExitPrintPreview() { |
13241 | #if NS_PRINT_PREVIEW1 |
13242 | nsCOMPtr<nsIWebBrowserPrint> viewer = do_QueryInterface(mDocumentViewer); |
13243 | return viewer->ExitPrintPreview(); |
13244 | #else |
13245 | return NS_OK; |
13246 | #endif |
13247 | } |
13248 | |
13249 | /* [infallible] */ |
13250 | NS_IMETHODIMPnsresult nsDocShell::GetIsTopLevelContentDocShell( |
13251 | bool* aIsTopLevelContentDocShell) { |
13252 | *aIsTopLevelContentDocShell = false; |
13253 | |
13254 | if (mItemType == typeContent) { |
13255 | *aIsTopLevelContentDocShell = mBrowsingContext->IsTopContent(); |
13256 | } |
13257 | |
13258 | return NS_OK; |
13259 | } |
13260 | |
13261 | // Implements nsILoadContext.originAttributes |
13262 | NS_IMETHODIMPnsresult |
13263 | nsDocShell::GetScriptableOriginAttributes(JSContext* aCx, |
13264 | JS::MutableHandle<JS::Value> aVal) { |
13265 | return mBrowsingContext->GetScriptableOriginAttributes(aCx, aVal); |
13266 | } |
13267 | |
13268 | // Implements nsIDocShell.GetOriginAttributes() |
13269 | NS_IMETHODIMPnsresult |
13270 | nsDocShell::GetOriginAttributes(JSContext* aCx, |
13271 | JS::MutableHandle<JS::Value> aVal) { |
13272 | return mBrowsingContext->GetScriptableOriginAttributes(aCx, aVal); |
13273 | } |
13274 | |
13275 | bool nsDocShell::ServiceWorkerAllowedToControlWindow(nsIPrincipal* aPrincipal, |
13276 | nsIURI* aURI) { |
13277 | 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" , 13277); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPrincipal" ")"); do { *((volatile int*)__null) = 13277; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
13278 | 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" , 13278); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aURI" ")") ; do { *((volatile int*)__null) = 13278; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
13279 | |
13280 | if (UsePrivateBrowsing() || mBrowsingContext->GetSandboxFlags()) { |
13281 | return false; |
13282 | } |
13283 | |
13284 | nsCOMPtr<nsIDocShellTreeItem> parent; |
13285 | GetInProcessSameTypeParent(getter_AddRefs(parent)); |
13286 | nsPIDOMWindowOuter* parentOuter = parent ? parent->GetWindow() : nullptr; |
13287 | nsPIDOMWindowInner* parentInner = |
13288 | parentOuter ? parentOuter->GetCurrentInnerWindow() : nullptr; |
13289 | |
13290 | StorageAccess storage = |
13291 | StorageAllowedForNewWindow(aPrincipal, aURI, parentInner); |
13292 | |
13293 | // If the partitioned service worker is enabled, service worker is allowed to |
13294 | // control the window if partition is enabled. |
13295 | if (StaticPrefs::privacy_partition_serviceWorkers() && parentInner) { |
13296 | RefPtr<Document> doc = parentInner->GetExtantDoc(); |
13297 | |
13298 | if (doc && StoragePartitioningEnabled(storage, doc->CookieJarSettings())) { |
13299 | return true; |
13300 | } |
13301 | } |
13302 | |
13303 | return storage == StorageAccess::eAllow; |
13304 | } |
13305 | |
13306 | nsresult nsDocShell::SetOriginAttributes(const OriginAttributes& aAttrs) { |
13307 | 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" , 13307); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mIsBeingDestroyed" ")"); do { *((volatile int*)__null) = 13307; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
13308 | return mBrowsingContext->SetOriginAttributes(aAttrs); |
13309 | } |
13310 | |
13311 | NS_IMETHODIMPnsresult |
13312 | nsDocShell::ResumeRedirectedLoad(uint64_t aIdentifier, int32_t aHistoryIndex) { |
13313 | RefPtr<nsDocShell> self = this; |
13314 | RefPtr<ChildProcessChannelListener> cpcl = |
13315 | ChildProcessChannelListener::GetSingleton(); |
13316 | |
13317 | // Call into InternalLoad with the pending channel when it is received. |
13318 | cpcl->RegisterCallback( |
13319 | aIdentifier, [self, aHistoryIndex]( |
13320 | nsDocShellLoadState* aLoadState, |
13321 | nsTArray<Endpoint<extensions::PStreamFilterParent>>&& |
13322 | aStreamFilterEndpoints, |
13323 | nsDOMNavigationTiming* aTiming) { |
13324 | 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" , 13324); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->GetPendingRedirectedChannel()" ")"); do { *((volatile int*)__null) = 13324; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
13325 | 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" , 13325)) { |
13326 | aLoadState->GetPendingRedirectedChannel()->CancelWithReason( |
13327 | NS_BINDING_ABORTED, "nsDocShell::mIsBeingDestroyed"_ns); |
13328 | return NS_BINDING_ABORTED; |
13329 | } |
13330 | |
13331 | self->mLoadType = aLoadState->LoadType(); |
13332 | nsCOMPtr<nsIURI> previousURI; |
13333 | uint32_t previousFlags = 0; |
13334 | ExtractLastVisit(aLoadState->GetPendingRedirectedChannel(), |
13335 | getter_AddRefs(previousURI), &previousFlags); |
13336 | self->SaveLastVisit(aLoadState->GetPendingRedirectedChannel(), |
13337 | previousURI, previousFlags); |
13338 | |
13339 | if (aTiming) { |
13340 | self->mTiming = new nsDOMNavigationTiming(self, aTiming); |
13341 | self->mBlankTiming = false; |
13342 | } |
13343 | |
13344 | // If we're performing a history load, locate the correct history entry, |
13345 | // and set the relevant bits on our loadState. |
13346 | if (aHistoryIndex >= 0 && self->GetSessionHistory() && |
13347 | !mozilla::SessionHistoryInParent()) { |
13348 | nsCOMPtr<nsISHistory> legacySHistory = |
13349 | self->GetSessionHistory()->LegacySHistory(); |
13350 | |
13351 | nsCOMPtr<nsISHEntry> entry; |
13352 | nsresult rv = legacySHistory->GetEntryAtIndex(aHistoryIndex, |
13353 | getter_AddRefs(entry)); |
13354 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) { |
13355 | legacySHistory->InternalSetRequestedIndex(aHistoryIndex); |
13356 | aLoadState->SetLoadType(LOAD_HISTORY); |
13357 | aLoadState->SetSHEntry(entry); |
13358 | } |
13359 | } |
13360 | |
13361 | self->InternalLoad(aLoadState); |
13362 | |
13363 | if (aLoadState->GetOriginalURIString().isSome()) { |
13364 | // Save URI string in case it's needed later when |
13365 | // sending to search engine service in EndPageLoad() |
13366 | self->mOriginalUriString = *aLoadState->GetOriginalURIString(); |
13367 | } |
13368 | |
13369 | for (auto& endpoint : aStreamFilterEndpoints) { |
13370 | extensions::StreamFilterParent::Attach( |
13371 | aLoadState->GetPendingRedirectedChannel(), std::move(endpoint)); |
13372 | } |
13373 | |
13374 | // If the channel isn't pending, then it means that InternalLoad |
13375 | // never connected it, and we shouldn't try to continue. This |
13376 | // can happen even if InternalLoad returned NS_OK. |
13377 | bool pending = false; |
13378 | aLoadState->GetPendingRedirectedChannel()->IsPending(&pending); |
13379 | 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" , 13379); MOZ_PretendNoReturn(); } } while (0); |
13380 | if (!pending) { |
13381 | return NS_BINDING_ABORTED; |
13382 | } |
13383 | return NS_OK; |
13384 | }); |
13385 | return NS_OK; |
13386 | } |
13387 | |
13388 | NS_IMETHODIMPnsresult |
13389 | nsDocShell::SetOriginAttributes(JS::Handle<JS::Value> aOriginAttributes, |
13390 | JSContext* aCx) { |
13391 | OriginAttributes attrs; |
13392 | if (!aOriginAttributes.isObject() || !attrs.Init(aCx, aOriginAttributes)) { |
13393 | return NS_ERROR_INVALID_ARG; |
13394 | } |
13395 | |
13396 | return SetOriginAttributes(attrs); |
13397 | } |
13398 | |
13399 | NS_IMETHODIMPnsresult |
13400 | nsDocShell::GetAsyncPanZoomEnabled(bool* aOut) { |
13401 | if (PresShell* presShell = GetPresShell()) { |
13402 | *aOut = presShell->AsyncPanZoomEnabled(); |
13403 | return NS_OK; |
13404 | } |
13405 | |
13406 | // If we don't have a presShell, fall back to the default platform value of |
13407 | // whether or not APZ is enabled. |
13408 | *aOut = gfxPlatform::AsyncPanZoomEnabled(); |
13409 | return NS_OK; |
13410 | } |
13411 | |
13412 | bool nsDocShell::HasUnloadedParent() { |
13413 | for (WindowContext* wc = GetBrowsingContext()->GetParentWindowContext(); wc; |
13414 | wc = wc->GetParentWindowContext()) { |
13415 | if (!wc->IsCurrent() || wc->IsDiscarded() || |
13416 | wc->GetBrowsingContext()->IsDiscarded()) { |
13417 | // If a parent is OOP and the parent WindowContext is no |
13418 | // longer current, we can assume the parent was unloaded. |
13419 | return true; |
13420 | } |
13421 | |
13422 | if (wc->GetBrowsingContext()->IsInProcess() && |
13423 | (!wc->GetBrowsingContext()->GetDocShell() || |
13424 | wc->GetBrowsingContext()->GetDocShell()->GetIsInUnload())) { |
13425 | return true; |
13426 | } |
13427 | } |
13428 | return false; |
13429 | } |
13430 | |
13431 | /* static */ |
13432 | bool nsDocShell::ShouldUpdateGlobalHistory(uint32_t aLoadType) { |
13433 | return !(aLoadType == LOAD_BYPASS_HISTORY || aLoadType == LOAD_ERROR_PAGE || |
13434 | aLoadType & LOAD_CMD_HISTORY); |
13435 | } |
13436 | |
13437 | void nsDocShell::UpdateGlobalHistoryTitle(nsIURI* aURI) { |
13438 | if (!mBrowsingContext->GetUseGlobalHistory() || UsePrivateBrowsing()) { |
13439 | return; |
13440 | } |
13441 | |
13442 | // Global history is interested into sub-frame visits only for link-coloring |
13443 | // purposes, thus title updates are skipped for those. |
13444 | // |
13445 | // Moreover, some iframe documents (such as the ones created via |
13446 | // document.open()) inherit the document uri of the caller, which would cause |
13447 | // us to override a previously set page title with one from the subframe. |
13448 | if (IsSubframe()) { |
13449 | return; |
13450 | } |
13451 | |
13452 | if (nsCOMPtr<IHistory> history = components::History::Service()) { |
13453 | history->SetURITitle(aURI, mTitle); |
13454 | } |
13455 | } |
13456 | |
13457 | bool nsDocShell::IsInvisible() { return mInvisible; } |
13458 | |
13459 | void nsDocShell::SetInvisible(bool aInvisible) { mInvisible = aInvisible; } |
13460 | |
13461 | /* static */ |
13462 | void nsDocShell::MaybeNotifyKeywordSearchLoading(const nsString& aProvider, |
13463 | const nsString& aKeyword) { |
13464 | if (aProvider.IsEmpty()) { |
13465 | return; |
13466 | } |
13467 | nsresult rv; |
13468 | nsCOMPtr<nsISupportsString> isupportsString = |
13469 | do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID"@mozilla.org/supports-string;1", &rv); |
13470 | 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" , 13470); return; } } while (false); |
13471 | |
13472 | rv = isupportsString->SetData(aProvider); |
13473 | 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" , 13473); return; } } while (false); |
13474 | |
13475 | nsCOMPtr<nsIObserverService> obsSvc = services::GetObserverService(); |
13476 | if (obsSvc) { |
13477 | // Note that "keyword-search" refers to a search via the url |
13478 | // bar, not a bookmarks keyword search. |
13479 | obsSvc->NotifyObservers(isupportsString, "keyword-search", aKeyword.get()); |
13480 | } |
13481 | } |
13482 | |
13483 | NS_IMETHODIMPnsresult |
13484 | nsDocShell::ShouldPrepareForIntercept(nsIURI* aURI, nsIChannel* aChannel, |
13485 | bool* aShouldIntercept) { |
13486 | return mInterceptController->ShouldPrepareForIntercept(aURI, aChannel, |
13487 | aShouldIntercept); |
13488 | } |
13489 | |
13490 | NS_IMETHODIMPnsresult |
13491 | nsDocShell::ChannelIntercepted(nsIInterceptedChannel* aChannel) { |
13492 | return mInterceptController->ChannelIntercepted(aChannel); |
13493 | } |
13494 | |
13495 | bool nsDocShell::InFrameSwap() { |
13496 | RefPtr<nsDocShell> shell = this; |
13497 | do { |
13498 | if (shell->mInFrameSwap) { |
13499 | return true; |
13500 | } |
13501 | shell = shell->GetInProcessParentDocshell(); |
13502 | } while (shell); |
13503 | return false; |
13504 | } |
13505 | |
13506 | UniquePtr<ClientSource> nsDocShell::TakeInitialClientSource() { |
13507 | return std::move(mInitialClientSource); |
13508 | } |
13509 | |
13510 | NS_IMETHODIMPnsresult |
13511 | nsDocShell::GetEditingSession(nsIEditingSession** aEditSession) { |
13512 | if (!NS_SUCCEEDED(EnsureEditorData())((bool)(__builtin_expect(!!(!NS_FAILED_impl(EnsureEditorData( ))), 1)))) { |
13513 | return NS_ERROR_FAILURE; |
13514 | } |
13515 | |
13516 | *aEditSession = do_AddRef(mEditorData->GetEditingSession()).take(); |
13517 | return *aEditSession ? NS_OK : NS_ERROR_FAILURE; |
13518 | } |
13519 | |
13520 | NS_IMETHODIMPnsresult |
13521 | nsDocShell::GetScriptableBrowserChild(nsIBrowserChild** aBrowserChild) { |
13522 | *aBrowserChild = GetBrowserChild().take(); |
13523 | return *aBrowserChild ? NS_OK : NS_ERROR_FAILURE; |
13524 | } |
13525 | |
13526 | already_AddRefed<nsIBrowserChild> nsDocShell::GetBrowserChild() { |
13527 | nsCOMPtr<nsIBrowserChild> tc = do_QueryReferent(mBrowserChild); |
13528 | return tc.forget(); |
13529 | } |
13530 | |
13531 | nsCommandManager* nsDocShell::GetCommandManager() { |
13532 | 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" , 13532); return nullptr; } } while (false); |
13533 | return mCommandManager; |
13534 | } |
13535 | |
13536 | NS_IMETHODIMP_(void)void |
13537 | nsDocShell::GetOriginAttributes(mozilla::OriginAttributes& aAttrs) { |
13538 | mBrowsingContext->GetOriginAttributes(aAttrs); |
13539 | } |
13540 | |
13541 | HTMLEditor* nsIDocShell::GetHTMLEditor() { |
13542 | nsDocShell* docShell = static_cast<nsDocShell*>(this); |
13543 | return docShell->GetHTMLEditorInternal(); |
13544 | } |
13545 | |
13546 | nsresult nsIDocShell::SetHTMLEditor(HTMLEditor* aHTMLEditor) { |
13547 | nsDocShell* docShell = static_cast<nsDocShell*>(this); |
13548 | return docShell->SetHTMLEditorInternal(aHTMLEditor); |
13549 | } |
13550 | |
13551 | #define MATRIX_LENGTH 20 |
13552 | |
13553 | NS_IMETHODIMPnsresult |
13554 | nsDocShell::SetColorMatrix(const nsTArray<float>& aMatrix) { |
13555 | if (aMatrix.Length() == MATRIX_LENGTH) { |
13556 | mColorMatrix.reset(new gfx::Matrix5x4()); |
13557 | static_assert( |
13558 | MATRIX_LENGTH * sizeof(float) == sizeof(mColorMatrix->components), |
13559 | "Size mismatch for our memcpy"); |
13560 | memcpy(mColorMatrix->components, aMatrix.Elements(), |
13561 | sizeof(mColorMatrix->components)); |
13562 | } else if (aMatrix.Length() == 0) { |
13563 | mColorMatrix.reset(); |
13564 | } else { |
13565 | return NS_ERROR_INVALID_ARG; |
13566 | } |
13567 | |
13568 | PresShell* presShell = GetPresShell(); |
13569 | if (!presShell) { |
13570 | return NS_ERROR_FAILURE; |
13571 | } |
13572 | |
13573 | nsIFrame* frame = presShell->GetRootFrame(); |
13574 | if (!frame) { |
13575 | return NS_ERROR_FAILURE; |
13576 | } |
13577 | |
13578 | frame->SchedulePaint(); |
13579 | |
13580 | return NS_OK; |
13581 | } |
13582 | |
13583 | NS_IMETHODIMPnsresult |
13584 | nsDocShell::GetColorMatrix(nsTArray<float>& aMatrix) { |
13585 | if (mColorMatrix) { |
13586 | aMatrix.SetLength(MATRIX_LENGTH); |
13587 | static_assert( |
13588 | MATRIX_LENGTH * sizeof(float) == sizeof(mColorMatrix->components), |
13589 | "Size mismatch for our memcpy"); |
13590 | memcpy(aMatrix.Elements(), mColorMatrix->components, |
13591 | MATRIX_LENGTH * sizeof(float)); |
13592 | } |
13593 | |
13594 | return NS_OK; |
13595 | } |
13596 | |
13597 | #undef MATRIX_LENGTH |
13598 | |
13599 | NS_IMETHODIMPnsresult |
13600 | nsDocShell::GetIsForceReloading(bool* aForceReload) { |
13601 | *aForceReload = IsForceReloading(); |
13602 | return NS_OK; |
13603 | } |
13604 | |
13605 | bool nsDocShell::IsForceReloading() { return IsForceReloadType(mLoadType); } |
13606 | |
13607 | NS_IMETHODIMPnsresult |
13608 | nsDocShell::GetBrowsingContextXPCOM(BrowsingContext** aBrowsingContext) { |
13609 | *aBrowsingContext = do_AddRef(mBrowsingContext).take(); |
13610 | return NS_OK; |
13611 | } |
13612 | |
13613 | BrowsingContext* nsDocShell::GetBrowsingContext() { return mBrowsingContext; } |
13614 | |
13615 | bool nsDocShell::GetIsAttemptingToNavigate() { |
13616 | // XXXbz the document.open spec says to abort even if there's just a |
13617 | // queued navigation task, sort of. It's not clear whether browsers |
13618 | // actually do that, and we didn't use to do it, so for now let's |
13619 | // not do that. |
13620 | // https://github.com/whatwg/html/issues/3447 tracks the spec side of this. |
13621 | if (mDocumentRequest) { |
13622 | // There's definitely a navigation in progress. |
13623 | return true; |
13624 | } |
13625 | |
13626 | // javascript: channels have slightly weird behavior: they're LOAD_BACKGROUND |
13627 | // until the script runs, which means they're not sending loadgroup |
13628 | // notifications and hence not getting set as mDocumentRequest. Look through |
13629 | // our loadgroup for document-level javascript: loads. |
13630 | if (!mLoadGroup) { |
13631 | return false; |
13632 | } |
13633 | |
13634 | nsCOMPtr<nsISimpleEnumerator> requests; |
13635 | mLoadGroup->GetRequests(getter_AddRefs(requests)); |
13636 | bool hasMore = false; |
13637 | while (NS_SUCCEEDED(requests->HasMoreElements(&hasMore))((bool)(__builtin_expect(!!(!NS_FAILED_impl(requests->HasMoreElements (&hasMore))), 1))) && hasMore) { |
13638 | nsCOMPtr<nsISupports> elem; |
13639 | requests->GetNext(getter_AddRefs(elem)); |
13640 | nsCOMPtr<nsIScriptChannel> scriptChannel(do_QueryInterface(elem)); |
13641 | if (!scriptChannel) { |
13642 | continue; |
13643 | } |
13644 | |
13645 | if (scriptChannel->GetIsDocumentLoad()) { |
13646 | // This is a javascript: load that might lead to a new document, |
13647 | // hence a navigation. |
13648 | return true; |
13649 | } |
13650 | } |
13651 | |
13652 | return mCheckingSessionHistory; |
13653 | } |
13654 | |
13655 | void nsDocShell::SetLoadingSessionHistoryInfo( |
13656 | const mozilla::dom::LoadingSessionHistoryInfo& aLoadingInfo, |
13657 | bool aNeedToReportActiveAfterLoadingBecomesActive) { |
13658 | // FIXME Would like to assert this, but can't yet. |
13659 | // MOZ_ASSERT(!mLoadingEntry); |
13660 | 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) |
13661 | ("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) |
13662 | 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); |
13663 | mLoadingEntry = MakeUnique<LoadingSessionHistoryInfo>(aLoadingInfo); |
13664 | mNeedToReportActiveAfterLoadingBecomesActive = |
13665 | aNeedToReportActiveAfterLoadingBecomesActive; |
13666 | } |
13667 | |
13668 | void nsDocShell::MoveLoadingToActiveEntry(bool aPersist, bool aExpired, |
13669 | uint32_t aCacheKey, |
13670 | nsIURI* aPreviousURI) { |
13671 | 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" , 13671); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mozilla::SessionHistoryInParent()" ")"); do { *((volatile int*)__null) = 13671; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
13672 | |
13673 | 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) |
13674 | ("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); |
13675 | |
13676 | UniquePtr<SessionHistoryInfo> previousActiveEntry(mActiveEntry.release()); |
13677 | mozilla::UniquePtr<mozilla::dom::LoadingSessionHistoryInfo> loadingEntry; |
13678 | mActiveEntryIsLoadingFromSessionHistory = |
13679 | mLoadingEntry && mLoadingEntry->mLoadIsFromSessionHistory; |
13680 | if (mLoadingEntry) { |
13681 | 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) |
13682 | ("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) |
13683 | "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) |
13684 | 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); |
13685 | mActiveEntry = MakeUnique<SessionHistoryInfo>(mLoadingEntry->mInfo); |
13686 | mLoadingEntry.swap(loadingEntry); |
13687 | if (!mActiveEntryIsLoadingFromSessionHistory) { |
13688 | if (mNeedToReportActiveAfterLoadingBecomesActive) { |
13689 | // Needed to pass various history length WPTs. |
13690 | mBrowsingContext->SetActiveSessionHistoryEntry( |
13691 | mozilla::Nothing(), mActiveEntry.get(), mLoadType, |
13692 | /* aUpdatedCacheKey = */ 0, false); |
13693 | } |
13694 | mBrowsingContext->IncrementHistoryEntryCountForBrowsingContext(); |
13695 | } |
13696 | } |
13697 | mNeedToReportActiveAfterLoadingBecomesActive = false; |
13698 | |
13699 | if (mActiveEntry) { |
13700 | if (aCacheKey != 0) { |
13701 | mActiveEntry->SetCacheKey(aCacheKey); |
13702 | } |
13703 | 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" , 13703); AnnotateMozCrashReason("MOZ_ASSERT" "(" "loadingEntry" ")"); do { *((volatile int*)__null) = 13703; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
13704 | uint32_t loadType = |
13705 | mLoadType == LOAD_ERROR_PAGE ? mFailedLoadType : mLoadType; |
13706 | |
13707 | if (loadingEntry->mLoadId != UINT64_MAX(18446744073709551615UL)) { |
13708 | // We're passing in mCurrentURI, which could be null. SessionHistoryCommit |
13709 | // does require a non-null uri if this is for a refresh load of the same |
13710 | // URI, but in that case mCurrentURI won't be null here. |
13711 | mBrowsingContext->SessionHistoryCommit( |
13712 | *loadingEntry, loadType, aPreviousURI, previousActiveEntry.get(), |
13713 | aPersist, false, aExpired, aCacheKey); |
13714 | } |
13715 | } |
13716 | } |
13717 | |
13718 | static bool IsFaviconLoad(nsIRequest* aRequest) { |
13719 | nsCOMPtr<nsIChannel> channel = do_QueryInterface(aRequest); |
13720 | if (!channel) { |
13721 | return false; |
13722 | } |
13723 | |
13724 | nsCOMPtr<nsILoadInfo> li = channel->LoadInfo(); |
13725 | return li && li->InternalContentPolicyType() == |
13726 | nsIContentPolicy::TYPE_INTERNAL_IMAGE_FAVICON; |
13727 | } |
13728 | |
13729 | void nsDocShell::RecordSingleChannelId(bool aStartRequest, |
13730 | nsIRequest* aRequest) { |
13731 | // Ignore favicon loads, they don't need to block caching. |
13732 | if (IsFaviconLoad(aRequest)) { |
13733 | return; |
13734 | } |
13735 | |
13736 | 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" , 13736); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mRequestForBlockingFromBFCacheCount > 0" ")"); do { *((volatile int*)__null) = 13736; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); } } while (false); |
13737 | |
13738 | mRequestForBlockingFromBFCacheCount += aStartRequest ? 1 : -1; |
13739 | |
13740 | if (mBrowsingContext->GetCurrentWindowContext()) { |
13741 | // We have three states: no request, one request with an id and |
13742 | // eiher one request without an id or multiple requests. Nothing() is no |
13743 | // request, Some(non-zero) is one request with an id and Some(0) is one |
13744 | // request without an id or multiple requests. |
13745 | Maybe<uint64_t> singleChannelId; |
13746 | if (mRequestForBlockingFromBFCacheCount > 1) { |
13747 | singleChannelId = Some(0); |
13748 | } else if (mRequestForBlockingFromBFCacheCount == 1) { |
13749 | nsCOMPtr<nsIIdentChannel> identChannel; |
13750 | if (aStartRequest) { |
13751 | identChannel = do_QueryInterface(aRequest); |
13752 | } else { |
13753 | // aChannel is the channel that's being removed, but we need to check if |
13754 | // the remaining channel in the loadgroup has an id. |
13755 | nsCOMPtr<nsISimpleEnumerator> requests; |
13756 | mLoadGroup->GetRequests(getter_AddRefs(requests)); |
13757 | for (const auto& request : SimpleEnumerator<nsIRequest>(requests)) { |
13758 | if (!IsFaviconLoad(request) && |
13759 | !!(identChannel = do_QueryInterface(request))) { |
13760 | break; |
13761 | } |
13762 | } |
13763 | } |
13764 | |
13765 | if (identChannel) { |
13766 | singleChannelId = Some(identChannel->ChannelId()); |
13767 | } else { |
13768 | singleChannelId = Some(0); |
13769 | } |
13770 | } else { |
13771 | 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" , 13771); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mRequestForBlockingFromBFCacheCount == 0" ")"); do { *((volatile int*)__null) = 13771; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
13772 | singleChannelId = Nothing(); |
13773 | } |
13774 | |
13775 | if (MOZ_UNLIKELY(MOZ_LOG_TEST(gSHIPBFCacheLog, LogLevel::Verbose))(__builtin_expect(!!((__builtin_expect(!!(mozilla::detail::log_test (gSHIPBFCacheLog, LogLevel::Verbose)), 0))), 0))) { |
13776 | nsAutoCString uri("[no uri]"); |
13777 | if (mCurrentURI) { |
13778 | uri = mCurrentURI->GetSpecOrDefault(); |
13779 | } |
13780 | if (singleChannelId.isNothing()) { |
13781 | 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) |
13782 | ("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) |
13783 | "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) |
13784 | 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); |
13785 | } else if (singleChannelId.value() == 0) { |
13786 | 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) |
13787 | ("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) |
13788 | "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) |
13789 | 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); |
13790 | } else { |
13791 | 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) |
13792 | ("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) |
13793 | " 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) |
13794 | 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); |
13795 | } |
13796 | } |
13797 | |
13798 | if (mSingleChannelId != singleChannelId) { |
13799 | mSingleChannelId = singleChannelId; |
13800 | WindowGlobalChild* wgc = |
13801 | mBrowsingContext->GetCurrentWindowContext()->GetWindowGlobalChild(); |
13802 | if (wgc) { |
13803 | wgc->SendSetSingleChannelId(singleChannelId); |
13804 | } |
13805 | } |
13806 | } |
13807 | } |
13808 | |
13809 | NS_IMETHODIMPnsresult |
13810 | nsDocShell::OnStartRequest(nsIRequest* aRequest) { |
13811 | if (MOZ_UNLIKELY(MOZ_LOG_TEST(gSHIPBFCacheLog, LogLevel::Verbose))(__builtin_expect(!!((__builtin_expect(!!(mozilla::detail::log_test (gSHIPBFCacheLog, LogLevel::Verbose)), 0))), 0))) { |
13812 | nsAutoCString uri("[no uri]"); |
13813 | if (mCurrentURI) { |
13814 | uri = mCurrentURI->GetSpecOrDefault(); |
13815 | } |
13816 | nsAutoCString name; |
13817 | aRequest->GetName(name); |
13818 | 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) |
13819 | ("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); |
13820 | } |
13821 | RecordSingleChannelId(true, aRequest); |
13822 | return nsDocLoader::OnStartRequest(aRequest); |
13823 | } |
13824 | |
13825 | NS_IMETHODIMPnsresult |
13826 | nsDocShell::OnStopRequest(nsIRequest* aRequest, nsresult aStatusCode) { |
13827 | if (MOZ_UNLIKELY(MOZ_LOG_TEST(gSHIPBFCacheLog, LogLevel::Verbose))(__builtin_expect(!!((__builtin_expect(!!(mozilla::detail::log_test (gSHIPBFCacheLog, LogLevel::Verbose)), 0))), 0))) { |
13828 | nsAutoCString uri("[no uri]"); |
13829 | if (mCurrentURI) { |
13830 | uri = mCurrentURI->GetSpecOrDefault(); |
13831 | } |
13832 | nsAutoCString name; |
13833 | aRequest->GetName(name); |
13834 | 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) |
13835 | 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) |
13836 | ("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); |
13837 | } |
13838 | RecordSingleChannelId(false, aRequest); |
13839 | return nsDocLoader::OnStopRequest(aRequest, aStatusCode); |
13840 | } |
13841 | |
13842 | void nsDocShell::MaybeDisconnectChildListenersOnPageHide() { |
13843 | 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" , 13843); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "XRE_IsContentProcess()" ")"); do { *((volatile int*)__null) = 13843; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
13844 | |
13845 | if (mChannelToDisconnectOnPageHide != 0 && mLoadGroup) { |
13846 | nsCOMPtr<nsISimpleEnumerator> requests; |
13847 | mLoadGroup->GetRequests(getter_AddRefs(requests)); |
13848 | for (const auto& request : SimpleEnumerator<nsIRequest>(requests)) { |
13849 | RefPtr<DocumentChannel> channel = do_QueryObject(request); |
13850 | if (channel && channel->ChannelId() == mChannelToDisconnectOnPageHide) { |
13851 | static_cast<DocumentChannelChild*>(channel.get()) |
13852 | ->DisconnectChildListeners(NS_BINDING_ABORTED, NS_BINDING_ABORTED); |
13853 | } |
13854 | } |
13855 | mChannelToDisconnectOnPageHide = 0; |
13856 | } |
13857 | } |