netwerk/protocol/http/HttpChannelChild.cpp

Thu, 15 Jan 2015 21:03:48 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 15 Jan 2015 21:03:48 +0100
branch
TOR_BUG_9701
changeset 11
deefc01c0e14
permissions
-rw-r--r--

Integrate friendly tips from Tor colleagues to make (or not) 4.5 alpha 3;
This includes removal of overloaded (but unused) methods, and addition of
a overlooked call to DataStruct::SetData(nsISupports, uint32_t, bool.)

michael@0 1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
michael@0 2 /* vim: set sw=2 ts=8 et tw=80 : */
michael@0 3
michael@0 4 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 5 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 6 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 7
michael@0 8 // HttpLog.h should generally be included first
michael@0 9 #include "HttpLog.h"
michael@0 10
michael@0 11 #include "nsHttp.h"
michael@0 12 #include "mozilla/unused.h"
michael@0 13 #include "mozilla/dom/ContentChild.h"
michael@0 14 #include "mozilla/dom/TabChild.h"
michael@0 15 #include "mozilla/dom/FileDescriptorSetChild.h"
michael@0 16 #include "mozilla/net/NeckoChild.h"
michael@0 17 #include "mozilla/net/HttpChannelChild.h"
michael@0 18
michael@0 19 #include "nsStringStream.h"
michael@0 20 #include "nsHttpHandler.h"
michael@0 21 #include "nsNetUtil.h"
michael@0 22 #include "nsSerializationHelper.h"
michael@0 23 #include "mozilla/Attributes.h"
michael@0 24 #include "mozilla/ipc/InputStreamUtils.h"
michael@0 25 #include "mozilla/ipc/URIUtils.h"
michael@0 26 #include "mozilla/net/ChannelDiverterChild.h"
michael@0 27 #include "mozilla/net/DNS.h"
michael@0 28 #include "SerializedLoadContext.h"
michael@0 29
michael@0 30 using namespace mozilla::dom;
michael@0 31 using namespace mozilla::ipc;
michael@0 32
michael@0 33 namespace mozilla {
michael@0 34 namespace net {
michael@0 35
michael@0 36 //-----------------------------------------------------------------------------
michael@0 37 // HttpChannelChild
michael@0 38 //-----------------------------------------------------------------------------
michael@0 39
michael@0 40 HttpChannelChild::HttpChannelChild()
michael@0 41 : HttpAsyncAborter<HttpChannelChild>(MOZ_THIS_IN_INITIALIZER_LIST())
michael@0 42 , mIsFromCache(false)
michael@0 43 , mCacheEntryAvailable(false)
michael@0 44 , mCacheExpirationTime(nsICache::NO_EXPIRATION_TIME)
michael@0 45 , mSendResumeAt(false)
michael@0 46 , mIPCOpen(false)
michael@0 47 , mKeptAlive(false)
michael@0 48 , mDivertingToParent(false)
michael@0 49 , mFlushedForDiversion(false)
michael@0 50 , mSuspendSent(false)
michael@0 51 {
michael@0 52 LOG(("Creating HttpChannelChild @%x\n", this));
michael@0 53
michael@0 54 mChannelCreationTime = PR_Now();
michael@0 55 mChannelCreationTimestamp = TimeStamp::Now();
michael@0 56 mAsyncOpenTime = TimeStamp::Now();
michael@0 57 mEventQ = new ChannelEventQueue(static_cast<nsIHttpChannel*>(this));
michael@0 58 }
michael@0 59
michael@0 60 HttpChannelChild::~HttpChannelChild()
michael@0 61 {
michael@0 62 LOG(("Destroying HttpChannelChild @%x\n", this));
michael@0 63 }
michael@0 64
michael@0 65 //-----------------------------------------------------------------------------
michael@0 66 // HttpChannelChild::nsISupports
michael@0 67 //-----------------------------------------------------------------------------
michael@0 68
michael@0 69 // Override nsHashPropertyBag's AddRef: we don't need thread-safe refcnt
michael@0 70 NS_IMPL_ADDREF(HttpChannelChild)
michael@0 71
michael@0 72 NS_IMETHODIMP_(MozExternalRefCountType) HttpChannelChild::Release()
michael@0 73 {
michael@0 74 NS_PRECONDITION(0 != mRefCnt, "dup release");
michael@0 75 NS_ASSERT_OWNINGTHREAD(HttpChannelChild);
michael@0 76 --mRefCnt;
michael@0 77 NS_LOG_RELEASE(this, mRefCnt, "HttpChannelChild");
michael@0 78
michael@0 79 // Normally we Send_delete in OnStopRequest, but when we need to retain the
michael@0 80 // remote channel for security info IPDL itself holds 1 reference, so we
michael@0 81 // Send_delete when refCnt==1. But if !mIPCOpen, then there's nobody to send
michael@0 82 // to, so we fall through.
michael@0 83 if (mKeptAlive && mRefCnt == 1 && mIPCOpen) {
michael@0 84 mKeptAlive = false;
michael@0 85 // Send_delete calls NeckoChild::DeallocPHttpChannel, which will release
michael@0 86 // again to refcount==0
michael@0 87 PHttpChannelChild::Send__delete__(this);
michael@0 88 return 0;
michael@0 89 }
michael@0 90
michael@0 91 if (mRefCnt == 0) {
michael@0 92 mRefCnt = 1; /* stabilize */
michael@0 93 delete this;
michael@0 94 return 0;
michael@0 95 }
michael@0 96 return mRefCnt;
michael@0 97 }
michael@0 98
michael@0 99 NS_INTERFACE_MAP_BEGIN(HttpChannelChild)
michael@0 100 NS_INTERFACE_MAP_ENTRY(nsIRequest)
michael@0 101 NS_INTERFACE_MAP_ENTRY(nsIChannel)
michael@0 102 NS_INTERFACE_MAP_ENTRY(nsIHttpChannel)
michael@0 103 NS_INTERFACE_MAP_ENTRY(nsIHttpChannelInternal)
michael@0 104 NS_INTERFACE_MAP_ENTRY(nsICacheInfoChannel)
michael@0 105 NS_INTERFACE_MAP_ENTRY(nsIResumableChannel)
michael@0 106 NS_INTERFACE_MAP_ENTRY(nsISupportsPriority)
michael@0 107 NS_INTERFACE_MAP_ENTRY(nsIProxiedChannel)
michael@0 108 NS_INTERFACE_MAP_ENTRY(nsITraceableChannel)
michael@0 109 NS_INTERFACE_MAP_ENTRY(nsIApplicationCacheContainer)
michael@0 110 NS_INTERFACE_MAP_ENTRY(nsIApplicationCacheChannel)
michael@0 111 NS_INTERFACE_MAP_ENTRY(nsIAsyncVerifyRedirectCallback)
michael@0 112 NS_INTERFACE_MAP_ENTRY(nsIChildChannel)
michael@0 113 NS_INTERFACE_MAP_ENTRY(nsIHttpChannelChild)
michael@0 114 NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIAssociatedContentSecurity, GetAssociatedContentSecurity())
michael@0 115 NS_INTERFACE_MAP_ENTRY(nsIDivertableChannel)
michael@0 116 NS_INTERFACE_MAP_END_INHERITING(HttpBaseChannel)
michael@0 117
michael@0 118 //-----------------------------------------------------------------------------
michael@0 119 // HttpChannelChild::PHttpChannelChild
michael@0 120 //-----------------------------------------------------------------------------
michael@0 121
michael@0 122 void
michael@0 123 HttpChannelChild::AddIPDLReference()
michael@0 124 {
michael@0 125 MOZ_ASSERT(!mIPCOpen, "Attempt to retain more than one IPDL reference");
michael@0 126 mIPCOpen = true;
michael@0 127 AddRef();
michael@0 128 }
michael@0 129
michael@0 130 void
michael@0 131 HttpChannelChild::ReleaseIPDLReference()
michael@0 132 {
michael@0 133 MOZ_ASSERT(mIPCOpen, "Attempt to release nonexistent IPDL reference");
michael@0 134 mIPCOpen = false;
michael@0 135 Release();
michael@0 136 }
michael@0 137
michael@0 138 class AssociateApplicationCacheEvent : public ChannelEvent
michael@0 139 {
michael@0 140 public:
michael@0 141 AssociateApplicationCacheEvent(HttpChannelChild* child,
michael@0 142 const nsCString &groupID,
michael@0 143 const nsCString &clientID)
michael@0 144 : mChild(child)
michael@0 145 , groupID(groupID)
michael@0 146 , clientID(clientID) {}
michael@0 147
michael@0 148 void Run() { mChild->AssociateApplicationCache(groupID, clientID); }
michael@0 149 private:
michael@0 150 HttpChannelChild* mChild;
michael@0 151 nsCString groupID;
michael@0 152 nsCString clientID;
michael@0 153 };
michael@0 154
michael@0 155 bool
michael@0 156 HttpChannelChild::RecvAssociateApplicationCache(const nsCString &groupID,
michael@0 157 const nsCString &clientID)
michael@0 158 {
michael@0 159 if (mEventQ->ShouldEnqueue()) {
michael@0 160 mEventQ->Enqueue(new AssociateApplicationCacheEvent(this, groupID, clientID));
michael@0 161 } else {
michael@0 162 AssociateApplicationCache(groupID, clientID);
michael@0 163 }
michael@0 164 return true;
michael@0 165 }
michael@0 166
michael@0 167 void
michael@0 168 HttpChannelChild::AssociateApplicationCache(const nsCString &groupID,
michael@0 169 const nsCString &clientID)
michael@0 170 {
michael@0 171 nsresult rv;
michael@0 172 mApplicationCache = do_CreateInstance(NS_APPLICATIONCACHE_CONTRACTID, &rv);
michael@0 173 if (NS_FAILED(rv))
michael@0 174 return;
michael@0 175
michael@0 176 mLoadedFromApplicationCache = true;
michael@0 177 mApplicationCache->InitAsHandle(groupID, clientID);
michael@0 178 }
michael@0 179
michael@0 180 class StartRequestEvent : public ChannelEvent
michael@0 181 {
michael@0 182 public:
michael@0 183 StartRequestEvent(HttpChannelChild* child,
michael@0 184 const nsresult& channelStatus,
michael@0 185 const nsHttpResponseHead& responseHead,
michael@0 186 const bool& useResponseHead,
michael@0 187 const nsHttpHeaderArray& requestHeaders,
michael@0 188 const bool& isFromCache,
michael@0 189 const bool& cacheEntryAvailable,
michael@0 190 const uint32_t& cacheExpirationTime,
michael@0 191 const nsCString& cachedCharset,
michael@0 192 const nsCString& securityInfoSerialization,
michael@0 193 const NetAddr& selfAddr,
michael@0 194 const NetAddr& peerAddr)
michael@0 195 : mChild(child)
michael@0 196 , mChannelStatus(channelStatus)
michael@0 197 , mResponseHead(responseHead)
michael@0 198 , mRequestHeaders(requestHeaders)
michael@0 199 , mUseResponseHead(useResponseHead)
michael@0 200 , mIsFromCache(isFromCache)
michael@0 201 , mCacheEntryAvailable(cacheEntryAvailable)
michael@0 202 , mCacheExpirationTime(cacheExpirationTime)
michael@0 203 , mCachedCharset(cachedCharset)
michael@0 204 , mSecurityInfoSerialization(securityInfoSerialization)
michael@0 205 , mSelfAddr(selfAddr)
michael@0 206 , mPeerAddr(peerAddr)
michael@0 207 {}
michael@0 208
michael@0 209 void Run()
michael@0 210 {
michael@0 211 mChild->OnStartRequest(mChannelStatus, mResponseHead, mUseResponseHead,
michael@0 212 mRequestHeaders, mIsFromCache, mCacheEntryAvailable,
michael@0 213 mCacheExpirationTime, mCachedCharset,
michael@0 214 mSecurityInfoSerialization, mSelfAddr, mPeerAddr);
michael@0 215 }
michael@0 216 private:
michael@0 217 HttpChannelChild* mChild;
michael@0 218 nsresult mChannelStatus;
michael@0 219 nsHttpResponseHead mResponseHead;
michael@0 220 nsHttpHeaderArray mRequestHeaders;
michael@0 221 bool mUseResponseHead;
michael@0 222 bool mIsFromCache;
michael@0 223 bool mCacheEntryAvailable;
michael@0 224 uint32_t mCacheExpirationTime;
michael@0 225 nsCString mCachedCharset;
michael@0 226 nsCString mSecurityInfoSerialization;
michael@0 227 NetAddr mSelfAddr;
michael@0 228 NetAddr mPeerAddr;
michael@0 229 };
michael@0 230
michael@0 231 bool
michael@0 232 HttpChannelChild::RecvOnStartRequest(const nsresult& channelStatus,
michael@0 233 const nsHttpResponseHead& responseHead,
michael@0 234 const bool& useResponseHead,
michael@0 235 const nsHttpHeaderArray& requestHeaders,
michael@0 236 const bool& isFromCache,
michael@0 237 const bool& cacheEntryAvailable,
michael@0 238 const uint32_t& cacheExpirationTime,
michael@0 239 const nsCString& cachedCharset,
michael@0 240 const nsCString& securityInfoSerialization,
michael@0 241 const NetAddr& selfAddr,
michael@0 242 const NetAddr& peerAddr,
michael@0 243 const int16_t& redirectCount)
michael@0 244 {
michael@0 245 // mFlushedForDiversion and mDivertingToParent should NEVER be set at this
michael@0 246 // stage, as they are set in the listener's OnStartRequest.
michael@0 247 MOZ_RELEASE_ASSERT(!mFlushedForDiversion,
michael@0 248 "mFlushedForDiversion should be unset before OnStartRequest!");
michael@0 249 MOZ_RELEASE_ASSERT(!mDivertingToParent,
michael@0 250 "mDivertingToParent should be unset before OnStartRequest!");
michael@0 251
michael@0 252
michael@0 253 mRedirectCount = redirectCount;
michael@0 254
michael@0 255 if (mEventQ->ShouldEnqueue()) {
michael@0 256 mEventQ->Enqueue(new StartRequestEvent(this, channelStatus, responseHead,
michael@0 257 useResponseHead, requestHeaders,
michael@0 258 isFromCache, cacheEntryAvailable,
michael@0 259 cacheExpirationTime, cachedCharset,
michael@0 260 securityInfoSerialization, selfAddr,
michael@0 261 peerAddr));
michael@0 262 } else {
michael@0 263 OnStartRequest(channelStatus, responseHead, useResponseHead, requestHeaders,
michael@0 264 isFromCache, cacheEntryAvailable, cacheExpirationTime,
michael@0 265 cachedCharset, securityInfoSerialization, selfAddr,
michael@0 266 peerAddr);
michael@0 267 }
michael@0 268 return true;
michael@0 269 }
michael@0 270
michael@0 271 void
michael@0 272 HttpChannelChild::OnStartRequest(const nsresult& channelStatus,
michael@0 273 const nsHttpResponseHead& responseHead,
michael@0 274 const bool& useResponseHead,
michael@0 275 const nsHttpHeaderArray& requestHeaders,
michael@0 276 const bool& isFromCache,
michael@0 277 const bool& cacheEntryAvailable,
michael@0 278 const uint32_t& cacheExpirationTime,
michael@0 279 const nsCString& cachedCharset,
michael@0 280 const nsCString& securityInfoSerialization,
michael@0 281 const NetAddr& selfAddr,
michael@0 282 const NetAddr& peerAddr)
michael@0 283 {
michael@0 284 LOG(("HttpChannelChild::RecvOnStartRequest [this=%p]\n", this));
michael@0 285
michael@0 286 // mFlushedForDiversion and mDivertingToParent should NEVER be set at this
michael@0 287 // stage, as they are set in the listener's OnStartRequest.
michael@0 288 MOZ_RELEASE_ASSERT(!mFlushedForDiversion,
michael@0 289 "mFlushedForDiversion should be unset before OnStartRequest!");
michael@0 290 MOZ_RELEASE_ASSERT(!mDivertingToParent,
michael@0 291 "mDivertingToParent should be unset before OnStartRequest!");
michael@0 292
michael@0 293 if (!mCanceled && NS_SUCCEEDED(mStatus)) {
michael@0 294 mStatus = channelStatus;
michael@0 295 }
michael@0 296
michael@0 297 if (useResponseHead && !mCanceled)
michael@0 298 mResponseHead = new nsHttpResponseHead(responseHead);
michael@0 299
michael@0 300 if (!securityInfoSerialization.IsEmpty()) {
michael@0 301 NS_DeserializeObject(securityInfoSerialization,
michael@0 302 getter_AddRefs(mSecurityInfo));
michael@0 303 }
michael@0 304
michael@0 305 mIsFromCache = isFromCache;
michael@0 306 mCacheEntryAvailable = cacheEntryAvailable;
michael@0 307 mCacheExpirationTime = cacheExpirationTime;
michael@0 308 mCachedCharset = cachedCharset;
michael@0 309
michael@0 310 AutoEventEnqueuer ensureSerialDispatch(mEventQ);
michael@0 311
michael@0 312 // replace our request headers with what actually got sent in the parent
michael@0 313 mRequestHead.Headers() = requestHeaders;
michael@0 314
michael@0 315 // Note: this is where we would notify "http-on-examine-response" observers.
michael@0 316 // We have deliberately disabled this for child processes (see bug 806753)
michael@0 317 //
michael@0 318 // gHttpHandler->OnExamineResponse(this);
michael@0 319
michael@0 320 mTracingEnabled = false;
michael@0 321
michael@0 322 nsresult rv = mListener->OnStartRequest(this, mListenerContext);
michael@0 323 if (NS_FAILED(rv)) {
michael@0 324 Cancel(rv);
michael@0 325 return;
michael@0 326 }
michael@0 327
michael@0 328 if (mDivertingToParent) {
michael@0 329 mListener = nullptr;
michael@0 330 mListenerContext = nullptr;
michael@0 331 if (mLoadGroup) {
michael@0 332 mLoadGroup->RemoveRequest(this, nullptr, mStatus);
michael@0 333 }
michael@0 334 }
michael@0 335
michael@0 336 if (mResponseHead)
michael@0 337 SetCookie(mResponseHead->PeekHeader(nsHttp::Set_Cookie));
michael@0 338
michael@0 339 rv = ApplyContentConversions();
michael@0 340 if (NS_FAILED(rv))
michael@0 341 Cancel(rv);
michael@0 342
michael@0 343 mSelfAddr = selfAddr;
michael@0 344 mPeerAddr = peerAddr;
michael@0 345 }
michael@0 346
michael@0 347 class TransportAndDataEvent : public ChannelEvent
michael@0 348 {
michael@0 349 public:
michael@0 350 TransportAndDataEvent(HttpChannelChild* child,
michael@0 351 const nsresult& channelStatus,
michael@0 352 const nsresult& transportStatus,
michael@0 353 const uint64_t& progress,
michael@0 354 const uint64_t& progressMax,
michael@0 355 const nsCString& data,
michael@0 356 const uint64_t& offset,
michael@0 357 const uint32_t& count)
michael@0 358 : mChild(child)
michael@0 359 , mChannelStatus(channelStatus)
michael@0 360 , mTransportStatus(transportStatus)
michael@0 361 , mProgress(progress)
michael@0 362 , mProgressMax(progressMax)
michael@0 363 , mData(data)
michael@0 364 , mOffset(offset)
michael@0 365 , mCount(count) {}
michael@0 366
michael@0 367 void Run()
michael@0 368 {
michael@0 369 mChild->OnTransportAndData(mChannelStatus, mTransportStatus, mProgress,
michael@0 370 mProgressMax, mData, mOffset, mCount);
michael@0 371 }
michael@0 372 private:
michael@0 373 HttpChannelChild* mChild;
michael@0 374 nsresult mChannelStatus;
michael@0 375 nsresult mTransportStatus;
michael@0 376 uint64_t mProgress;
michael@0 377 uint64_t mProgressMax;
michael@0 378 nsCString mData;
michael@0 379 uint64_t mOffset;
michael@0 380 uint32_t mCount;
michael@0 381 };
michael@0 382
michael@0 383 bool
michael@0 384 HttpChannelChild::RecvOnTransportAndData(const nsresult& channelStatus,
michael@0 385 const nsresult& transportStatus,
michael@0 386 const uint64_t& progress,
michael@0 387 const uint64_t& progressMax,
michael@0 388 const nsCString& data,
michael@0 389 const uint64_t& offset,
michael@0 390 const uint32_t& count)
michael@0 391 {
michael@0 392 MOZ_RELEASE_ASSERT(!mFlushedForDiversion,
michael@0 393 "Should not be receiving any more callbacks from parent!");
michael@0 394
michael@0 395 if (mEventQ->ShouldEnqueue()) {
michael@0 396 mEventQ->Enqueue(new TransportAndDataEvent(this, channelStatus,
michael@0 397 transportStatus, progress,
michael@0 398 progressMax, data, offset,
michael@0 399 count));
michael@0 400 } else {
michael@0 401 MOZ_RELEASE_ASSERT(!mDivertingToParent,
michael@0 402 "ShouldEnqueue when diverting to parent!");
michael@0 403
michael@0 404 OnTransportAndData(channelStatus, transportStatus, progress, progressMax,
michael@0 405 data, offset, count);
michael@0 406 }
michael@0 407 return true;
michael@0 408 }
michael@0 409
michael@0 410 void
michael@0 411 HttpChannelChild::OnTransportAndData(const nsresult& channelStatus,
michael@0 412 const nsresult& transportStatus,
michael@0 413 const uint64_t progress,
michael@0 414 const uint64_t& progressMax,
michael@0 415 const nsCString& data,
michael@0 416 const uint64_t& offset,
michael@0 417 const uint32_t& count)
michael@0 418 {
michael@0 419 LOG(("HttpChannelChild::OnTransportAndData [this=%p]\n", this));
michael@0 420
michael@0 421 if (!mCanceled && NS_SUCCEEDED(mStatus)) {
michael@0 422 mStatus = channelStatus;
michael@0 423 }
michael@0 424
michael@0 425 // For diversion to parent, just SendDivertOnDataAvailable.
michael@0 426 if (mDivertingToParent) {
michael@0 427 MOZ_RELEASE_ASSERT(!mFlushedForDiversion,
michael@0 428 "Should not be processing any more callbacks from parent!");
michael@0 429
michael@0 430 SendDivertOnDataAvailable(data, offset, count);
michael@0 431 return;
michael@0 432 }
michael@0 433
michael@0 434 if (mCanceled)
michael@0 435 return;
michael@0 436
michael@0 437 // cache the progress sink so we don't have to query for it each time.
michael@0 438 if (!mProgressSink)
michael@0 439 GetCallback(mProgressSink);
michael@0 440
michael@0 441 // Hold queue lock throughout all three calls, else we might process a later
michael@0 442 // necko msg in between them.
michael@0 443 AutoEventEnqueuer ensureSerialDispatch(mEventQ);
michael@0 444
michael@0 445 // block status/progress after Cancel or OnStopRequest has been called,
michael@0 446 // or if channel has LOAD_BACKGROUND set.
michael@0 447 // - JDUELL: may not need mStatus/mIsPending checks, given this is always called
michael@0 448 // during OnDataAvailable, and we've already checked mCanceled. Code
michael@0 449 // dupe'd from nsHttpChannel
michael@0 450 if (mProgressSink && NS_SUCCEEDED(mStatus) && mIsPending &&
michael@0 451 !(mLoadFlags & LOAD_BACKGROUND))
michael@0 452 {
michael@0 453 // OnStatus
michael@0 454 //
michael@0 455 MOZ_ASSERT(transportStatus == NS_NET_STATUS_RECEIVING_FROM ||
michael@0 456 transportStatus == NS_NET_STATUS_READING);
michael@0 457
michael@0 458 nsAutoCString host;
michael@0 459 mURI->GetHost(host);
michael@0 460 mProgressSink->OnStatus(this, nullptr, transportStatus,
michael@0 461 NS_ConvertUTF8toUTF16(host).get());
michael@0 462 // OnProgress
michael@0 463 //
michael@0 464 if (progress > 0) {
michael@0 465 MOZ_ASSERT(progress <= progressMax, "unexpected progress values");
michael@0 466 mProgressSink->OnProgress(this, nullptr, progress, progressMax);
michael@0 467 }
michael@0 468 }
michael@0 469
michael@0 470 // OnDataAvailable
michael@0 471 //
michael@0 472 // NOTE: the OnDataAvailable contract requires the client to read all the data
michael@0 473 // in the inputstream. This code relies on that ('data' will go away after
michael@0 474 // this function). Apparently the previous, non-e10s behavior was to actually
michael@0 475 // support only reading part of the data, allowing later calls to read the
michael@0 476 // rest.
michael@0 477 nsCOMPtr<nsIInputStream> stringStream;
michael@0 478 nsresult rv = NS_NewByteInputStream(getter_AddRefs(stringStream), data.get(),
michael@0 479 count, NS_ASSIGNMENT_DEPEND);
michael@0 480 if (NS_FAILED(rv)) {
michael@0 481 Cancel(rv);
michael@0 482 return;
michael@0 483 }
michael@0 484
michael@0 485 rv = mListener->OnDataAvailable(this, mListenerContext,
michael@0 486 stringStream, offset, count);
michael@0 487 stringStream->Close();
michael@0 488 if (NS_FAILED(rv)) {
michael@0 489 Cancel(rv);
michael@0 490 }
michael@0 491 }
michael@0 492
michael@0 493 class StopRequestEvent : public ChannelEvent
michael@0 494 {
michael@0 495 public:
michael@0 496 StopRequestEvent(HttpChannelChild* child,
michael@0 497 const nsresult& channelStatus)
michael@0 498 : mChild(child)
michael@0 499 , mChannelStatus(channelStatus) {}
michael@0 500
michael@0 501 void Run() { mChild->OnStopRequest(mChannelStatus); }
michael@0 502 private:
michael@0 503 HttpChannelChild* mChild;
michael@0 504 nsresult mChannelStatus;
michael@0 505 };
michael@0 506
michael@0 507 bool
michael@0 508 HttpChannelChild::RecvOnStopRequest(const nsresult& channelStatus)
michael@0 509 {
michael@0 510 MOZ_RELEASE_ASSERT(!mFlushedForDiversion,
michael@0 511 "Should not be receiving any more callbacks from parent!");
michael@0 512
michael@0 513 if (mEventQ->ShouldEnqueue()) {
michael@0 514 mEventQ->Enqueue(new StopRequestEvent(this, channelStatus));
michael@0 515 } else {
michael@0 516 MOZ_ASSERT(!mDivertingToParent, "ShouldEnqueue when diverting to parent!");
michael@0 517
michael@0 518 OnStopRequest(channelStatus);
michael@0 519 }
michael@0 520 return true;
michael@0 521 }
michael@0 522
michael@0 523 void
michael@0 524 HttpChannelChild::OnStopRequest(const nsresult& channelStatus)
michael@0 525 {
michael@0 526 LOG(("HttpChannelChild::OnStopRequest [this=%p status=%x]\n",
michael@0 527 this, channelStatus));
michael@0 528
michael@0 529 if (mDivertingToParent) {
michael@0 530 MOZ_RELEASE_ASSERT(!mFlushedForDiversion,
michael@0 531 "Should not be processing any more callbacks from parent!");
michael@0 532
michael@0 533 SendDivertOnStopRequest(channelStatus);
michael@0 534 return;
michael@0 535 }
michael@0 536
michael@0 537 mIsPending = false;
michael@0 538
michael@0 539 if (!mCanceled && NS_SUCCEEDED(mStatus)) {
michael@0 540 mStatus = channelStatus;
michael@0 541 }
michael@0 542
michael@0 543 { // We must flush the queue before we Send__delete__
michael@0 544 // (although we really shouldn't receive any msgs after OnStop),
michael@0 545 // so make sure this goes out of scope before then.
michael@0 546 AutoEventEnqueuer ensureSerialDispatch(mEventQ);
michael@0 547
michael@0 548 mListener->OnStopRequest(this, mListenerContext, mStatus);
michael@0 549
michael@0 550 mListener = 0;
michael@0 551 mListenerContext = 0;
michael@0 552 mCacheEntryAvailable = false;
michael@0 553 if (mLoadGroup)
michael@0 554 mLoadGroup->RemoveRequest(this, nullptr, mStatus);
michael@0 555 }
michael@0 556
michael@0 557 if (mLoadFlags & LOAD_DOCUMENT_URI) {
michael@0 558 // Keep IPDL channel open, but only for updating security info.
michael@0 559 mKeptAlive = true;
michael@0 560 SendDocumentChannelCleanup();
michael@0 561 } else {
michael@0 562 // This calls NeckoChild::DeallocPHttpChannelChild(), which deletes |this| if IPDL
michael@0 563 // holds the last reference. Don't rely on |this| existing after here.
michael@0 564 PHttpChannelChild::Send__delete__(this);
michael@0 565 }
michael@0 566 }
michael@0 567
michael@0 568 class ProgressEvent : public ChannelEvent
michael@0 569 {
michael@0 570 public:
michael@0 571 ProgressEvent(HttpChannelChild* child,
michael@0 572 const uint64_t& progress,
michael@0 573 const uint64_t& progressMax)
michael@0 574 : mChild(child)
michael@0 575 , mProgress(progress)
michael@0 576 , mProgressMax(progressMax) {}
michael@0 577
michael@0 578 void Run() { mChild->OnProgress(mProgress, mProgressMax); }
michael@0 579 private:
michael@0 580 HttpChannelChild* mChild;
michael@0 581 uint64_t mProgress, mProgressMax;
michael@0 582 };
michael@0 583
michael@0 584 bool
michael@0 585 HttpChannelChild::RecvOnProgress(const uint64_t& progress,
michael@0 586 const uint64_t& progressMax)
michael@0 587 {
michael@0 588 if (mEventQ->ShouldEnqueue()) {
michael@0 589 mEventQ->Enqueue(new ProgressEvent(this, progress, progressMax));
michael@0 590 } else {
michael@0 591 OnProgress(progress, progressMax);
michael@0 592 }
michael@0 593 return true;
michael@0 594 }
michael@0 595
michael@0 596 void
michael@0 597 HttpChannelChild::OnProgress(const uint64_t& progress,
michael@0 598 const uint64_t& progressMax)
michael@0 599 {
michael@0 600 LOG(("HttpChannelChild::OnProgress [this=%p progress=%llu/%llu]\n",
michael@0 601 this, progress, progressMax));
michael@0 602
michael@0 603 if (mCanceled)
michael@0 604 return;
michael@0 605
michael@0 606 // cache the progress sink so we don't have to query for it each time.
michael@0 607 if (!mProgressSink)
michael@0 608 GetCallback(mProgressSink);
michael@0 609
michael@0 610 AutoEventEnqueuer ensureSerialDispatch(mEventQ);
michael@0 611
michael@0 612 // block socket status event after Cancel or OnStopRequest has been called,
michael@0 613 // or if channel has LOAD_BACKGROUND set
michael@0 614 if (mProgressSink && NS_SUCCEEDED(mStatus) && mIsPending &&
michael@0 615 !(mLoadFlags & LOAD_BACKGROUND))
michael@0 616 {
michael@0 617 if (progress > 0) {
michael@0 618 MOZ_ASSERT(progress <= progressMax, "unexpected progress values");
michael@0 619 mProgressSink->OnProgress(this, nullptr, progress, progressMax);
michael@0 620 }
michael@0 621 }
michael@0 622 }
michael@0 623
michael@0 624 class StatusEvent : public ChannelEvent
michael@0 625 {
michael@0 626 public:
michael@0 627 StatusEvent(HttpChannelChild* child,
michael@0 628 const nsresult& status)
michael@0 629 : mChild(child)
michael@0 630 , mStatus(status) {}
michael@0 631
michael@0 632 void Run() { mChild->OnStatus(mStatus); }
michael@0 633 private:
michael@0 634 HttpChannelChild* mChild;
michael@0 635 nsresult mStatus;
michael@0 636 };
michael@0 637
michael@0 638 bool
michael@0 639 HttpChannelChild::RecvOnStatus(const nsresult& status)
michael@0 640 {
michael@0 641 if (mEventQ->ShouldEnqueue()) {
michael@0 642 mEventQ->Enqueue(new StatusEvent(this, status));
michael@0 643 } else {
michael@0 644 OnStatus(status);
michael@0 645 }
michael@0 646 return true;
michael@0 647 }
michael@0 648
michael@0 649 void
michael@0 650 HttpChannelChild::OnStatus(const nsresult& status)
michael@0 651 {
michael@0 652 LOG(("HttpChannelChild::OnStatus [this=%p status=%x]\n", this, status));
michael@0 653
michael@0 654 if (mCanceled)
michael@0 655 return;
michael@0 656
michael@0 657 // cache the progress sink so we don't have to query for it each time.
michael@0 658 if (!mProgressSink)
michael@0 659 GetCallback(mProgressSink);
michael@0 660
michael@0 661 AutoEventEnqueuer ensureSerialDispatch(mEventQ);
michael@0 662
michael@0 663 // block socket status event after Cancel or OnStopRequest has been called,
michael@0 664 // or if channel has LOAD_BACKGROUND set
michael@0 665 if (mProgressSink && NS_SUCCEEDED(mStatus) && mIsPending &&
michael@0 666 !(mLoadFlags & LOAD_BACKGROUND))
michael@0 667 {
michael@0 668 nsAutoCString host;
michael@0 669 mURI->GetHost(host);
michael@0 670 mProgressSink->OnStatus(this, nullptr, status,
michael@0 671 NS_ConvertUTF8toUTF16(host).get());
michael@0 672 }
michael@0 673 }
michael@0 674
michael@0 675 class FailedAsyncOpenEvent : public ChannelEvent
michael@0 676 {
michael@0 677 public:
michael@0 678 FailedAsyncOpenEvent(HttpChannelChild* child, const nsresult& status)
michael@0 679 : mChild(child)
michael@0 680 , mStatus(status) {}
michael@0 681
michael@0 682 void Run() { mChild->FailedAsyncOpen(mStatus); }
michael@0 683 private:
michael@0 684 HttpChannelChild* mChild;
michael@0 685 nsresult mStatus;
michael@0 686 };
michael@0 687
michael@0 688 bool
michael@0 689 HttpChannelChild::RecvFailedAsyncOpen(const nsresult& status)
michael@0 690 {
michael@0 691 if (mEventQ->ShouldEnqueue()) {
michael@0 692 mEventQ->Enqueue(new FailedAsyncOpenEvent(this, status));
michael@0 693 } else {
michael@0 694 FailedAsyncOpen(status);
michael@0 695 }
michael@0 696 return true;
michael@0 697 }
michael@0 698
michael@0 699 // We need to have an implementation of this function just so that we can keep
michael@0 700 // all references to mCallOnResume of type HttpChannelChild: it's not OK in C++
michael@0 701 // to set a member function ptr to a base class function.
michael@0 702 void
michael@0 703 HttpChannelChild::HandleAsyncAbort()
michael@0 704 {
michael@0 705 HttpAsyncAborter<HttpChannelChild>::HandleAsyncAbort();
michael@0 706 }
michael@0 707
michael@0 708 void
michael@0 709 HttpChannelChild::FailedAsyncOpen(const nsresult& status)
michael@0 710 {
michael@0 711 LOG(("HttpChannelChild::FailedAsyncOpen [this=%p status=%x]\n", this, status));
michael@0 712
michael@0 713 mStatus = status;
michael@0 714 mIsPending = false;
michael@0 715 // We're already being called from IPDL, therefore already "async"
michael@0 716 HandleAsyncAbort();
michael@0 717 }
michael@0 718
michael@0 719 void
michael@0 720 HttpChannelChild::DoNotifyListenerCleanup()
michael@0 721 {
michael@0 722 if (mIPCOpen)
michael@0 723 PHttpChannelChild::Send__delete__(this);
michael@0 724 }
michael@0 725
michael@0 726 class DeleteSelfEvent : public ChannelEvent
michael@0 727 {
michael@0 728 public:
michael@0 729 DeleteSelfEvent(HttpChannelChild* child) : mChild(child) {}
michael@0 730 void Run() { mChild->DeleteSelf(); }
michael@0 731 private:
michael@0 732 HttpChannelChild* mChild;
michael@0 733 };
michael@0 734
michael@0 735 bool
michael@0 736 HttpChannelChild::RecvDeleteSelf()
michael@0 737 {
michael@0 738 if (mEventQ->ShouldEnqueue()) {
michael@0 739 mEventQ->Enqueue(new DeleteSelfEvent(this));
michael@0 740 } else {
michael@0 741 DeleteSelf();
michael@0 742 }
michael@0 743 return true;
michael@0 744 }
michael@0 745
michael@0 746 void
michael@0 747 HttpChannelChild::DeleteSelf()
michael@0 748 {
michael@0 749 Send__delete__(this);
michael@0 750 }
michael@0 751
michael@0 752 class Redirect1Event : public ChannelEvent
michael@0 753 {
michael@0 754 public:
michael@0 755 Redirect1Event(HttpChannelChild* child,
michael@0 756 const uint32_t& newChannelId,
michael@0 757 const URIParams& newURI,
michael@0 758 const uint32_t& redirectFlags,
michael@0 759 const nsHttpResponseHead& responseHead)
michael@0 760 : mChild(child)
michael@0 761 , mNewChannelId(newChannelId)
michael@0 762 , mNewURI(newURI)
michael@0 763 , mRedirectFlags(redirectFlags)
michael@0 764 , mResponseHead(responseHead) {}
michael@0 765
michael@0 766 void Run()
michael@0 767 {
michael@0 768 mChild->Redirect1Begin(mNewChannelId, mNewURI, mRedirectFlags,
michael@0 769 mResponseHead);
michael@0 770 }
michael@0 771 private:
michael@0 772 HttpChannelChild* mChild;
michael@0 773 uint32_t mNewChannelId;
michael@0 774 URIParams mNewURI;
michael@0 775 uint32_t mRedirectFlags;
michael@0 776 nsHttpResponseHead mResponseHead;
michael@0 777 };
michael@0 778
michael@0 779 bool
michael@0 780 HttpChannelChild::RecvRedirect1Begin(const uint32_t& newChannelId,
michael@0 781 const URIParams& newUri,
michael@0 782 const uint32_t& redirectFlags,
michael@0 783 const nsHttpResponseHead& responseHead)
michael@0 784 {
michael@0 785 if (mEventQ->ShouldEnqueue()) {
michael@0 786 mEventQ->Enqueue(new Redirect1Event(this, newChannelId, newUri,
michael@0 787 redirectFlags, responseHead));
michael@0 788 } else {
michael@0 789 Redirect1Begin(newChannelId, newUri, redirectFlags, responseHead);
michael@0 790 }
michael@0 791 return true;
michael@0 792 }
michael@0 793
michael@0 794 void
michael@0 795 HttpChannelChild::Redirect1Begin(const uint32_t& newChannelId,
michael@0 796 const URIParams& newUri,
michael@0 797 const uint32_t& redirectFlags,
michael@0 798 const nsHttpResponseHead& responseHead)
michael@0 799 {
michael@0 800 nsresult rv;
michael@0 801
michael@0 802 nsCOMPtr<nsIIOService> ioService;
michael@0 803 rv = gHttpHandler->GetIOService(getter_AddRefs(ioService));
michael@0 804 if (NS_FAILED(rv)) {
michael@0 805 // Veto redirect. nsHttpChannel decides to cancel or continue.
michael@0 806 OnRedirectVerifyCallback(rv);
michael@0 807 return;
michael@0 808 }
michael@0 809
michael@0 810 nsCOMPtr<nsIURI> uri = DeserializeURI(newUri);
michael@0 811
michael@0 812 nsCOMPtr<nsIChannel> newChannel;
michael@0 813 rv = ioService->NewChannelFromURI(uri, getter_AddRefs(newChannel));
michael@0 814 if (NS_FAILED(rv)) {
michael@0 815 // Veto redirect. nsHttpChannel decides to cancel or continue.
michael@0 816 OnRedirectVerifyCallback(rv);
michael@0 817 return;
michael@0 818 }
michael@0 819
michael@0 820 // We won't get OnStartRequest, set cookies here.
michael@0 821 mResponseHead = new nsHttpResponseHead(responseHead);
michael@0 822 SetCookie(mResponseHead->PeekHeader(nsHttp::Set_Cookie));
michael@0 823
michael@0 824 bool rewriteToGET = HttpBaseChannel::ShouldRewriteRedirectToGET(mResponseHead->Status(),
michael@0 825 mRequestHead.ParsedMethod());
michael@0 826
michael@0 827 rv = SetupReplacementChannel(uri, newChannel, !rewriteToGET);
michael@0 828 if (NS_FAILED(rv)) {
michael@0 829 // Veto redirect. nsHttpChannel decides to cancel or continue.
michael@0 830 OnRedirectVerifyCallback(rv);
michael@0 831 return;
michael@0 832 }
michael@0 833
michael@0 834 mRedirectChannelChild = do_QueryInterface(newChannel);
michael@0 835 if (mRedirectChannelChild) {
michael@0 836 mRedirectChannelChild->ConnectParent(newChannelId);
michael@0 837 rv = gHttpHandler->AsyncOnChannelRedirect(this,
michael@0 838 newChannel,
michael@0 839 redirectFlags);
michael@0 840 } else {
michael@0 841 LOG((" redirecting to a protocol that doesn't implement"
michael@0 842 " nsIChildChannel"));
michael@0 843 rv = NS_ERROR_FAILURE;
michael@0 844 }
michael@0 845
michael@0 846 if (NS_FAILED(rv))
michael@0 847 OnRedirectVerifyCallback(rv);
michael@0 848 }
michael@0 849
michael@0 850 class Redirect3Event : public ChannelEvent
michael@0 851 {
michael@0 852 public:
michael@0 853 Redirect3Event(HttpChannelChild* child) : mChild(child) {}
michael@0 854 void Run() { mChild->Redirect3Complete(); }
michael@0 855 private:
michael@0 856 HttpChannelChild* mChild;
michael@0 857 };
michael@0 858
michael@0 859 bool
michael@0 860 HttpChannelChild::RecvRedirect3Complete()
michael@0 861 {
michael@0 862 if (mEventQ->ShouldEnqueue()) {
michael@0 863 mEventQ->Enqueue(new Redirect3Event(this));
michael@0 864 } else {
michael@0 865 Redirect3Complete();
michael@0 866 }
michael@0 867 return true;
michael@0 868 }
michael@0 869
michael@0 870 class HttpFlushedForDiversionEvent : public ChannelEvent
michael@0 871 {
michael@0 872 public:
michael@0 873 HttpFlushedForDiversionEvent(HttpChannelChild* aChild)
michael@0 874 : mChild(aChild)
michael@0 875 {
michael@0 876 MOZ_RELEASE_ASSERT(aChild);
michael@0 877 }
michael@0 878
michael@0 879 void Run()
michael@0 880 {
michael@0 881 mChild->FlushedForDiversion();
michael@0 882 }
michael@0 883 private:
michael@0 884 HttpChannelChild* mChild;
michael@0 885 };
michael@0 886
michael@0 887 bool
michael@0 888 HttpChannelChild::RecvFlushedForDiversion()
michael@0 889 {
michael@0 890 MOZ_RELEASE_ASSERT(mDivertingToParent);
michael@0 891 MOZ_RELEASE_ASSERT(mEventQ->ShouldEnqueue());
michael@0 892
michael@0 893 mEventQ->Enqueue(new HttpFlushedForDiversionEvent(this));
michael@0 894
michael@0 895 return true;
michael@0 896 }
michael@0 897
michael@0 898 void
michael@0 899 HttpChannelChild::FlushedForDiversion()
michael@0 900 {
michael@0 901 MOZ_RELEASE_ASSERT(mDivertingToParent);
michael@0 902
michael@0 903 // Once this is set, it should not be unset before HttpChannelChild is taken
michael@0 904 // down. After it is set, no OnStart/OnData/OnStop callbacks should be
michael@0 905 // received from the parent channel, nor dequeued from the ChannelEventQueue.
michael@0 906 mFlushedForDiversion = true;
michael@0 907
michael@0 908 SendDivertComplete();
michael@0 909 }
michael@0 910
michael@0 911 bool
michael@0 912 HttpChannelChild::RecvDivertMessages()
michael@0 913 {
michael@0 914 MOZ_RELEASE_ASSERT(mDivertingToParent);
michael@0 915 MOZ_RELEASE_ASSERT(mSuspendCount > 0);
michael@0 916
michael@0 917 // DivertTo() has been called on parent, so we can now start sending queued
michael@0 918 // IPDL messages back to parent listener.
michael@0 919 MOZ_RELEASE_ASSERT(NS_SUCCEEDED(Resume()));
michael@0 920
michael@0 921 return true;
michael@0 922 }
michael@0 923
michael@0 924 void
michael@0 925 HttpChannelChild::Redirect3Complete()
michael@0 926 {
michael@0 927 nsresult rv = NS_OK;
michael@0 928
michael@0 929 // Chrome channel has been AsyncOpen'd. Reflect this in child.
michael@0 930 if (mRedirectChannelChild)
michael@0 931 rv = mRedirectChannelChild->CompleteRedirectSetup(mListener,
michael@0 932 mListenerContext);
michael@0 933
michael@0 934 // Redirecting to new channel: shut this down and init new channel
michael@0 935 if (mLoadGroup)
michael@0 936 mLoadGroup->RemoveRequest(this, nullptr, NS_BINDING_ABORTED);
michael@0 937
michael@0 938 if (NS_FAILED(rv))
michael@0 939 NS_WARNING("CompleteRedirectSetup failed, HttpChannelChild already open?");
michael@0 940
michael@0 941 // Release ref to new channel.
michael@0 942 mRedirectChannelChild = nullptr;
michael@0 943 }
michael@0 944
michael@0 945 //-----------------------------------------------------------------------------
michael@0 946 // HttpChannelChild::nsIChildChannel
michael@0 947 //-----------------------------------------------------------------------------
michael@0 948
michael@0 949 NS_IMETHODIMP
michael@0 950 HttpChannelChild::ConnectParent(uint32_t id)
michael@0 951 {
michael@0 952 mozilla::dom::TabChild* tabChild = nullptr;
michael@0 953 nsCOMPtr<nsITabChild> iTabChild;
michael@0 954 GetCallback(iTabChild);
michael@0 955 if (iTabChild) {
michael@0 956 tabChild = static_cast<mozilla::dom::TabChild*>(iTabChild.get());
michael@0 957 }
michael@0 958 if (MissingRequiredTabChild(tabChild, "http")) {
michael@0 959 return NS_ERROR_ILLEGAL_VALUE;
michael@0 960 }
michael@0 961
michael@0 962 // The socket transport in the chrome process now holds a logical ref to us
michael@0 963 // until OnStopRequest, or we do a redirect, or we hit an IPDL error.
michael@0 964 AddIPDLReference();
michael@0 965
michael@0 966 HttpChannelConnectArgs connectArgs(id);
michael@0 967 if (!gNeckoChild->
michael@0 968 SendPHttpChannelConstructor(this, tabChild,
michael@0 969 IPC::SerializedLoadContext(this),
michael@0 970 connectArgs)) {
michael@0 971 return NS_ERROR_FAILURE;
michael@0 972 }
michael@0 973
michael@0 974 return NS_OK;
michael@0 975 }
michael@0 976
michael@0 977 NS_IMETHODIMP
michael@0 978 HttpChannelChild::CompleteRedirectSetup(nsIStreamListener *listener,
michael@0 979 nsISupports *aContext)
michael@0 980 {
michael@0 981 LOG(("HttpChannelChild::FinishRedirectSetup [this=%p]\n", this));
michael@0 982
michael@0 983 NS_ENSURE_TRUE(!mIsPending, NS_ERROR_IN_PROGRESS);
michael@0 984 NS_ENSURE_TRUE(!mWasOpened, NS_ERROR_ALREADY_OPENED);
michael@0 985
michael@0 986 /*
michael@0 987 * No need to check for cancel: we don't get here if nsHttpChannel canceled
michael@0 988 * before AsyncOpen(); if it's canceled after that, OnStart/Stop will just
michael@0 989 * get called with error code as usual. So just setup mListener and make the
michael@0 990 * channel reflect AsyncOpen'ed state.
michael@0 991 */
michael@0 992
michael@0 993 mIsPending = true;
michael@0 994 mWasOpened = true;
michael@0 995 mListener = listener;
michael@0 996 mListenerContext = aContext;
michael@0 997
michael@0 998 // add ourselves to the load group.
michael@0 999 if (mLoadGroup)
michael@0 1000 mLoadGroup->AddRequest(this, nullptr);
michael@0 1001
michael@0 1002 // We already have an open IPDL connection to the parent. If on-modify-request
michael@0 1003 // listeners or load group observers canceled us, let the parent handle it
michael@0 1004 // and send it back to us naturally.
michael@0 1005 return NS_OK;
michael@0 1006 }
michael@0 1007
michael@0 1008 //-----------------------------------------------------------------------------
michael@0 1009 // HttpChannelChild::nsIAsyncVerifyRedirectCallback
michael@0 1010 //-----------------------------------------------------------------------------
michael@0 1011
michael@0 1012 NS_IMETHODIMP
michael@0 1013 HttpChannelChild::OnRedirectVerifyCallback(nsresult result)
michael@0 1014 {
michael@0 1015 OptionalURIParams redirectURI;
michael@0 1016 nsCOMPtr<nsIHttpChannel> newHttpChannel =
michael@0 1017 do_QueryInterface(mRedirectChannelChild);
michael@0 1018
michael@0 1019 if (newHttpChannel) {
michael@0 1020 // Must not be called until after redirect observers called.
michael@0 1021 newHttpChannel->SetOriginalURI(mOriginalURI);
michael@0 1022 }
michael@0 1023
michael@0 1024 RequestHeaderTuples emptyHeaders;
michael@0 1025 RequestHeaderTuples* headerTuples = &emptyHeaders;
michael@0 1026
michael@0 1027 nsCOMPtr<nsIHttpChannelChild> newHttpChannelChild =
michael@0 1028 do_QueryInterface(mRedirectChannelChild);
michael@0 1029 if (newHttpChannelChild && NS_SUCCEEDED(result)) {
michael@0 1030 newHttpChannelChild->AddCookiesToRequest();
michael@0 1031 newHttpChannelChild->GetClientSetRequestHeaders(&headerTuples);
michael@0 1032 }
michael@0 1033
michael@0 1034 /* If the redirect was canceled, bypass OMR and send an empty API
michael@0 1035 * redirect URI */
michael@0 1036 SerializeURI(nullptr, redirectURI);
michael@0 1037
michael@0 1038 if (NS_SUCCEEDED(result)) {
michael@0 1039 // Note: this is where we would notify "http-on-modify-response" observers.
michael@0 1040 // We have deliberately disabled this for child processes (see bug 806753)
michael@0 1041 //
michael@0 1042 // After we verify redirect, nsHttpChannel may hit the network: must give
michael@0 1043 // "http-on-modify-request" observers the chance to cancel before that.
michael@0 1044 //base->CallOnModifyRequestObservers();
michael@0 1045
michael@0 1046 nsCOMPtr<nsIHttpChannelInternal> newHttpChannelInternal =
michael@0 1047 do_QueryInterface(mRedirectChannelChild);
michael@0 1048 if (newHttpChannelInternal) {
michael@0 1049 nsCOMPtr<nsIURI> apiRedirectURI;
michael@0 1050 nsresult rv = newHttpChannelInternal->GetApiRedirectToURI(
michael@0 1051 getter_AddRefs(apiRedirectURI));
michael@0 1052 if (NS_SUCCEEDED(rv) && apiRedirectURI) {
michael@0 1053 /* If there was an API redirect of this channel, we need to send it
michael@0 1054 * up here, since it can't be sent via SendAsyncOpen. */
michael@0 1055 SerializeURI(apiRedirectURI, redirectURI);
michael@0 1056 }
michael@0 1057 }
michael@0 1058 }
michael@0 1059
michael@0 1060 if (mIPCOpen)
michael@0 1061 SendRedirect2Verify(result, *headerTuples, redirectURI);
michael@0 1062
michael@0 1063 return NS_OK;
michael@0 1064 }
michael@0 1065
michael@0 1066 //-----------------------------------------------------------------------------
michael@0 1067 // HttpChannelChild::nsIRequest
michael@0 1068 //-----------------------------------------------------------------------------
michael@0 1069
michael@0 1070 NS_IMETHODIMP
michael@0 1071 HttpChannelChild::Cancel(nsresult status)
michael@0 1072 {
michael@0 1073 MOZ_ASSERT(NS_IsMainThread());
michael@0 1074
michael@0 1075 if (!mCanceled) {
michael@0 1076 // If this cancel occurs before nsHttpChannel has been set up, AsyncOpen
michael@0 1077 // is responsible for cleaning up.
michael@0 1078 mCanceled = true;
michael@0 1079 mStatus = status;
michael@0 1080 if (RemoteChannelExists())
michael@0 1081 SendCancel(status);
michael@0 1082 }
michael@0 1083 return NS_OK;
michael@0 1084 }
michael@0 1085
michael@0 1086 NS_IMETHODIMP
michael@0 1087 HttpChannelChild::Suspend()
michael@0 1088 {
michael@0 1089 NS_ENSURE_TRUE(RemoteChannelExists(), NS_ERROR_NOT_AVAILABLE);
michael@0 1090
michael@0 1091 // SendSuspend only once, when suspend goes from 0 to 1.
michael@0 1092 // Don't SendSuspend at all if we're diverting callbacks to the parent;
michael@0 1093 // suspend will be called at the correct time in the parent itself.
michael@0 1094 if (!mSuspendCount++ && !mDivertingToParent) {
michael@0 1095 SendSuspend();
michael@0 1096 mSuspendSent = true;
michael@0 1097 }
michael@0 1098 mEventQ->Suspend();
michael@0 1099
michael@0 1100 return NS_OK;
michael@0 1101 }
michael@0 1102
michael@0 1103 NS_IMETHODIMP
michael@0 1104 HttpChannelChild::Resume()
michael@0 1105 {
michael@0 1106 NS_ENSURE_TRUE(RemoteChannelExists(), NS_ERROR_NOT_AVAILABLE);
michael@0 1107 NS_ENSURE_TRUE(mSuspendCount > 0, NS_ERROR_UNEXPECTED);
michael@0 1108
michael@0 1109 nsresult rv = NS_OK;
michael@0 1110
michael@0 1111 // SendResume only once, when suspend count drops to 0.
michael@0 1112 // Don't SendResume at all if we're diverting callbacks to the parent (unless
michael@0 1113 // suspend was sent earlier); otherwise, resume will be called at the correct
michael@0 1114 // time in the parent itself.
michael@0 1115 if (!--mSuspendCount && (!mDivertingToParent || mSuspendSent)) {
michael@0 1116 SendResume();
michael@0 1117 if (mCallOnResume) {
michael@0 1118 AsyncCall(mCallOnResume);
michael@0 1119 mCallOnResume = nullptr;
michael@0 1120 }
michael@0 1121 }
michael@0 1122 mEventQ->Resume();
michael@0 1123
michael@0 1124 return rv;
michael@0 1125 }
michael@0 1126
michael@0 1127 //-----------------------------------------------------------------------------
michael@0 1128 // HttpChannelChild::nsIChannel
michael@0 1129 //-----------------------------------------------------------------------------
michael@0 1130
michael@0 1131 NS_IMETHODIMP
michael@0 1132 HttpChannelChild::GetSecurityInfo(nsISupports **aSecurityInfo)
michael@0 1133 {
michael@0 1134 NS_ENSURE_ARG_POINTER(aSecurityInfo);
michael@0 1135 NS_IF_ADDREF(*aSecurityInfo = mSecurityInfo);
michael@0 1136 return NS_OK;
michael@0 1137 }
michael@0 1138
michael@0 1139 NS_IMETHODIMP
michael@0 1140 HttpChannelChild::AsyncOpen(nsIStreamListener *listener, nsISupports *aContext)
michael@0 1141 {
michael@0 1142 LOG(("HttpChannelChild::AsyncOpen [this=%p uri=%s]\n", this, mSpec.get()));
michael@0 1143
michael@0 1144 if (mCanceled)
michael@0 1145 return mStatus;
michael@0 1146
michael@0 1147 NS_ENSURE_TRUE(gNeckoChild != nullptr, NS_ERROR_FAILURE);
michael@0 1148 NS_ENSURE_ARG_POINTER(listener);
michael@0 1149 NS_ENSURE_TRUE(!mIsPending, NS_ERROR_IN_PROGRESS);
michael@0 1150 NS_ENSURE_TRUE(!mWasOpened, NS_ERROR_ALREADY_OPENED);
michael@0 1151
michael@0 1152 mAsyncOpenTime = TimeStamp::Now();
michael@0 1153
michael@0 1154 // Port checked in parent, but duplicate here so we can return with error
michael@0 1155 // immediately
michael@0 1156 nsresult rv;
michael@0 1157 rv = NS_CheckPortSafety(mURI);
michael@0 1158 if (NS_FAILED(rv))
michael@0 1159 return rv;
michael@0 1160
michael@0 1161 const char *cookieHeader = mRequestHead.PeekHeader(nsHttp::Cookie);
michael@0 1162 if (cookieHeader) {
michael@0 1163 mUserSetCookieHeader = cookieHeader;
michael@0 1164 }
michael@0 1165
michael@0 1166 AddCookiesToRequest();
michael@0 1167
michael@0 1168 //
michael@0 1169 // NOTE: From now on we must return NS_OK; all errors must be handled via
michael@0 1170 // OnStart/OnStopRequest
michael@0 1171 //
michael@0 1172
michael@0 1173 // Note: this is where we would notify "http-on-modify-request" observers.
michael@0 1174 // We have deliberately disabled this for child processes (see bug 806753)
michael@0 1175 //
michael@0 1176 // notify "http-on-modify-request" observers
michael@0 1177 //CallOnModifyRequestObservers();
michael@0 1178
michael@0 1179 mIsPending = true;
michael@0 1180 mWasOpened = true;
michael@0 1181 mListener = listener;
michael@0 1182 mListenerContext = aContext;
michael@0 1183
michael@0 1184 // add ourselves to the load group.
michael@0 1185 if (mLoadGroup)
michael@0 1186 mLoadGroup->AddRequest(this, nullptr);
michael@0 1187
michael@0 1188 if (mCanceled) {
michael@0 1189 // We may have been canceled already, either by on-modify-request
michael@0 1190 // listeners or by load group observers; in that case, don't create IPDL
michael@0 1191 // connection. See nsHttpChannel::AsyncOpen().
michael@0 1192 AsyncAbort(mStatus);
michael@0 1193 return NS_OK;
michael@0 1194 }
michael@0 1195
michael@0 1196 nsCString appCacheClientId;
michael@0 1197 if (mInheritApplicationCache) {
michael@0 1198 // Pick up an application cache from the notification
michael@0 1199 // callbacks if available
michael@0 1200 nsCOMPtr<nsIApplicationCacheContainer> appCacheContainer;
michael@0 1201 GetCallback(appCacheContainer);
michael@0 1202
michael@0 1203 if (appCacheContainer) {
michael@0 1204 nsCOMPtr<nsIApplicationCache> appCache;
michael@0 1205 rv = appCacheContainer->GetApplicationCache(getter_AddRefs(appCache));
michael@0 1206 if (NS_SUCCEEDED(rv) && appCache) {
michael@0 1207 appCache->GetClientID(appCacheClientId);
michael@0 1208 }
michael@0 1209 }
michael@0 1210 }
michael@0 1211
michael@0 1212 //
michael@0 1213 // Send request to the chrome process...
michael@0 1214 //
michael@0 1215
michael@0 1216 mozilla::dom::TabChild* tabChild = nullptr;
michael@0 1217 nsCOMPtr<nsITabChild> iTabChild;
michael@0 1218 GetCallback(iTabChild);
michael@0 1219 if (iTabChild) {
michael@0 1220 tabChild = static_cast<mozilla::dom::TabChild*>(iTabChild.get());
michael@0 1221 }
michael@0 1222 if (MissingRequiredTabChild(tabChild, "http")) {
michael@0 1223 return NS_ERROR_ILLEGAL_VALUE;
michael@0 1224 }
michael@0 1225
michael@0 1226 HttpChannelOpenArgs openArgs;
michael@0 1227 // No access to HttpChannelOpenArgs members, but they each have a
michael@0 1228 // function with the struct name that returns a ref.
michael@0 1229 SerializeURI(mURI, openArgs.uri());
michael@0 1230 SerializeURI(mOriginalURI, openArgs.original());
michael@0 1231 SerializeURI(mDocumentURI, openArgs.doc());
michael@0 1232 SerializeURI(mReferrer, openArgs.referrer());
michael@0 1233 SerializeURI(mAPIRedirectToURI, openArgs.apiRedirectTo());
michael@0 1234 openArgs.loadFlags() = mLoadFlags;
michael@0 1235 openArgs.requestHeaders() = mClientSetRequestHeaders;
michael@0 1236 openArgs.requestMethod() = mRequestHead.Method();
michael@0 1237
michael@0 1238 nsTArray<mozilla::ipc::FileDescriptor> fds;
michael@0 1239 SerializeInputStream(mUploadStream, openArgs.uploadStream(), fds);
michael@0 1240
michael@0 1241 PFileDescriptorSetChild* fdSet = nullptr;
michael@0 1242 if (!fds.IsEmpty()) {
michael@0 1243 MOZ_ASSERT(gNeckoChild->Manager());
michael@0 1244
michael@0 1245 fdSet = gNeckoChild->Manager()->SendPFileDescriptorSetConstructor(fds[0]);
michael@0 1246 for (uint32_t i = 1; i < fds.Length(); ++i) {
michael@0 1247 unused << fdSet->SendAddFileDescriptor(fds[i]);
michael@0 1248 }
michael@0 1249 }
michael@0 1250
michael@0 1251 OptionalFileDescriptorSet optionalFDs;
michael@0 1252 if (fdSet) {
michael@0 1253 optionalFDs = fdSet;
michael@0 1254 } else {
michael@0 1255 optionalFDs = mozilla::void_t();
michael@0 1256 }
michael@0 1257
michael@0 1258 openArgs.fds() = optionalFDs;
michael@0 1259
michael@0 1260 openArgs.uploadStreamHasHeaders() = mUploadStreamHasHeaders;
michael@0 1261 openArgs.priority() = mPriority;
michael@0 1262 openArgs.redirectionLimit() = mRedirectionLimit;
michael@0 1263 openArgs.allowPipelining() = mAllowPipelining;
michael@0 1264 openArgs.forceAllowThirdPartyCookie() = mForceAllowThirdPartyCookie;
michael@0 1265 openArgs.resumeAt() = mSendResumeAt;
michael@0 1266 openArgs.startPos() = mStartPos;
michael@0 1267 openArgs.entityID() = mEntityID;
michael@0 1268 openArgs.chooseApplicationCache() = mChooseApplicationCache;
michael@0 1269 openArgs.appCacheClientID() = appCacheClientId;
michael@0 1270 openArgs.allowSpdy() = mAllowSpdy;
michael@0 1271
michael@0 1272 // The socket transport in the chrome process now holds a logical ref to us
michael@0 1273 // until OnStopRequest, or we do a redirect, or we hit an IPDL error.
michael@0 1274 AddIPDLReference();
michael@0 1275
michael@0 1276 gNeckoChild->SendPHttpChannelConstructor(this, tabChild,
michael@0 1277 IPC::SerializedLoadContext(this),
michael@0 1278 openArgs);
michael@0 1279
michael@0 1280 if (fdSet) {
michael@0 1281 FileDescriptorSetChild* fdSetActor =
michael@0 1282 static_cast<FileDescriptorSetChild*>(fdSet);
michael@0 1283
michael@0 1284 fdSetActor->ForgetFileDescriptors(fds);
michael@0 1285 }
michael@0 1286
michael@0 1287 return NS_OK;
michael@0 1288 }
michael@0 1289
michael@0 1290 //-----------------------------------------------------------------------------
michael@0 1291 // HttpChannelChild::nsIHttpChannel
michael@0 1292 //-----------------------------------------------------------------------------
michael@0 1293
michael@0 1294 NS_IMETHODIMP
michael@0 1295 HttpChannelChild::SetRequestHeader(const nsACString& aHeader,
michael@0 1296 const nsACString& aValue,
michael@0 1297 bool aMerge)
michael@0 1298 {
michael@0 1299 nsresult rv = HttpBaseChannel::SetRequestHeader(aHeader, aValue, aMerge);
michael@0 1300 if (NS_FAILED(rv))
michael@0 1301 return rv;
michael@0 1302
michael@0 1303 RequestHeaderTuple* tuple = mClientSetRequestHeaders.AppendElement();
michael@0 1304 if (!tuple)
michael@0 1305 return NS_ERROR_OUT_OF_MEMORY;
michael@0 1306
michael@0 1307 tuple->mHeader = aHeader;
michael@0 1308 tuple->mValue = aValue;
michael@0 1309 tuple->mMerge = aMerge;
michael@0 1310 return NS_OK;
michael@0 1311 }
michael@0 1312
michael@0 1313 NS_IMETHODIMP
michael@0 1314 HttpChannelChild::RedirectTo(nsIURI *newURI)
michael@0 1315 {
michael@0 1316 // disabled until/unless addons run in child or something else needs this
michael@0 1317 return NS_ERROR_NOT_IMPLEMENTED;
michael@0 1318 }
michael@0 1319
michael@0 1320 //-----------------------------------------------------------------------------
michael@0 1321 // HttpChannelChild::nsIHttpChannelInternal
michael@0 1322 //-----------------------------------------------------------------------------
michael@0 1323
michael@0 1324 NS_IMETHODIMP
michael@0 1325 HttpChannelChild::SetupFallbackChannel(const char *aFallbackKey)
michael@0 1326 {
michael@0 1327 DROP_DEAD();
michael@0 1328 }
michael@0 1329
michael@0 1330 // The next four _should_ be implemented, but we need to figure out how
michael@0 1331 // to transfer the data from the chrome process first.
michael@0 1332
michael@0 1333 NS_IMETHODIMP
michael@0 1334 HttpChannelChild::GetRemoteAddress(nsACString & _result)
michael@0 1335 {
michael@0 1336 return NS_ERROR_NOT_AVAILABLE;
michael@0 1337 }
michael@0 1338
michael@0 1339 NS_IMETHODIMP
michael@0 1340 HttpChannelChild::GetRemotePort(int32_t * _result)
michael@0 1341 {
michael@0 1342 NS_ENSURE_ARG_POINTER(_result);
michael@0 1343 return NS_ERROR_NOT_AVAILABLE;
michael@0 1344 }
michael@0 1345
michael@0 1346 NS_IMETHODIMP
michael@0 1347 HttpChannelChild::GetLocalAddress(nsACString & _result)
michael@0 1348 {
michael@0 1349 return NS_ERROR_NOT_AVAILABLE;
michael@0 1350 }
michael@0 1351
michael@0 1352 NS_IMETHODIMP
michael@0 1353 HttpChannelChild::GetLocalPort(int32_t * _result)
michael@0 1354 {
michael@0 1355 NS_ENSURE_ARG_POINTER(_result);
michael@0 1356 return NS_ERROR_NOT_AVAILABLE;
michael@0 1357 }
michael@0 1358
michael@0 1359
michael@0 1360 //-----------------------------------------------------------------------------
michael@0 1361 // HttpChannelChild::nsICacheInfoChannel
michael@0 1362 //-----------------------------------------------------------------------------
michael@0 1363
michael@0 1364 NS_IMETHODIMP
michael@0 1365 HttpChannelChild::GetCacheTokenExpirationTime(uint32_t *_retval)
michael@0 1366 {
michael@0 1367 NS_ENSURE_ARG_POINTER(_retval);
michael@0 1368 if (!mCacheEntryAvailable)
michael@0 1369 return NS_ERROR_NOT_AVAILABLE;
michael@0 1370
michael@0 1371 *_retval = mCacheExpirationTime;
michael@0 1372 return NS_OK;
michael@0 1373 }
michael@0 1374
michael@0 1375 NS_IMETHODIMP
michael@0 1376 HttpChannelChild::GetCacheTokenCachedCharset(nsACString &_retval)
michael@0 1377 {
michael@0 1378 if (!mCacheEntryAvailable)
michael@0 1379 return NS_ERROR_NOT_AVAILABLE;
michael@0 1380
michael@0 1381 _retval = mCachedCharset;
michael@0 1382 return NS_OK;
michael@0 1383 }
michael@0 1384 NS_IMETHODIMP
michael@0 1385 HttpChannelChild::SetCacheTokenCachedCharset(const nsACString &aCharset)
michael@0 1386 {
michael@0 1387 if (!mCacheEntryAvailable || !RemoteChannelExists())
michael@0 1388 return NS_ERROR_NOT_AVAILABLE;
michael@0 1389
michael@0 1390 mCachedCharset = aCharset;
michael@0 1391 if (!SendSetCacheTokenCachedCharset(PromiseFlatCString(aCharset))) {
michael@0 1392 return NS_ERROR_FAILURE;
michael@0 1393 }
michael@0 1394 return NS_OK;
michael@0 1395 }
michael@0 1396
michael@0 1397 NS_IMETHODIMP
michael@0 1398 HttpChannelChild::IsFromCache(bool *value)
michael@0 1399 {
michael@0 1400 if (!mIsPending)
michael@0 1401 return NS_ERROR_NOT_AVAILABLE;
michael@0 1402
michael@0 1403 *value = mIsFromCache;
michael@0 1404 return NS_OK;
michael@0 1405 }
michael@0 1406
michael@0 1407 //-----------------------------------------------------------------------------
michael@0 1408 // HttpChannelChild::nsIResumableChannel
michael@0 1409 //-----------------------------------------------------------------------------
michael@0 1410
michael@0 1411 NS_IMETHODIMP
michael@0 1412 HttpChannelChild::ResumeAt(uint64_t startPos, const nsACString& entityID)
michael@0 1413 {
michael@0 1414 ENSURE_CALLED_BEFORE_CONNECT();
michael@0 1415 mStartPos = startPos;
michael@0 1416 mEntityID = entityID;
michael@0 1417 mSendResumeAt = true;
michael@0 1418 return NS_OK;
michael@0 1419 }
michael@0 1420
michael@0 1421 // GetEntityID is shared in HttpBaseChannel
michael@0 1422
michael@0 1423 //-----------------------------------------------------------------------------
michael@0 1424 // HttpChannelChild::nsISupportsPriority
michael@0 1425 //-----------------------------------------------------------------------------
michael@0 1426
michael@0 1427 NS_IMETHODIMP
michael@0 1428 HttpChannelChild::SetPriority(int32_t aPriority)
michael@0 1429 {
michael@0 1430 int16_t newValue = clamped<int32_t>(aPriority, INT16_MIN, INT16_MAX);
michael@0 1431 if (mPriority == newValue)
michael@0 1432 return NS_OK;
michael@0 1433 mPriority = newValue;
michael@0 1434 if (RemoteChannelExists())
michael@0 1435 SendSetPriority(mPriority);
michael@0 1436 return NS_OK;
michael@0 1437 }
michael@0 1438
michael@0 1439 //-----------------------------------------------------------------------------
michael@0 1440 // HttpChannelChild::nsIProxiedChannel
michael@0 1441 //-----------------------------------------------------------------------------
michael@0 1442
michael@0 1443 NS_IMETHODIMP
michael@0 1444 HttpChannelChild::GetProxyInfo(nsIProxyInfo **aProxyInfo)
michael@0 1445 {
michael@0 1446 DROP_DEAD();
michael@0 1447 }
michael@0 1448
michael@0 1449 //-----------------------------------------------------------------------------
michael@0 1450 // HttpChannelChild::nsIApplicationCacheContainer
michael@0 1451 //-----------------------------------------------------------------------------
michael@0 1452
michael@0 1453 NS_IMETHODIMP
michael@0 1454 HttpChannelChild::GetApplicationCache(nsIApplicationCache **aApplicationCache)
michael@0 1455 {
michael@0 1456 NS_IF_ADDREF(*aApplicationCache = mApplicationCache);
michael@0 1457 return NS_OK;
michael@0 1458 }
michael@0 1459 NS_IMETHODIMP
michael@0 1460 HttpChannelChild::SetApplicationCache(nsIApplicationCache *aApplicationCache)
michael@0 1461 {
michael@0 1462 NS_ENSURE_TRUE(!mWasOpened, NS_ERROR_ALREADY_OPENED);
michael@0 1463
michael@0 1464 mApplicationCache = aApplicationCache;
michael@0 1465 return NS_OK;
michael@0 1466 }
michael@0 1467
michael@0 1468 //-----------------------------------------------------------------------------
michael@0 1469 // HttpChannelChild::nsIApplicationCacheChannel
michael@0 1470 //-----------------------------------------------------------------------------
michael@0 1471
michael@0 1472 NS_IMETHODIMP
michael@0 1473 HttpChannelChild::GetApplicationCacheForWrite(nsIApplicationCache **aApplicationCache)
michael@0 1474 {
michael@0 1475 *aApplicationCache = nullptr;
michael@0 1476 return NS_OK;
michael@0 1477 }
michael@0 1478 NS_IMETHODIMP
michael@0 1479 HttpChannelChild::SetApplicationCacheForWrite(nsIApplicationCache *aApplicationCache)
michael@0 1480 {
michael@0 1481 NS_ENSURE_TRUE(!mWasOpened, NS_ERROR_ALREADY_OPENED);
michael@0 1482
michael@0 1483 // Child channels are not intended to be used for cache writes
michael@0 1484 return NS_ERROR_NOT_IMPLEMENTED;
michael@0 1485 }
michael@0 1486
michael@0 1487 NS_IMETHODIMP
michael@0 1488 HttpChannelChild::GetLoadedFromApplicationCache(bool *aLoadedFromApplicationCache)
michael@0 1489 {
michael@0 1490 *aLoadedFromApplicationCache = mLoadedFromApplicationCache;
michael@0 1491 return NS_OK;
michael@0 1492 }
michael@0 1493
michael@0 1494 NS_IMETHODIMP
michael@0 1495 HttpChannelChild::GetInheritApplicationCache(bool *aInherit)
michael@0 1496 {
michael@0 1497 *aInherit = mInheritApplicationCache;
michael@0 1498 return NS_OK;
michael@0 1499 }
michael@0 1500 NS_IMETHODIMP
michael@0 1501 HttpChannelChild::SetInheritApplicationCache(bool aInherit)
michael@0 1502 {
michael@0 1503 mInheritApplicationCache = aInherit;
michael@0 1504 return NS_OK;
michael@0 1505 }
michael@0 1506
michael@0 1507 NS_IMETHODIMP
michael@0 1508 HttpChannelChild::GetChooseApplicationCache(bool *aChoose)
michael@0 1509 {
michael@0 1510 *aChoose = mChooseApplicationCache;
michael@0 1511 return NS_OK;
michael@0 1512 }
michael@0 1513
michael@0 1514 NS_IMETHODIMP
michael@0 1515 HttpChannelChild::SetChooseApplicationCache(bool aChoose)
michael@0 1516 {
michael@0 1517 mChooseApplicationCache = aChoose;
michael@0 1518 return NS_OK;
michael@0 1519 }
michael@0 1520
michael@0 1521 NS_IMETHODIMP
michael@0 1522 HttpChannelChild::MarkOfflineCacheEntryAsForeign()
michael@0 1523 {
michael@0 1524 SendMarkOfflineCacheEntryAsForeign();
michael@0 1525 return NS_OK;
michael@0 1526 }
michael@0 1527
michael@0 1528 //-----------------------------------------------------------------------------
michael@0 1529 // HttpChannelChild::nsIAssociatedContentSecurity
michael@0 1530 //-----------------------------------------------------------------------------
michael@0 1531
michael@0 1532 bool
michael@0 1533 HttpChannelChild::GetAssociatedContentSecurity(
michael@0 1534 nsIAssociatedContentSecurity** _result)
michael@0 1535 {
michael@0 1536 if (!mSecurityInfo)
michael@0 1537 return false;
michael@0 1538
michael@0 1539 nsCOMPtr<nsIAssociatedContentSecurity> assoc =
michael@0 1540 do_QueryInterface(mSecurityInfo);
michael@0 1541 if (!assoc)
michael@0 1542 return false;
michael@0 1543
michael@0 1544 if (_result)
michael@0 1545 assoc.forget(_result);
michael@0 1546 return true;
michael@0 1547 }
michael@0 1548
michael@0 1549 /* attribute unsigned long countSubRequestsBrokenSecurity; */
michael@0 1550 NS_IMETHODIMP
michael@0 1551 HttpChannelChild::GetCountSubRequestsBrokenSecurity(
michael@0 1552 int32_t *aSubRequestsBrokenSecurity)
michael@0 1553 {
michael@0 1554 nsCOMPtr<nsIAssociatedContentSecurity> assoc;
michael@0 1555 if (!GetAssociatedContentSecurity(getter_AddRefs(assoc)))
michael@0 1556 return NS_OK;
michael@0 1557
michael@0 1558 return assoc->GetCountSubRequestsBrokenSecurity(aSubRequestsBrokenSecurity);
michael@0 1559 }
michael@0 1560 NS_IMETHODIMP
michael@0 1561 HttpChannelChild::SetCountSubRequestsBrokenSecurity(
michael@0 1562 int32_t aSubRequestsBrokenSecurity)
michael@0 1563 {
michael@0 1564 nsCOMPtr<nsIAssociatedContentSecurity> assoc;
michael@0 1565 if (!GetAssociatedContentSecurity(getter_AddRefs(assoc)))
michael@0 1566 return NS_OK;
michael@0 1567
michael@0 1568 return assoc->SetCountSubRequestsBrokenSecurity(aSubRequestsBrokenSecurity);
michael@0 1569 }
michael@0 1570
michael@0 1571 /* attribute unsigned long countSubRequestsNoSecurity; */
michael@0 1572 NS_IMETHODIMP
michael@0 1573 HttpChannelChild::GetCountSubRequestsNoSecurity(int32_t *aSubRequestsNoSecurity)
michael@0 1574 {
michael@0 1575 nsCOMPtr<nsIAssociatedContentSecurity> assoc;
michael@0 1576 if (!GetAssociatedContentSecurity(getter_AddRefs(assoc)))
michael@0 1577 return NS_OK;
michael@0 1578
michael@0 1579 return assoc->GetCountSubRequestsNoSecurity(aSubRequestsNoSecurity);
michael@0 1580 }
michael@0 1581 NS_IMETHODIMP
michael@0 1582 HttpChannelChild::SetCountSubRequestsNoSecurity(int32_t aSubRequestsNoSecurity)
michael@0 1583 {
michael@0 1584 nsCOMPtr<nsIAssociatedContentSecurity> assoc;
michael@0 1585 if (!GetAssociatedContentSecurity(getter_AddRefs(assoc)))
michael@0 1586 return NS_OK;
michael@0 1587
michael@0 1588 return assoc->SetCountSubRequestsNoSecurity(aSubRequestsNoSecurity);
michael@0 1589 }
michael@0 1590
michael@0 1591 NS_IMETHODIMP
michael@0 1592 HttpChannelChild::Flush()
michael@0 1593 {
michael@0 1594 nsCOMPtr<nsIAssociatedContentSecurity> assoc;
michael@0 1595 if (!GetAssociatedContentSecurity(getter_AddRefs(assoc)))
michael@0 1596 return NS_OK;
michael@0 1597
michael@0 1598 nsresult rv;
michael@0 1599 int32_t broken, no;
michael@0 1600
michael@0 1601 rv = assoc->GetCountSubRequestsBrokenSecurity(&broken);
michael@0 1602 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1603 rv = assoc->GetCountSubRequestsNoSecurity(&no);
michael@0 1604 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1605
michael@0 1606 if (mIPCOpen)
michael@0 1607 SendUpdateAssociatedContentSecurity(broken, no);
michael@0 1608
michael@0 1609 return NS_OK;
michael@0 1610 }
michael@0 1611
michael@0 1612 //-----------------------------------------------------------------------------
michael@0 1613 // HttpChannelChild::nsIHttpChannelChild
michael@0 1614 //-----------------------------------------------------------------------------
michael@0 1615
michael@0 1616 NS_IMETHODIMP HttpChannelChild::AddCookiesToRequest()
michael@0 1617 {
michael@0 1618 HttpBaseChannel::AddCookiesToRequest();
michael@0 1619 return NS_OK;
michael@0 1620 }
michael@0 1621
michael@0 1622 NS_IMETHODIMP HttpChannelChild::GetClientSetRequestHeaders(RequestHeaderTuples **aRequestHeaders)
michael@0 1623 {
michael@0 1624 *aRequestHeaders = &mClientSetRequestHeaders;
michael@0 1625 return NS_OK;
michael@0 1626 }
michael@0 1627
michael@0 1628 //-----------------------------------------------------------------------------
michael@0 1629 // HttpChannelChild::nsIDivertableChannel
michael@0 1630 //-----------------------------------------------------------------------------
michael@0 1631 NS_IMETHODIMP
michael@0 1632 HttpChannelChild::DivertToParent(ChannelDiverterChild **aChild)
michael@0 1633 {
michael@0 1634 MOZ_RELEASE_ASSERT(aChild);
michael@0 1635 MOZ_RELEASE_ASSERT(gNeckoChild);
michael@0 1636 MOZ_RELEASE_ASSERT(!mDivertingToParent);
michael@0 1637
michael@0 1638 // We must fail DivertToParent() if there's no parent end of the channel (and
michael@0 1639 // won't be!) due to early failure.
michael@0 1640 if (NS_FAILED(mStatus) && !RemoteChannelExists()) {
michael@0 1641 return mStatus;
michael@0 1642 }
michael@0 1643
michael@0 1644 nsresult rv = Suspend();
michael@0 1645 if (NS_WARN_IF(NS_FAILED(rv))) {
michael@0 1646 return rv;
michael@0 1647 }
michael@0 1648
michael@0 1649 // Once this is set, it should not be unset before the child is taken down.
michael@0 1650 mDivertingToParent = true;
michael@0 1651
michael@0 1652 PChannelDiverterChild* diverter =
michael@0 1653 gNeckoChild->SendPChannelDiverterConstructor(this);
michael@0 1654 MOZ_RELEASE_ASSERT(diverter);
michael@0 1655
michael@0 1656 *aChild = static_cast<ChannelDiverterChild*>(diverter);
michael@0 1657
michael@0 1658 return NS_OK;
michael@0 1659 }
michael@0 1660
michael@0 1661 }} // mozilla::net

mercurial