Backed out changeset f1426851ae30 (bug 1844755) for causing failures on test_printpre...
[gecko.git] / netwerk / ipc / DocumentChannel.cpp
blob7aff42a0c6a1836dfd90e9f31f755c2c23fe1f34
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 "nsMimeTypes.h"
36 #include "nsNetUtil.h"
37 #include "nsPIDOMWindow.h"
38 #include "nsPIDOMWindowInlines.h"
39 #include "nsStringFwd.h"
40 #include "nsThreadUtils.h"
41 #include "nsXULAppAPI.h"
42 #include "nscore.h"
44 using namespace mozilla::dom;
45 using namespace mozilla::ipc;
47 extern mozilla::LazyLogModule gDocumentChannelLog;
48 #define LOG(fmt) MOZ_LOG(gDocumentChannelLog, mozilla::LogLevel::Verbose, fmt)
50 namespace mozilla {
51 namespace net {
53 //-----------------------------------------------------------------------------
54 // DocumentChannel::nsISupports
56 NS_IMPL_ADDREF(DocumentChannel)
57 NS_IMPL_RELEASE(DocumentChannel)
59 NS_INTERFACE_MAP_BEGIN(DocumentChannel)
60 NS_INTERFACE_MAP_ENTRY(nsIRequest)
61 NS_INTERFACE_MAP_ENTRY(nsIChannel)
62 NS_INTERFACE_MAP_ENTRY(nsIIdentChannel)
63 NS_INTERFACE_MAP_ENTRY_CONCRETE(DocumentChannel)
64 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIRequest)
65 NS_INTERFACE_MAP_END
67 DocumentChannel::DocumentChannel(nsDocShellLoadState* aLoadState,
68 net::LoadInfo* aLoadInfo,
69 nsLoadFlags aLoadFlags, uint32_t aCacheKey,
70 bool aUriModified, bool aIsXFOError)
71 : mLoadState(aLoadState),
72 mCacheKey(aCacheKey),
73 mLoadFlags(aLoadFlags),
74 mURI(aLoadState->URI()),
75 mLoadInfo(aLoadInfo),
76 mUriModified(aUriModified),
77 mIsXFOError(aIsXFOError) {
78 LOG(("DocumentChannel ctor [this=%p, uri=%s]", this,
79 aLoadState->URI()->GetSpecOrDefault().get()));
80 RefPtr<nsHttpHandler> handler = nsHttpHandler::GetInstance();
81 uint64_t channelId;
82 Unused << handler->NewChannelId(channelId);
83 mChannelId = channelId;
86 NS_IMETHODIMP
87 DocumentChannel::AsyncOpen(nsIStreamListener* aListener) {
88 MOZ_CRASH("If we get here, something is broken");
89 return NS_ERROR_NOT_IMPLEMENTED;
92 void DocumentChannel::ShutdownListeners(nsresult aStatusCode) {
93 LOG(("DocumentChannel ShutdownListeners [this=%p, status=%" PRIx32 "]", this,
94 static_cast<uint32_t>(aStatusCode)));
95 mStatus = aStatusCode;
97 nsCOMPtr<nsIStreamListener> listener = mListener;
98 if (listener) {
99 listener->OnStartRequest(this);
102 mIsPending = false;
104 listener = mListener; // it might have changed!
105 nsCOMPtr<nsILoadGroup> loadGroup = mLoadGroup;
107 mListener = nullptr;
108 mLoadGroup = nullptr;
109 mCallbacks = nullptr;
111 NS_DispatchToMainThread(NS_NewRunnableFunction(
112 "DocumentChannel::ShutdownListeners", [=, self = RefPtr{this}] {
113 if (listener) {
114 listener->OnStopRequest(self, aStatusCode);
117 if (loadGroup) {
118 loadGroup->RemoveRequest(self, nullptr, aStatusCode);
120 }));
122 DeleteIPDL();
125 void DocumentChannel::DisconnectChildListeners(
126 const nsresult& aStatus, const nsresult& aLoadGroupStatus) {
127 MOZ_ASSERT(NS_FAILED(aStatus));
128 mStatus = aLoadGroupStatus;
129 // Make sure we remove from the load group before
130 // setting mStatus, as existing tests expect the
131 // status to be successful when we disconnect.
132 if (mLoadGroup) {
133 mLoadGroup->RemoveRequest(this, nullptr, aStatus);
134 mLoadGroup = nullptr;
137 ShutdownListeners(aStatus);
140 nsDocShell* DocumentChannel::GetDocShell() {
141 nsCOMPtr<nsILoadContext> loadContext;
142 NS_QueryNotificationCallbacks(this, loadContext);
143 if (!loadContext) {
144 return nullptr;
146 nsCOMPtr<mozIDOMWindowProxy> domWindow;
147 loadContext->GetAssociatedWindow(getter_AddRefs(domWindow));
148 if (!domWindow) {
149 return nullptr;
151 auto* pDomWindow = nsPIDOMWindowOuter::From(domWindow);
152 nsIDocShell* docshell = pDomWindow->GetDocShell();
153 return nsDocShell::Cast(docshell);
156 static bool URIUsesDocChannel(nsIURI* aURI) {
157 if (SchemeIsJavascript(aURI)) {
158 return false;
161 nsCString spec = aURI->GetSpecOrDefault();
162 return !spec.EqualsLiteral("about:crashcontent");
165 bool DocumentChannel::CanUseDocumentChannel(nsIURI* aURI) {
166 // We want to use DocumentChannel if we're using a supported scheme.
167 return URIUsesDocChannel(aURI);
170 /* static */
171 already_AddRefed<DocumentChannel> DocumentChannel::CreateForDocument(
172 nsDocShellLoadState* aLoadState, class LoadInfo* aLoadInfo,
173 nsLoadFlags aLoadFlags, nsIInterfaceRequestor* aNotificationCallbacks,
174 uint32_t aCacheKey, bool aUriModified, bool aIsXFOError) {
175 RefPtr<DocumentChannel> channel;
176 if (XRE_IsContentProcess()) {
177 channel = new DocumentChannelChild(aLoadState, aLoadInfo, aLoadFlags,
178 aCacheKey, aUriModified, aIsXFOError);
179 } else {
180 channel =
181 new ParentProcessDocumentChannel(aLoadState, aLoadInfo, aLoadFlags,
182 aCacheKey, aUriModified, aIsXFOError);
184 channel->SetNotificationCallbacks(aNotificationCallbacks);
185 return channel.forget();
188 /* static */
189 already_AddRefed<DocumentChannel> DocumentChannel::CreateForObject(
190 nsDocShellLoadState* aLoadState, class LoadInfo* aLoadInfo,
191 nsLoadFlags aLoadFlags, nsIInterfaceRequestor* aNotificationCallbacks) {
192 return CreateForDocument(aLoadState, aLoadInfo, aLoadFlags,
193 aNotificationCallbacks, 0, false, false);
196 NS_IMETHODIMP DocumentChannel::SetCanceledReason(const nsACString& aReason) {
197 return SetCanceledReasonImpl(aReason);
200 NS_IMETHODIMP DocumentChannel::GetCanceledReason(nsACString& aReason) {
201 return GetCanceledReasonImpl(aReason);
204 NS_IMETHODIMP DocumentChannel::CancelWithReason(nsresult aStatus,
205 const nsACString& aReason) {
206 return CancelWithReasonImpl(aStatus, aReason);
209 NS_IMETHODIMP
210 DocumentChannel::Cancel(nsresult aStatusCode) {
211 MOZ_CRASH("If we get here, something is broken");
212 return NS_ERROR_NOT_IMPLEMENTED;
215 NS_IMETHODIMP
216 DocumentChannel::Suspend() {
217 MOZ_CRASH("If we get here, something is broken");
218 return NS_ERROR_NOT_IMPLEMENTED;
221 NS_IMETHODIMP
222 DocumentChannel::Resume() {
223 MOZ_CRASH("If we get here, something is broken");
224 return NS_ERROR_NOT_IMPLEMENTED;
227 //-----------------------------------------------------------------------------
228 // Remainder of nsIRequest/nsIChannel.
229 //-----------------------------------------------------------------------------
231 NS_IMETHODIMP DocumentChannel::GetNotificationCallbacks(
232 nsIInterfaceRequestor** aCallbacks) {
233 nsCOMPtr<nsIInterfaceRequestor> callbacks(mCallbacks);
234 callbacks.forget(aCallbacks);
235 return NS_OK;
238 NS_IMETHODIMP DocumentChannel::SetNotificationCallbacks(
239 nsIInterfaceRequestor* aNotificationCallbacks) {
240 mCallbacks = aNotificationCallbacks;
241 return NS_OK;
244 NS_IMETHODIMP DocumentChannel::GetLoadGroup(nsILoadGroup** aLoadGroup) {
245 nsCOMPtr<nsILoadGroup> loadGroup(mLoadGroup);
246 loadGroup.forget(aLoadGroup);
247 return NS_OK;
250 NS_IMETHODIMP DocumentChannel::SetLoadGroup(nsILoadGroup* aLoadGroup) {
251 mLoadGroup = aLoadGroup;
252 return NS_OK;
255 NS_IMETHODIMP DocumentChannel::GetStatus(nsresult* aStatus) {
256 *aStatus = mStatus;
257 return NS_OK;
260 NS_IMETHODIMP DocumentChannel::GetName(nsACString& aResult) {
261 if (!mURI) {
262 aResult.Truncate();
263 return NS_OK;
265 nsCString spec;
266 nsresult rv = mURI->GetSpec(spec);
267 NS_ENSURE_SUCCESS(rv, rv);
269 aResult.AssignLiteral("documentchannel:");
270 aResult.Append(spec);
271 return NS_OK;
274 NS_IMETHODIMP DocumentChannel::IsPending(bool* aResult) {
275 *aResult = mIsPending;
276 return NS_OK;
279 NS_IMETHODIMP DocumentChannel::GetLoadFlags(nsLoadFlags* aLoadFlags) {
280 *aLoadFlags = mLoadFlags;
281 return NS_OK;
284 NS_IMETHODIMP
285 DocumentChannel::GetTRRMode(nsIRequest::TRRMode* aTRRMode) {
286 return GetTRRModeImpl(aTRRMode);
289 NS_IMETHODIMP
290 DocumentChannel::SetTRRMode(nsIRequest::TRRMode aTRRMode) {
291 return SetTRRModeImpl(aTRRMode);
294 NS_IMETHODIMP DocumentChannel::SetLoadFlags(nsLoadFlags aLoadFlags) {
295 // Setting load flags for TYPE_OBJECT is OK, so long as the channel to parent
296 // isn't opened yet, or we're only setting the `LOAD_DOCUMENT_URI` flag.
297 auto contentPolicy = mLoadInfo->GetExternalContentPolicyType();
298 if (contentPolicy == ExtContentPolicy::TYPE_OBJECT) {
299 if (mWasOpened) {
300 MOZ_DIAGNOSTIC_ASSERT(
301 aLoadFlags == (mLoadFlags | nsIChannel::LOAD_DOCUMENT_URI),
302 "After the channel has been opened, can only set the "
303 "`LOAD_DOCUMENT_URI` flag.");
305 mLoadFlags = aLoadFlags;
306 return NS_OK;
309 MOZ_CRASH_UNSAFE_PRINTF(
310 "DocumentChannel::SetLoadFlags: Don't set flags after creation "
311 "(differing flags %x != %x)",
312 (mLoadFlags ^ aLoadFlags) & mLoadFlags,
313 (mLoadFlags ^ aLoadFlags) & aLoadFlags);
316 NS_IMETHODIMP DocumentChannel::GetOriginalURI(nsIURI** aOriginalURI) {
317 nsCOMPtr<nsIURI> originalURI =
318 mLoadState->OriginalURI() ? mLoadState->OriginalURI() : mLoadState->URI();
319 originalURI.forget(aOriginalURI);
320 return NS_OK;
323 NS_IMETHODIMP DocumentChannel::SetOriginalURI(nsIURI* aOriginalURI) {
324 MOZ_CRASH("If we get here, something is broken");
325 return NS_ERROR_NOT_IMPLEMENTED;
328 NS_IMETHODIMP DocumentChannel::GetURI(nsIURI** aURI) {
329 nsCOMPtr<nsIURI> uri(mURI);
330 uri.forget(aURI);
331 return NS_OK;
334 NS_IMETHODIMP DocumentChannel::GetOwner(nsISupports** aOwner) {
335 nsCOMPtr<nsISupports> owner(mOwner);
336 owner.forget(aOwner);
337 return NS_OK;
340 NS_IMETHODIMP DocumentChannel::SetOwner(nsISupports* aOwner) {
341 mOwner = aOwner;
342 return NS_OK;
345 NS_IMETHODIMP DocumentChannel::GetSecurityInfo(
346 nsITransportSecurityInfo** aSecurityInfo) {
347 *aSecurityInfo = nullptr;
348 return NS_OK;
351 NS_IMETHODIMP DocumentChannel::GetContentType(nsACString& aContentType) {
352 // We may be trying to load HTML object data, and have determined that we're
353 // going to be performing a document load. In that case, fake the "text/html"
354 // content type for nsObjectLoadingContent.
355 if ((mLoadFlags & nsIRequest::LOAD_HTML_OBJECT_DATA) &&
356 (mLoadFlags & nsIChannel::LOAD_DOCUMENT_URI)) {
357 aContentType = TEXT_HTML;
358 return NS_OK;
361 NS_ERROR("If we get here, something is broken");
362 return NS_ERROR_NOT_IMPLEMENTED;
365 NS_IMETHODIMP DocumentChannel::SetContentType(const nsACString& aContentType) {
366 MOZ_CRASH("If we get here, something is broken");
367 return NS_ERROR_NOT_IMPLEMENTED;
370 NS_IMETHODIMP DocumentChannel::GetContentCharset(nsACString& aContentCharset) {
371 MOZ_CRASH("If we get here, something is broken");
372 return NS_ERROR_NOT_IMPLEMENTED;
375 NS_IMETHODIMP DocumentChannel::SetContentCharset(
376 const nsACString& aContentCharset) {
377 MOZ_CRASH("If we get here, something is broken");
378 return NS_ERROR_NOT_IMPLEMENTED;
381 NS_IMETHODIMP DocumentChannel::GetContentLength(int64_t* aContentLength) {
382 MOZ_CRASH("If we get here, something is broken");
383 return NS_ERROR_NOT_IMPLEMENTED;
386 NS_IMETHODIMP DocumentChannel::SetContentLength(int64_t aContentLength) {
387 MOZ_CRASH("If we get here, something is broken");
388 return NS_ERROR_NOT_IMPLEMENTED;
391 NS_IMETHODIMP DocumentChannel::Open(nsIInputStream** aStream) {
392 MOZ_CRASH("If we get here, something is broken");
393 return NS_ERROR_NOT_IMPLEMENTED;
396 NS_IMETHODIMP DocumentChannel::GetContentDisposition(
397 uint32_t* aContentDisposition) {
398 MOZ_CRASH("If we get here, something is broken");
399 return NS_ERROR_NOT_IMPLEMENTED;
402 NS_IMETHODIMP DocumentChannel::SetContentDisposition(
403 uint32_t aContentDisposition) {
404 MOZ_CRASH("If we get here, something is broken");
405 return NS_ERROR_NOT_IMPLEMENTED;
408 NS_IMETHODIMP DocumentChannel::GetContentDispositionFilename(
409 nsAString& aContentDispositionFilename) {
410 MOZ_CRASH("If we get here, something will be broken");
411 return NS_ERROR_NOT_IMPLEMENTED;
414 NS_IMETHODIMP DocumentChannel::SetContentDispositionFilename(
415 const nsAString& aContentDispositionFilename) {
416 MOZ_CRASH("If we get here, something will be broken");
417 return NS_ERROR_NOT_IMPLEMENTED;
420 NS_IMETHODIMP DocumentChannel::GetContentDispositionHeader(
421 nsACString& aContentDispositionHeader) {
422 MOZ_CRASH("If we get here, something is broken");
423 return NS_ERROR_NOT_IMPLEMENTED;
426 NS_IMETHODIMP DocumentChannel::GetLoadInfo(nsILoadInfo** aLoadInfo) {
427 nsCOMPtr<nsILoadInfo> loadInfo(mLoadInfo);
428 loadInfo.forget(aLoadInfo);
429 return NS_OK;
432 NS_IMETHODIMP DocumentChannel::SetLoadInfo(nsILoadInfo* aLoadInfo) {
433 MOZ_CRASH("If we get here, something is broken");
434 return NS_ERROR_NOT_IMPLEMENTED;
437 NS_IMETHODIMP DocumentChannel::GetIsDocument(bool* aIsDocument) {
438 return NS_GetIsDocumentChannel(this, aIsDocument);
441 NS_IMETHODIMP DocumentChannel::GetCanceled(bool* aCanceled) {
442 *aCanceled = mCanceled;
443 return NS_OK;
446 //-----------------------------------------------------------------------------
447 // nsIIdentChannel
448 //-----------------------------------------------------------------------------
450 NS_IMETHODIMP
451 DocumentChannel::GetChannelId(uint64_t* aChannelId) {
452 *aChannelId = mChannelId;
453 return NS_OK;
456 NS_IMETHODIMP
457 DocumentChannel::SetChannelId(uint64_t aChannelId) {
458 mChannelId = aChannelId;
459 return NS_OK;
462 //-----------------------------------------------------------------------------
463 // Helpers
464 //-----------------------------------------------------------------------------
466 uint64_t InnerWindowIDForExtantDoc(nsDocShell* docShell) {
467 if (!docShell) {
468 return 0;
471 Document* doc = docShell->GetExtantDocument();
472 if (!doc) {
473 return 0;
476 return doc->InnerWindowID();
479 } // namespace net
480 } // namespace mozilla
482 #undef LOG