Backed out changeset b71c8c052463 (bug 1943846) for causing mass failures. CLOSED...
[gecko.git] / netwerk / ipc / DocumentChannel.cpp
blob0e8a9e02da88877ff2862d749b65f0c6da6ce64c
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set sw=2 ts=8 et tw=80 : */
4 /* This Source Code Form is subject to the terms of the Mozilla Public
5 * License, v. 2.0. If a copy of the MPL was not distributed with this
6 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
8 #include "mozilla/net/DocumentChannel.h"
10 #include <inttypes.h>
11 #include <utility>
12 #include "mozIDOMWindow.h"
13 #include "mozilla/AlreadyAddRefed.h"
14 #include "mozilla/Assertions.h"
15 #include "mozilla/LoadInfo.h"
16 #include "mozilla/Logging.h"
17 #include "mozilla/RefPtr.h"
18 #include "mozilla/TimeStamp.h"
19 #include "mozilla/Unused.h"
20 #include "mozilla/dom/Document.h"
21 #include "mozilla/net/DocumentChannelChild.h"
22 #include "mozilla/net/ParentProcessDocumentChannel.h"
23 #include "nsCOMPtr.h"
24 #include "nsDebug.h"
25 #include "nsDocShell.h"
26 #include "nsDocShellLoadState.h"
27 #include "nsHttpHandler.h"
28 #include "nsIContentPolicy.h"
29 #include "nsIInterfaceRequestor.h"
30 #include "nsILoadContext.h"
31 #include "nsILoadGroup.h"
32 #include "nsILoadInfo.h"
33 #include "nsIStreamListener.h"
34 #include "nsIURI.h"
35 #include "nsLoadGroup.h"
36 #include "nsMimeTypes.h"
37 #include "nsNetUtil.h"
38 #include "nsPIDOMWindow.h"
39 #include "nsPIDOMWindowInlines.h"
40 #include "nsStringFwd.h"
41 #include "nsThreadUtils.h"
42 #include "nsXULAppAPI.h"
43 #include "nscore.h"
45 using namespace mozilla::dom;
46 using namespace mozilla::ipc;
48 extern mozilla::LazyLogModule gDocumentChannelLog;
49 #define LOG(fmt) MOZ_LOG(gDocumentChannelLog, mozilla::LogLevel::Verbose, fmt)
51 namespace mozilla {
52 namespace net {
54 //-----------------------------------------------------------------------------
55 // DocumentChannel::nsISupports
57 NS_IMPL_ADDREF(DocumentChannel)
58 NS_IMPL_RELEASE(DocumentChannel)
60 NS_INTERFACE_MAP_BEGIN(DocumentChannel)
61 NS_INTERFACE_MAP_ENTRY(nsIRequest)
62 NS_INTERFACE_MAP_ENTRY(nsIChannel)
63 NS_INTERFACE_MAP_ENTRY(nsIIdentChannel)
64 NS_INTERFACE_MAP_ENTRY_CONCRETE(DocumentChannel)
65 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIRequest)
66 NS_INTERFACE_MAP_END
68 DocumentChannel::DocumentChannel(nsDocShellLoadState* aLoadState,
69 net::LoadInfo* aLoadInfo,
70 nsLoadFlags aLoadFlags, uint32_t aCacheKey,
71 bool aUriModified,
72 bool aIsEmbeddingBlockedError)
73 : mLoadState(aLoadState),
74 mCacheKey(aCacheKey),
75 mLoadFlags(aLoadFlags),
76 mURI(aLoadState->URI()),
77 mLoadInfo(aLoadInfo),
78 mUriModified(aUriModified),
79 mIsEmbeddingBlockedError(aIsEmbeddingBlockedError) {
80 LOG(("DocumentChannel ctor [this=%p, uri=%s]", this,
81 aLoadState->URI()->GetSpecOrDefault().get()));
82 RefPtr<nsHttpHandler> handler = nsHttpHandler::GetInstance();
83 uint64_t channelId;
84 Unused << handler->NewChannelId(channelId);
85 mChannelId = channelId;
88 NS_IMETHODIMP
89 DocumentChannel::AsyncOpen(nsIStreamListener* aListener) {
90 MOZ_CRASH("If we get here, something is broken");
91 return NS_ERROR_NOT_IMPLEMENTED;
94 void DocumentChannel::ShutdownListeners(nsresult aStatusCode) {
95 LOG(("DocumentChannel ShutdownListeners [this=%p, status=%" PRIx32 "]", this,
96 static_cast<uint32_t>(aStatusCode)));
97 mStatus = aStatusCode;
99 nsCOMPtr<nsIStreamListener> listener = mListener;
100 if (listener) {
101 listener->OnStartRequest(this);
104 mIsPending = false;
106 listener = mListener; // it might have changed!
107 nsCOMPtr<nsILoadGroup> loadGroup = mLoadGroup;
109 mListener = nullptr;
110 mLoadGroup = nullptr;
111 mCallbacks = nullptr;
113 NS_DispatchToMainThread(NS_NewRunnableFunction(
114 "DocumentChannel::ShutdownListeners", [=, self = RefPtr{this}] {
115 if (listener) {
116 listener->OnStopRequest(self, aStatusCode);
119 if (loadGroup) {
120 loadGroup->RemoveRequest(self, nullptr, aStatusCode);
122 }));
124 DeleteIPDL();
127 void DocumentChannel::DisconnectChildListeners(
128 const nsresult& aStatus, const nsresult& aLoadGroupStatus) {
129 MOZ_ASSERT(NS_FAILED(aStatus));
130 mStatus = aLoadGroupStatus;
131 // Make sure we remove from the load group before
132 // setting mStatus, as existing tests expect the
133 // status to be successful when we disconnect.
134 if (mLoadGroup) {
135 mLoadGroup->RemoveRequest(this, nullptr, aStatus);
136 mLoadGroup = nullptr;
139 ShutdownListeners(aStatus);
142 nsDocShell* DocumentChannel::GetDocShell() {
143 nsCOMPtr<nsILoadContext> loadContext;
144 NS_QueryNotificationCallbacks(this, loadContext);
145 if (!loadContext) {
146 return nullptr;
148 nsCOMPtr<mozIDOMWindowProxy> domWindow;
149 loadContext->GetAssociatedWindow(getter_AddRefs(domWindow));
150 if (!domWindow) {
151 return nullptr;
153 auto* pDomWindow = nsPIDOMWindowOuter::From(domWindow);
154 nsIDocShell* docshell = pDomWindow->GetDocShell();
155 return nsDocShell::Cast(docshell);
158 static bool URIUsesDocChannel(nsIURI* aURI) {
159 if (SchemeIsJavascript(aURI)) {
160 return false;
163 nsCString spec = aURI->GetSpecOrDefault();
164 return !spec.EqualsLiteral("about:crashcontent");
167 bool DocumentChannel::CanUseDocumentChannel(nsIURI* aURI) {
168 // We want to use DocumentChannel if we're using a supported scheme.
169 return URIUsesDocChannel(aURI);
172 /* static */
173 already_AddRefed<DocumentChannel> DocumentChannel::CreateForDocument(
174 nsDocShellLoadState* aLoadState, class LoadInfo* aLoadInfo,
175 nsLoadFlags aLoadFlags, nsIInterfaceRequestor* aNotificationCallbacks,
176 uint32_t aCacheKey, bool aUriModified, bool aIsEmbeddingBlockedError) {
177 RefPtr<DocumentChannel> channel;
178 if (XRE_IsContentProcess()) {
179 channel =
180 new DocumentChannelChild(aLoadState, aLoadInfo, aLoadFlags, aCacheKey,
181 aUriModified, aIsEmbeddingBlockedError);
182 } else {
183 channel = new ParentProcessDocumentChannel(
184 aLoadState, aLoadInfo, aLoadFlags, aCacheKey, aUriModified,
185 aIsEmbeddingBlockedError);
187 channel->SetNotificationCallbacks(aNotificationCallbacks);
188 return channel.forget();
191 /* static */
192 already_AddRefed<DocumentChannel> DocumentChannel::CreateForObject(
193 nsDocShellLoadState* aLoadState, class LoadInfo* aLoadInfo,
194 nsLoadFlags aLoadFlags, nsIInterfaceRequestor* aNotificationCallbacks) {
195 return CreateForDocument(aLoadState, aLoadInfo, aLoadFlags,
196 aNotificationCallbacks, 0, false, false);
199 NS_IMETHODIMP DocumentChannel::SetCanceledReason(const nsACString& aReason) {
200 return SetCanceledReasonImpl(aReason);
203 NS_IMETHODIMP DocumentChannel::GetCanceledReason(nsACString& aReason) {
204 return GetCanceledReasonImpl(aReason);
207 NS_IMETHODIMP DocumentChannel::CancelWithReason(nsresult aStatus,
208 const nsACString& aReason) {
209 return CancelWithReasonImpl(aStatus, aReason);
212 NS_IMETHODIMP
213 DocumentChannel::Cancel(nsresult aStatusCode) {
214 MOZ_CRASH("If we get here, something is broken");
215 return NS_ERROR_NOT_IMPLEMENTED;
218 NS_IMETHODIMP
219 DocumentChannel::Suspend() {
220 MOZ_CRASH("If we get here, something is broken");
221 return NS_ERROR_NOT_IMPLEMENTED;
224 NS_IMETHODIMP
225 DocumentChannel::Resume() {
226 MOZ_CRASH("If we get here, something is broken");
227 return NS_ERROR_NOT_IMPLEMENTED;
230 //-----------------------------------------------------------------------------
231 // Remainder of nsIRequest/nsIChannel.
232 //-----------------------------------------------------------------------------
234 NS_IMETHODIMP DocumentChannel::GetNotificationCallbacks(
235 nsIInterfaceRequestor** aCallbacks) {
236 nsCOMPtr<nsIInterfaceRequestor> callbacks(mCallbacks);
237 callbacks.forget(aCallbacks);
238 return NS_OK;
241 NS_IMETHODIMP DocumentChannel::SetNotificationCallbacks(
242 nsIInterfaceRequestor* aNotificationCallbacks) {
243 mCallbacks = aNotificationCallbacks;
244 return NS_OK;
247 NS_IMETHODIMP DocumentChannel::GetLoadGroup(nsILoadGroup** aLoadGroup) {
248 nsCOMPtr<nsILoadGroup> loadGroup(mLoadGroup);
249 loadGroup.forget(aLoadGroup);
250 return NS_OK;
253 NS_IMETHODIMP DocumentChannel::SetLoadGroup(nsILoadGroup* aLoadGroup) {
254 mLoadGroup = aLoadGroup;
255 return NS_OK;
258 NS_IMETHODIMP DocumentChannel::GetStatus(nsresult* aStatus) {
259 *aStatus = mStatus;
260 return NS_OK;
263 NS_IMETHODIMP DocumentChannel::GetName(nsACString& aResult) {
264 if (!mURI) {
265 aResult.Truncate();
266 return NS_OK;
268 nsCString spec;
269 nsresult rv = mURI->GetSpec(spec);
270 NS_ENSURE_SUCCESS(rv, rv);
272 aResult.AssignLiteral("documentchannel:");
273 aResult.Append(spec);
274 return NS_OK;
277 NS_IMETHODIMP DocumentChannel::IsPending(bool* aResult) {
278 *aResult = mIsPending;
279 return NS_OK;
282 NS_IMETHODIMP DocumentChannel::GetLoadFlags(nsLoadFlags* aLoadFlags) {
283 *aLoadFlags = mLoadFlags;
284 return NS_OK;
287 NS_IMETHODIMP
288 DocumentChannel::GetTRRMode(nsIRequest::TRRMode* aTRRMode) {
289 return GetTRRModeImpl(aTRRMode);
292 NS_IMETHODIMP
293 DocumentChannel::SetTRRMode(nsIRequest::TRRMode aTRRMode) {
294 return SetTRRModeImpl(aTRRMode);
297 NS_IMETHODIMP DocumentChannel::SetLoadFlags(nsLoadFlags aLoadFlags) {
298 nsLoadFlags mayChange = 0;
299 if (mLoadInfo->GetExternalContentPolicyType() ==
300 ExtContentPolicy::TYPE_OBJECT) {
301 // Setting load flags for TYPE_OBJECT is OK, so long as the channel to
302 // parent isn't opened yet, or we're only setting the `LOAD_DOCUMENT_URI`
303 // flag.
304 mayChange = mWasOpened ? LOAD_DOCUMENT_URI : ~0u;
305 } else if (!mWasOpened) {
306 // If we haven't been opened yet, allow the LoadGroup to
307 // set cache control flags inherited from the default channel.
308 mayChange = nsLoadGroup::kInheritedLoadFlags;
311 // Check if we're allowed to adjust these flags.
312 if ((mLoadFlags & ~mayChange) == (aLoadFlags & ~mayChange)) {
313 mLoadFlags = aLoadFlags;
314 return NS_OK;
316 MOZ_CRASH_UNSAFE_PRINTF(
317 "DocumentChannel::SetLoadFlags: Don't set flags after creation "
318 "(differing flags %x != %x)",
319 (mLoadFlags ^ aLoadFlags) & mLoadFlags,
320 (mLoadFlags ^ aLoadFlags) & aLoadFlags);
321 return NS_OK;
324 NS_IMETHODIMP DocumentChannel::GetOriginalURI(nsIURI** aOriginalURI) {
325 nsCOMPtr<nsIURI> originalURI =
326 mLoadState->OriginalURI() ? mLoadState->OriginalURI() : mLoadState->URI();
327 originalURI.forget(aOriginalURI);
328 return NS_OK;
331 NS_IMETHODIMP DocumentChannel::SetOriginalURI(nsIURI* aOriginalURI) {
332 MOZ_CRASH("If we get here, something is broken");
333 return NS_ERROR_NOT_IMPLEMENTED;
336 NS_IMETHODIMP DocumentChannel::GetURI(nsIURI** aURI) {
337 nsCOMPtr<nsIURI> uri(mURI);
338 uri.forget(aURI);
339 return NS_OK;
342 NS_IMETHODIMP DocumentChannel::GetOwner(nsISupports** aOwner) {
343 nsCOMPtr<nsISupports> owner(mOwner);
344 owner.forget(aOwner);
345 return NS_OK;
348 NS_IMETHODIMP DocumentChannel::SetOwner(nsISupports* aOwner) {
349 mOwner = aOwner;
350 return NS_OK;
353 NS_IMETHODIMP DocumentChannel::GetSecurityInfo(
354 nsITransportSecurityInfo** aSecurityInfo) {
355 *aSecurityInfo = nullptr;
356 return NS_OK;
359 NS_IMETHODIMP DocumentChannel::GetContentType(nsACString& aContentType) {
360 // We may be trying to load HTML object data, and have determined that we're
361 // going to be performing a document load. In that case, fake the "text/html"
362 // content type for nsObjectLoadingContent.
363 if ((mLoadFlags & nsIRequest::LOAD_HTML_OBJECT_DATA) &&
364 (mLoadFlags & nsIChannel::LOAD_DOCUMENT_URI)) {
365 aContentType = TEXT_HTML;
366 return NS_OK;
369 NS_ERROR("If we get here, something is broken");
370 return NS_ERROR_NOT_IMPLEMENTED;
373 NS_IMETHODIMP DocumentChannel::SetContentType(const nsACString& aContentType) {
374 MOZ_CRASH("If we get here, something is broken");
375 return NS_ERROR_NOT_IMPLEMENTED;
378 NS_IMETHODIMP DocumentChannel::GetContentCharset(nsACString& aContentCharset) {
379 MOZ_CRASH("If we get here, something is broken");
380 return NS_ERROR_NOT_IMPLEMENTED;
383 NS_IMETHODIMP DocumentChannel::SetContentCharset(
384 const nsACString& aContentCharset) {
385 MOZ_CRASH("If we get here, something is broken");
386 return NS_ERROR_NOT_IMPLEMENTED;
389 NS_IMETHODIMP DocumentChannel::GetContentLength(int64_t* aContentLength) {
390 MOZ_CRASH("If we get here, something is broken");
391 return NS_ERROR_NOT_IMPLEMENTED;
394 NS_IMETHODIMP DocumentChannel::SetContentLength(int64_t aContentLength) {
395 MOZ_CRASH("If we get here, something is broken");
396 return NS_ERROR_NOT_IMPLEMENTED;
399 NS_IMETHODIMP DocumentChannel::Open(nsIInputStream** aStream) {
400 MOZ_CRASH("If we get here, something is broken");
401 return NS_ERROR_NOT_IMPLEMENTED;
404 NS_IMETHODIMP DocumentChannel::GetContentDisposition(
405 uint32_t* aContentDisposition) {
406 MOZ_CRASH("If we get here, something is broken");
407 return NS_ERROR_NOT_IMPLEMENTED;
410 NS_IMETHODIMP DocumentChannel::SetContentDisposition(
411 uint32_t aContentDisposition) {
412 MOZ_CRASH("If we get here, something is broken");
413 return NS_ERROR_NOT_IMPLEMENTED;
416 NS_IMETHODIMP DocumentChannel::GetContentDispositionFilename(
417 nsAString& aContentDispositionFilename) {
418 MOZ_CRASH("If we get here, something will be broken");
419 return NS_ERROR_NOT_IMPLEMENTED;
422 NS_IMETHODIMP DocumentChannel::SetContentDispositionFilename(
423 const nsAString& aContentDispositionFilename) {
424 MOZ_CRASH("If we get here, something will be broken");
425 return NS_ERROR_NOT_IMPLEMENTED;
428 NS_IMETHODIMP DocumentChannel::GetContentDispositionHeader(
429 nsACString& aContentDispositionHeader) {
430 MOZ_CRASH("If we get here, something is broken");
431 return NS_ERROR_NOT_IMPLEMENTED;
434 NS_IMETHODIMP DocumentChannel::GetLoadInfo(nsILoadInfo** aLoadInfo) {
435 nsCOMPtr<nsILoadInfo> loadInfo(mLoadInfo);
436 loadInfo.forget(aLoadInfo);
437 return NS_OK;
440 NS_IMETHODIMP DocumentChannel::SetLoadInfo(nsILoadInfo* aLoadInfo) {
441 MOZ_CRASH("If we get here, something is broken");
442 return NS_ERROR_NOT_IMPLEMENTED;
445 NS_IMETHODIMP DocumentChannel::GetIsDocument(bool* aIsDocument) {
446 return NS_GetIsDocumentChannel(this, aIsDocument);
449 NS_IMETHODIMP DocumentChannel::GetCanceled(bool* aCanceled) {
450 *aCanceled = mCanceled;
451 return NS_OK;
454 //-----------------------------------------------------------------------------
455 // nsIIdentChannel
456 //-----------------------------------------------------------------------------
458 NS_IMETHODIMP
459 DocumentChannel::GetChannelId(uint64_t* aChannelId) {
460 *aChannelId = mChannelId;
461 return NS_OK;
464 NS_IMETHODIMP
465 DocumentChannel::SetChannelId(uint64_t aChannelId) {
466 mChannelId = aChannelId;
467 return NS_OK;
470 //-----------------------------------------------------------------------------
471 // Helpers
472 //-----------------------------------------------------------------------------
474 uint64_t InnerWindowIDForExtantDoc(nsDocShell* docShell) {
475 if (!docShell) {
476 return 0;
479 Document* doc = docShell->GetExtantDocument();
480 if (!doc) {
481 return 0;
484 return doc->InnerWindowID();
487 } // namespace net
488 } // namespace mozilla
490 #undef LOG