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