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 : /* ***** BEGIN LICENSE BLOCK *****
4 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 : *
6 : * The contents of this file are subject to the Mozilla Public License Version
7 : * 1.1 (the "License"); you may not use this file except in compliance with
8 : * the License. You may obtain a copy of the License at
9 : * http://www.mozilla.org/MPL/
10 : *
11 : * Software distributed under the License is distributed on an "AS IS" basis,
12 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 : * for the specific language governing rights and limitations under the
14 : * License.
15 : *
16 : * The Original Code is mozilla.org code.
17 : *
18 : * The Initial Developer of the Original Code is
19 : * the Mozilla Foundation.
20 : * Portions created by the Initial Developer are Copyright (C) 2009
21 : * the Initial Developer. All Rights Reserved.
22 : *
23 : * Contributor(s):
24 : * Jason Duell <jduell.mcbugs@gmail.com>
25 : * Honza Bambas <honzab@firemni.cz>
26 : *
27 : * Alternatively, the contents of this file may be used under the terms of
28 : * either the GNU General Public License Version 2 or later (the "GPL"), or
29 : * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
30 : * in which case the provisions of the GPL or the LGPL are applicable instead
31 : * of those above. If you wish to allow use of your version of this file only
32 : * under the terms of either the GPL or the LGPL, and not to allow others to
33 : * use your version of this file under the terms of the MPL, indicate your
34 : * decision by deleting the provisions above and replace them with the notice
35 : * and other provisions required by the GPL or the LGPL. If you do not delete
36 : * the provisions above, a recipient may use your version of this file under
37 : * the terms of any one of the MPL, the GPL or the LGPL.
38 : *
39 : * ***** END LICENSE BLOCK ***** */
40 :
41 : #include "mozilla/net/HttpChannelParent.h"
42 : #include "mozilla/dom/TabParent.h"
43 : #include "mozilla/net/NeckoParent.h"
44 : #include "mozilla/unused.h"
45 : #include "HttpChannelParentListener.h"
46 : #include "nsHttpChannel.h"
47 : #include "nsHttpHandler.h"
48 : #include "nsNetUtil.h"
49 : #include "nsISupportsPriority.h"
50 : #include "nsIAuthPromptProvider.h"
51 : #include "nsIDocShellTreeItem.h"
52 : #include "nsIBadCertListener2.h"
53 : #include "nsICacheEntryDescriptor.h"
54 : #include "nsSerializationHelper.h"
55 : #include "nsISerializable.h"
56 : #include "nsIAssociatedContentSecurity.h"
57 : #include "nsIApplicationCacheService.h"
58 : #include "nsIOfflineCacheUpdate.h"
59 : #include "nsIRedirectChannelRegistrar.h"
60 : #include "prinit.h"
61 :
62 : namespace mozilla {
63 : namespace net {
64 :
65 0 : HttpChannelParent::HttpChannelParent(PBrowserParent* iframeEmbedding)
66 : : mIPCClosed(false)
67 : , mStoredStatus(0)
68 : , mStoredProgress(0)
69 : , mStoredProgressMax(0)
70 : , mSentRedirect1Begin(false)
71 : , mSentRedirect1BeginFailed(false)
72 0 : , mReceivedRedirect2Verify(false)
73 : {
74 : // Ensure gHttpHandler is initialized: we need the atom table up and running.
75 : nsIHttpProtocolHandler* handler;
76 0 : CallGetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "http", &handler);
77 0 : NS_ASSERTION(handler, "no http handler");
78 :
79 0 : mTabParent = do_QueryObject(static_cast<TabParent*>(iframeEmbedding));
80 0 : }
81 :
82 0 : HttpChannelParent::~HttpChannelParent()
83 : {
84 0 : gHttpHandler->Release();
85 0 : }
86 :
87 : void
88 0 : HttpChannelParent::ActorDestroy(ActorDestroyReason why)
89 : {
90 : // We may still have refcount>0 if nsHttpChannel hasn't called OnStopRequest
91 : // yet, but child process has crashed. We must not try to send any more msgs
92 : // to child, or IPDL will kill chrome process, too.
93 0 : mIPCClosed = true;
94 0 : }
95 :
96 : //-----------------------------------------------------------------------------
97 : // HttpChannelParent::nsISupports
98 : //-----------------------------------------------------------------------------
99 :
100 0 : NS_IMPL_ISUPPORTS6(HttpChannelParent,
101 : nsIInterfaceRequestor,
102 : nsIProgressEventSink,
103 : nsIRequestObserver,
104 : nsIStreamListener,
105 : nsIParentChannel,
106 : nsIParentRedirectingChannel)
107 :
108 : //-----------------------------------------------------------------------------
109 : // HttpChannelParent::nsIInterfaceRequestor
110 : //-----------------------------------------------------------------------------
111 :
112 : NS_IMETHODIMP
113 0 : HttpChannelParent::GetInterface(const nsIID& aIID, void **result)
114 : {
115 0 : if (aIID.Equals(NS_GET_IID(nsIAuthPromptProvider)) ||
116 0 : aIID.Equals(NS_GET_IID(nsISecureBrowserUI))) {
117 0 : if (!mTabParent)
118 0 : return NS_NOINTERFACE;
119 :
120 0 : return mTabParent->QueryInterface(aIID, result);
121 : }
122 :
123 0 : return QueryInterface(aIID, result);
124 : }
125 :
126 : //-----------------------------------------------------------------------------
127 : // HttpChannelParent::PHttpChannelParent
128 : //-----------------------------------------------------------------------------
129 :
130 : bool
131 0 : HttpChannelParent::RecvAsyncOpen(const IPC::URI& aURI,
132 : const IPC::URI& aOriginalURI,
133 : const IPC::URI& aDocURI,
134 : const IPC::URI& aReferrerURI,
135 : const PRUint32& loadFlags,
136 : const RequestHeaderTuples& requestHeaders,
137 : const nsHttpAtom& requestMethod,
138 : const IPC::InputStream& uploadStream,
139 : const bool& uploadStreamHasHeaders,
140 : const PRUint16& priority,
141 : const PRUint8& redirectionLimit,
142 : const bool& allowPipelining,
143 : const bool& forceAllowThirdPartyCookie,
144 : const bool& doResumeAt,
145 : const PRUint64& startPos,
146 : const nsCString& entityID,
147 : const bool& chooseApplicationCache,
148 : const nsCString& appCacheClientID,
149 : const bool& allowSpdy)
150 : {
151 0 : nsCOMPtr<nsIURI> uri(aURI);
152 0 : nsCOMPtr<nsIURI> originalUri(aOriginalURI);
153 0 : nsCOMPtr<nsIURI> docUri(aDocURI);
154 0 : nsCOMPtr<nsIURI> referrerUri(aReferrerURI);
155 :
156 0 : nsCString uriSpec;
157 0 : uri->GetSpec(uriSpec);
158 0 : LOG(("HttpChannelParent RecvAsyncOpen [this=%x uri=%s]\n",
159 : this, uriSpec.get()));
160 :
161 : nsresult rv;
162 :
163 0 : nsCOMPtr<nsIIOService> ios(do_GetIOService(&rv));
164 0 : if (NS_FAILED(rv))
165 0 : return SendFailedAsyncOpen(rv);
166 :
167 0 : rv = NS_NewChannel(getter_AddRefs(mChannel), uri, ios, nsnull, nsnull, loadFlags);
168 0 : if (NS_FAILED(rv))
169 0 : return SendFailedAsyncOpen(rv);
170 :
171 0 : nsHttpChannel *httpChan = static_cast<nsHttpChannel *>(mChannel.get());
172 :
173 0 : if (doResumeAt)
174 0 : httpChan->ResumeAt(startPos, entityID);
175 :
176 0 : if (originalUri)
177 0 : httpChan->SetOriginalURI(originalUri);
178 0 : if (docUri)
179 0 : httpChan->SetDocumentURI(docUri);
180 0 : if (referrerUri)
181 0 : httpChan->SetReferrerInternal(referrerUri);
182 0 : if (loadFlags != nsIRequest::LOAD_NORMAL)
183 0 : httpChan->SetLoadFlags(loadFlags);
184 :
185 0 : for (PRUint32 i = 0; i < requestHeaders.Length(); i++) {
186 0 : httpChan->SetRequestHeader(requestHeaders[i].mHeader,
187 0 : requestHeaders[i].mValue,
188 0 : requestHeaders[i].mMerge);
189 : }
190 :
191 : nsRefPtr<HttpChannelParentListener> channelListener =
192 0 : new HttpChannelParentListener(this);
193 :
194 0 : httpChan->SetNotificationCallbacks(channelListener);
195 :
196 0 : httpChan->SetRequestMethod(nsDependentCString(requestMethod.get()));
197 :
198 0 : nsCOMPtr<nsIInputStream> stream(uploadStream);
199 0 : if (stream) {
200 0 : httpChan->InternalSetUploadStream(stream);
201 0 : httpChan->SetUploadStreamHasHeaders(uploadStreamHasHeaders);
202 : }
203 :
204 0 : if (priority != nsISupportsPriority::PRIORITY_NORMAL)
205 0 : httpChan->SetPriority(priority);
206 0 : httpChan->SetRedirectionLimit(redirectionLimit);
207 0 : httpChan->SetAllowPipelining(allowPipelining);
208 0 : httpChan->SetForceAllowThirdPartyCookie(forceAllowThirdPartyCookie);
209 0 : httpChan->SetAllowSpdy(allowSpdy);
210 :
211 : nsCOMPtr<nsIApplicationCacheChannel> appCacheChan =
212 0 : do_QueryInterface(mChannel);
213 : nsCOMPtr<nsIApplicationCacheService> appCacheService =
214 0 : do_GetService(NS_APPLICATIONCACHESERVICE_CONTRACTID);
215 :
216 0 : bool setChooseApplicationCache = chooseApplicationCache;
217 0 : if (appCacheChan && appCacheService) {
218 : // We might potentially want to drop this flag (that is TRUE by default)
219 : // after we succefully associate the channel with an application cache
220 : // reported by the channel child. Dropping it here may be too early.
221 0 : appCacheChan->SetInheritApplicationCache(false);
222 0 : if (!appCacheClientID.IsEmpty()) {
223 0 : nsCOMPtr<nsIApplicationCache> appCache;
224 0 : rv = appCacheService->GetApplicationCache(appCacheClientID,
225 0 : getter_AddRefs(appCache));
226 0 : if (NS_SUCCEEDED(rv)) {
227 0 : appCacheChan->SetApplicationCache(appCache);
228 0 : setChooseApplicationCache = false;
229 : }
230 : }
231 :
232 0 : if (setChooseApplicationCache) {
233 : nsCOMPtr<nsIOfflineCacheUpdateService> offlineUpdateService =
234 0 : do_GetService("@mozilla.org/offlinecacheupdate-service;1", &rv);
235 0 : if (NS_SUCCEEDED(rv)) {
236 0 : rv = offlineUpdateService->OfflineAppAllowedForURI(uri,
237 : nsnull,
238 0 : &setChooseApplicationCache);
239 :
240 0 : if (setChooseApplicationCache && NS_SUCCEEDED(rv))
241 0 : appCacheChan->SetChooseApplicationCache(true);
242 : }
243 : }
244 : }
245 :
246 0 : rv = httpChan->AsyncOpen(channelListener, nsnull);
247 0 : if (NS_FAILED(rv))
248 0 : return SendFailedAsyncOpen(rv);
249 :
250 0 : return true;
251 : }
252 :
253 : bool
254 0 : HttpChannelParent::RecvConnectChannel(const PRUint32& channelId)
255 : {
256 : nsresult rv;
257 :
258 0 : LOG(("Looking for a registered channel [this=%p, id=%d]", this, channelId));
259 0 : rv = NS_LinkRedirectChannels(channelId, this, getter_AddRefs(mChannel));
260 0 : LOG((" found channel %p, rv=%08x", mChannel.get(), rv));
261 :
262 0 : return true;
263 : }
264 :
265 : bool
266 0 : HttpChannelParent::RecvSetPriority(const PRUint16& priority)
267 : {
268 0 : if (mChannel) {
269 0 : nsHttpChannel *httpChan = static_cast<nsHttpChannel *>(mChannel.get());
270 0 : httpChan->SetPriority(priority);
271 : }
272 :
273 : nsCOMPtr<nsISupportsPriority> priorityRedirectChannel =
274 0 : do_QueryInterface(mRedirectChannel);
275 0 : if (priorityRedirectChannel)
276 0 : priorityRedirectChannel->SetPriority(priority);
277 :
278 0 : return true;
279 : }
280 :
281 : bool
282 0 : HttpChannelParent::RecvSuspend()
283 : {
284 0 : if (mChannel) {
285 0 : mChannel->Suspend();
286 : }
287 0 : return true;
288 : }
289 :
290 : bool
291 0 : HttpChannelParent::RecvResume()
292 : {
293 0 : if (mChannel) {
294 0 : mChannel->Resume();
295 : }
296 0 : return true;
297 : }
298 :
299 : bool
300 0 : HttpChannelParent::RecvCancel(const nsresult& status)
301 : {
302 : // May receive cancel before channel has been constructed!
303 0 : if (mChannel) {
304 0 : nsHttpChannel *httpChan = static_cast<nsHttpChannel *>(mChannel.get());
305 0 : httpChan->Cancel(status);
306 : }
307 0 : return true;
308 : }
309 :
310 :
311 : bool
312 0 : HttpChannelParent::RecvSetCacheTokenCachedCharset(const nsCString& charset)
313 : {
314 0 : if (mCacheDescriptor)
315 0 : mCacheDescriptor->SetMetaDataElement("charset", charset.get());
316 0 : return true;
317 : }
318 :
319 : bool
320 0 : HttpChannelParent::RecvUpdateAssociatedContentSecurity(const PRInt32& high,
321 : const PRInt32& low,
322 : const PRInt32& broken,
323 : const PRInt32& no)
324 : {
325 0 : if (mAssociatedContentSecurity) {
326 0 : mAssociatedContentSecurity->SetCountSubRequestsHighSecurity(high);
327 0 : mAssociatedContentSecurity->SetCountSubRequestsLowSecurity(low);
328 0 : mAssociatedContentSecurity->SetCountSubRequestsBrokenSecurity(broken);
329 0 : mAssociatedContentSecurity->SetCountSubRequestsNoSecurity(no);
330 : }
331 0 : return true;
332 : }
333 :
334 : // Bug 621446 investigation, we don't want conditional PR_Aborts bellow to be
335 : // merged to a single address.
336 : #pragma warning(disable : 4068)
337 : #pragma GCC optimize ("O0")
338 :
339 : bool
340 0 : HttpChannelParent::RecvRedirect2Verify(const nsresult& result,
341 : const RequestHeaderTuples& changedHeaders)
342 : {
343 0 : if (NS_SUCCEEDED(result)) {
344 : nsCOMPtr<nsIHttpChannel> newHttpChannel =
345 0 : do_QueryInterface(mRedirectChannel);
346 :
347 0 : if (newHttpChannel) {
348 0 : for (PRUint32 i = 0; i < changedHeaders.Length(); i++) {
349 0 : newHttpChannel->SetRequestHeader(changedHeaders[i].mHeader,
350 0 : changedHeaders[i].mValue,
351 0 : changedHeaders[i].mMerge);
352 : }
353 : }
354 : }
355 :
356 0 : if (!mRedirectCallback) {
357 : // Bug 621446 investigation (optimization turned off above)
358 0 : if (mReceivedRedirect2Verify)
359 0 : NS_RUNTIMEABORT("Duplicate fire");
360 0 : if (mSentRedirect1BeginFailed)
361 0 : NS_RUNTIMEABORT("Send to child failed");
362 0 : if (mSentRedirect1Begin && NS_FAILED(result))
363 0 : NS_RUNTIMEABORT("Redirect failed");
364 0 : if (mSentRedirect1Begin && NS_SUCCEEDED(result))
365 0 : NS_RUNTIMEABORT("Redirect succeeded");
366 0 : if (!mRedirectChannel)
367 0 : NS_RUNTIMEABORT("Missing redirect channel");
368 : }
369 :
370 0 : mReceivedRedirect2Verify = true;
371 :
372 0 : mRedirectCallback->OnRedirectVerifyCallback(result);
373 0 : mRedirectCallback = nsnull;
374 0 : return true;
375 : }
376 :
377 : // Bug 621446 investigation
378 : #pragma GCC reset_options
379 :
380 : bool
381 0 : HttpChannelParent::RecvDocumentChannelCleanup()
382 : {
383 : // From now on only using mAssociatedContentSecurity. Free everything else.
384 0 : mChannel = 0; // Reclaim some memory sooner.
385 0 : mCacheDescriptor = 0; // Else we'll block other channels reading same URI
386 0 : return true;
387 : }
388 :
389 : bool
390 0 : HttpChannelParent::RecvMarkOfflineCacheEntryAsForeign()
391 : {
392 0 : nsHttpChannel *httpChan = static_cast<nsHttpChannel *>(mChannel.get());
393 0 : httpChan->MarkOfflineCacheEntryAsForeign();
394 0 : return true;
395 : }
396 :
397 : //-----------------------------------------------------------------------------
398 : // HttpChannelParent::nsIRequestObserver
399 : //-----------------------------------------------------------------------------
400 :
401 : NS_IMETHODIMP
402 0 : HttpChannelParent::OnStartRequest(nsIRequest *aRequest, nsISupports *aContext)
403 : {
404 0 : LOG(("HttpChannelParent::OnStartRequest [this=%x]\n", this));
405 :
406 0 : nsHttpChannel *chan = static_cast<nsHttpChannel *>(aRequest);
407 0 : nsHttpResponseHead *responseHead = chan->GetResponseHead();
408 0 : nsHttpRequestHead *requestHead = chan->GetRequestHead();
409 0 : bool isFromCache = false;
410 0 : chan->IsFromCache(&isFromCache);
411 0 : PRUint32 expirationTime = nsICache::NO_EXPIRATION_TIME;
412 0 : chan->GetCacheTokenExpirationTime(&expirationTime);
413 0 : nsCString cachedCharset;
414 0 : chan->GetCacheTokenCachedCharset(cachedCharset);
415 :
416 : bool loadedFromApplicationCache;
417 0 : chan->GetLoadedFromApplicationCache(&loadedFromApplicationCache);
418 0 : if (loadedFromApplicationCache) {
419 0 : nsCOMPtr<nsIApplicationCache> appCache;
420 0 : chan->GetApplicationCache(getter_AddRefs(appCache));
421 0 : nsCString appCacheGroupId;
422 0 : nsCString appCacheClientId;
423 0 : appCache->GetGroupID(appCacheGroupId);
424 0 : appCache->GetClientID(appCacheClientId);
425 0 : if (mIPCClosed ||
426 0 : !SendAssociateApplicationCache(appCacheGroupId, appCacheClientId))
427 : {
428 0 : return NS_ERROR_UNEXPECTED;
429 : }
430 : }
431 :
432 0 : nsCOMPtr<nsIEncodedChannel> encodedChannel = do_QueryInterface(aRequest);
433 0 : if (encodedChannel)
434 0 : encodedChannel->SetApplyConversion(false);
435 :
436 : // Keep the cache entry for future use in RecvSetCacheTokenCachedCharset().
437 : // It could be already released by nsHttpChannel at that time.
438 0 : chan->GetCacheToken(getter_AddRefs(mCacheDescriptor));
439 :
440 0 : nsCString secInfoSerialization;
441 0 : nsCOMPtr<nsISupports> secInfoSupp;
442 0 : chan->GetSecurityInfo(getter_AddRefs(secInfoSupp));
443 0 : if (secInfoSupp) {
444 0 : mAssociatedContentSecurity = do_QueryInterface(secInfoSupp);
445 0 : nsCOMPtr<nsISerializable> secInfoSer = do_QueryInterface(secInfoSupp);
446 0 : if (secInfoSer)
447 0 : NS_SerializeToString(secInfoSer, secInfoSerialization);
448 : }
449 :
450 0 : nsHttpChannel *httpChan = static_cast<nsHttpChannel *>(mChannel.get());
451 0 : if (mIPCClosed ||
452 0 : !SendOnStartRequest(responseHead ? *responseHead : nsHttpResponseHead(),
453 0 : !!responseHead,
454 0 : requestHead->Headers(),
455 : isFromCache,
456 0 : mCacheDescriptor ? true : false,
457 : expirationTime, cachedCharset, secInfoSerialization,
458 0 : httpChan->GetSelfAddr(), httpChan->GetPeerAddr()))
459 : {
460 0 : return NS_ERROR_UNEXPECTED;
461 : }
462 0 : return NS_OK;
463 : }
464 :
465 : NS_IMETHODIMP
466 0 : HttpChannelParent::OnStopRequest(nsIRequest *aRequest,
467 : nsISupports *aContext,
468 : nsresult aStatusCode)
469 : {
470 0 : LOG(("HttpChannelParent::OnStopRequest: [this=%x status=%ul]\n",
471 : this, aStatusCode));
472 :
473 0 : if (mIPCClosed || !SendOnStopRequest(aStatusCode))
474 0 : return NS_ERROR_UNEXPECTED;
475 0 : return NS_OK;
476 : }
477 :
478 : //-----------------------------------------------------------------------------
479 : // HttpChannelParent::nsIStreamListener
480 : //-----------------------------------------------------------------------------
481 :
482 : NS_IMETHODIMP
483 0 : HttpChannelParent::OnDataAvailable(nsIRequest *aRequest,
484 : nsISupports *aContext,
485 : nsIInputStream *aInputStream,
486 : PRUint32 aOffset,
487 : PRUint32 aCount)
488 : {
489 0 : LOG(("HttpChannelParent::OnDataAvailable [this=%x]\n", this));
490 :
491 0 : nsCString data;
492 0 : nsresult rv = NS_ReadInputStreamToString(aInputStream, data, aCount);
493 0 : if (NS_FAILED(rv))
494 0 : return rv;
495 :
496 : // OnDataAvailable is always preceded by OnStatus/OnProgress calls that set
497 : // mStoredStatus/mStoredProgress(Max) to appropriate values, unless
498 : // LOAD_BACKGROUND set. In that case, they'll have garbage values, but
499 : // child doesn't use them.
500 0 : if (mIPCClosed || !SendOnTransportAndData(mStoredStatus, mStoredProgress,
501 : mStoredProgressMax, data, aOffset,
502 0 : aCount)) {
503 0 : return NS_ERROR_UNEXPECTED;
504 : }
505 0 : return NS_OK;
506 : }
507 :
508 : //-----------------------------------------------------------------------------
509 : // HttpChannelParent::nsIProgressEventSink
510 : //-----------------------------------------------------------------------------
511 :
512 : NS_IMETHODIMP
513 0 : HttpChannelParent::OnProgress(nsIRequest *aRequest,
514 : nsISupports *aContext,
515 : PRUint64 aProgress,
516 : PRUint64 aProgressMax)
517 : {
518 : // OnStatus has always just set mStoredStatus. If it indicates this precedes
519 : // OnDataAvailable, store and ODA will send to child.
520 0 : if (mStoredStatus == nsISocketTransport::STATUS_RECEIVING_FROM ||
521 : mStoredStatus == nsITransport::STATUS_READING)
522 : {
523 0 : mStoredProgress = aProgress;
524 0 : mStoredProgressMax = aProgressMax;
525 : } else {
526 : // Send to child now. The only case I've observed that this handles (i.e.
527 : // non-ODA status with progress > 0) is data upload progress notification
528 : // (status == nsISocketTransport::STATUS_SENDING_TO)
529 0 : if (mIPCClosed || !SendOnProgress(aProgress, aProgressMax))
530 0 : return NS_ERROR_UNEXPECTED;
531 : }
532 :
533 0 : return NS_OK;
534 : }
535 :
536 : NS_IMETHODIMP
537 0 : HttpChannelParent::OnStatus(nsIRequest *aRequest,
538 : nsISupports *aContext,
539 : nsresult aStatus,
540 : const PRUnichar *aStatusArg)
541 : {
542 : // If this precedes OnDataAvailable, store and ODA will send to child.
543 0 : if (aStatus == nsISocketTransport::STATUS_RECEIVING_FROM ||
544 : aStatus == nsITransport::STATUS_READING)
545 : {
546 0 : mStoredStatus = aStatus;
547 0 : return NS_OK;
548 : }
549 : // Otherwise, send to child now
550 0 : if (mIPCClosed || !SendOnStatus(aStatus))
551 0 : return NS_ERROR_UNEXPECTED;
552 0 : return NS_OK;
553 : }
554 :
555 : //-----------------------------------------------------------------------------
556 : // HttpChannelParent::nsIParentChannel
557 : //-----------------------------------------------------------------------------
558 :
559 : NS_IMETHODIMP
560 0 : HttpChannelParent::Delete()
561 : {
562 0 : if (!mIPCClosed)
563 0 : unused << SendDeleteSelf();
564 :
565 0 : return NS_OK;
566 : }
567 :
568 : //-----------------------------------------------------------------------------
569 : // HttpChannelParent::nsIParentRedirectingChannel
570 : //-----------------------------------------------------------------------------
571 :
572 : NS_IMETHODIMP
573 0 : HttpChannelParent::StartRedirect(PRUint32 newChannelId,
574 : nsIChannel* newChannel,
575 : PRUint32 redirectFlags,
576 : nsIAsyncVerifyRedirectCallback* callback)
577 : {
578 0 : if (mIPCClosed)
579 0 : return NS_BINDING_ABORTED;
580 :
581 0 : nsCOMPtr<nsIURI> newURI;
582 0 : newChannel->GetURI(getter_AddRefs(newURI));
583 :
584 0 : nsHttpChannel *httpChan = static_cast<nsHttpChannel *>(mChannel.get());
585 0 : nsHttpResponseHead *responseHead = httpChan->GetResponseHead();
586 : bool result = SendRedirect1Begin(newChannelId,
587 0 : IPC::URI(newURI),
588 : redirectFlags,
589 : responseHead ? *responseHead
590 0 : : nsHttpResponseHead());
591 0 : if (!result) {
592 : // Bug 621446 investigation
593 0 : mSentRedirect1BeginFailed = true;
594 0 : return NS_BINDING_ABORTED;
595 : }
596 :
597 : // Bug 621446 investigation
598 0 : mSentRedirect1Begin = true;
599 :
600 : // Result is handled in RecvRedirect2Verify above
601 :
602 0 : mRedirectChannel = newChannel;
603 0 : mRedirectCallback = callback;
604 0 : return NS_OK;
605 : }
606 :
607 : NS_IMETHODIMP
608 0 : HttpChannelParent::CompleteRedirect(bool succeeded)
609 : {
610 0 : if (succeeded && !mIPCClosed) {
611 : // TODO: check return value: assume child dead if failed
612 0 : unused << SendRedirect3Complete();
613 : }
614 :
615 0 : mRedirectChannel = nsnull;
616 0 : return NS_OK;
617 : }
618 :
619 : }} // mozilla::net
|