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 : * Honza Bambas <honzab@firemni.cz>
27 : *
28 : * Alternatively, the contents of this file may be used under the terms of
29 : * either the GNU General Public License Version 2 or later (the "GPL"), or
30 : * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
31 : * in which case the provisions of the GPL or the LGPL are applicable instead
32 : * of those above. If you wish to allow use of your version of this file only
33 : * under the terms of either the GPL or the LGPL, and not to allow others to
34 : * use your version of this file under the terms of the MPL, indicate your
35 : * decision by deleting the provisions above and replace them with the notice
36 : * and other provisions required by the GPL or the LGPL. If you do not delete
37 : * the provisions above, a recipient may use your version of this file under
38 : * the terms of any one of the MPL, the GPL or the LGPL.
39 : *
40 : * ***** END LICENSE BLOCK ***** */
41 :
42 : #include "HttpChannelParentListener.h"
43 : #include "mozilla/net/HttpChannelParent.h"
44 : #include "mozilla/dom/TabParent.h"
45 : #include "mozilla/net/NeckoParent.h"
46 : #include "mozilla/unused.h"
47 : #include "nsHttpChannel.h"
48 : #include "nsHttpHandler.h"
49 : #include "nsNetUtil.h"
50 : #include "nsISupportsPriority.h"
51 : #include "nsIAuthPromptProvider.h"
52 : #include "nsIDocShellTreeItem.h"
53 : #include "nsIBadCertListener2.h"
54 : #include "nsICacheEntryDescriptor.h"
55 : #include "nsSerializationHelper.h"
56 : #include "nsISerializable.h"
57 : #include "nsIAssociatedContentSecurity.h"
58 : #include "nsISecureBrowserUI.h"
59 : #include "nsIRedirectChannelRegistrar.h"
60 :
61 : #include "nsIFTPChannel.h"
62 :
63 : using mozilla::unused;
64 :
65 : namespace mozilla {
66 : namespace net {
67 :
68 0 : HttpChannelParentListener::HttpChannelParentListener(HttpChannelParent* aInitialChannel)
69 : : mActiveChannel(aInitialChannel)
70 0 : , mRedirectChannelId(0)
71 : {
72 0 : }
73 :
74 0 : HttpChannelParentListener::~HttpChannelParentListener()
75 : {
76 0 : }
77 :
78 : //-----------------------------------------------------------------------------
79 : // HttpChannelParentListener::nsISupports
80 : //-----------------------------------------------------------------------------
81 :
82 0 : NS_IMPL_ISUPPORTS5(HttpChannelParentListener,
83 : nsIInterfaceRequestor,
84 : nsIStreamListener,
85 : nsIRequestObserver,
86 : nsIChannelEventSink,
87 : nsIRedirectResultListener)
88 :
89 : //-----------------------------------------------------------------------------
90 : // HttpChannelParentListener::nsIRequestObserver
91 : //-----------------------------------------------------------------------------
92 :
93 : NS_IMETHODIMP
94 0 : HttpChannelParentListener::OnStartRequest(nsIRequest *aRequest, nsISupports *aContext)
95 : {
96 0 : if (!mActiveChannel)
97 0 : return NS_ERROR_UNEXPECTED;
98 :
99 0 : LOG(("HttpChannelParentListener::OnStartRequest [this=%x]\n", this));
100 0 : return mActiveChannel->OnStartRequest(aRequest, aContext);
101 : }
102 :
103 : NS_IMETHODIMP
104 0 : HttpChannelParentListener::OnStopRequest(nsIRequest *aRequest,
105 : nsISupports *aContext,
106 : nsresult aStatusCode)
107 : {
108 0 : if (!mActiveChannel)
109 0 : return NS_ERROR_UNEXPECTED;
110 :
111 0 : LOG(("HttpChannelParentListener::OnStopRequest: [this=%x status=%ul]\n",
112 : this, aStatusCode));
113 0 : nsresult rv = mActiveChannel->OnStopRequest(aRequest, aContext, aStatusCode);
114 :
115 0 : mActiveChannel = nsnull;
116 0 : return rv;
117 : }
118 :
119 : //-----------------------------------------------------------------------------
120 : // HttpChannelParentListener::nsIStreamListener
121 : //-----------------------------------------------------------------------------
122 :
123 : NS_IMETHODIMP
124 0 : HttpChannelParentListener::OnDataAvailable(nsIRequest *aRequest,
125 : nsISupports *aContext,
126 : nsIInputStream *aInputStream,
127 : PRUint32 aOffset,
128 : PRUint32 aCount)
129 : {
130 0 : if (!mActiveChannel)
131 0 : return NS_ERROR_UNEXPECTED;
132 :
133 0 : LOG(("HttpChannelParentListener::OnDataAvailable [this=%x]\n", this));
134 0 : return mActiveChannel->OnDataAvailable(aRequest, aContext, aInputStream, aOffset, aCount);
135 : }
136 :
137 : //-----------------------------------------------------------------------------
138 : // HttpChannelParentListener::nsIInterfaceRequestor
139 : //-----------------------------------------------------------------------------
140 :
141 : NS_IMETHODIMP
142 0 : HttpChannelParentListener::GetInterface(const nsIID& aIID, void **result)
143 : {
144 0 : if (aIID.Equals(NS_GET_IID(nsIChannelEventSink)) ||
145 0 : aIID.Equals(NS_GET_IID(nsIHttpEventSink)) ||
146 0 : aIID.Equals(NS_GET_IID(nsIRedirectResultListener)))
147 : {
148 0 : return QueryInterface(aIID, result);
149 : }
150 :
151 0 : nsCOMPtr<nsIInterfaceRequestor> ir;
152 0 : if (mActiveChannel &&
153 0 : NS_SUCCEEDED(CallQueryInterface(mActiveChannel.get(),
154 : getter_AddRefs(ir))))
155 : {
156 0 : return ir->GetInterface(aIID, result);
157 : }
158 :
159 0 : return NS_NOINTERFACE;
160 : }
161 :
162 : //-----------------------------------------------------------------------------
163 : // HttpChannelParentListener::nsIChannelEventSink
164 : //-----------------------------------------------------------------------------
165 :
166 : NS_IMETHODIMP
167 0 : HttpChannelParentListener::AsyncOnChannelRedirect(
168 : nsIChannel *oldChannel,
169 : nsIChannel *newChannel,
170 : PRUint32 redirectFlags,
171 : nsIAsyncVerifyRedirectCallback* callback)
172 : {
173 : nsresult rv;
174 :
175 : // Register the new channel and obtain id for it
176 : nsCOMPtr<nsIRedirectChannelRegistrar> registrar =
177 0 : do_GetService("@mozilla.org/redirectchannelregistrar;1", &rv);
178 0 : NS_ENSURE_SUCCESS(rv, rv);
179 :
180 0 : rv = registrar->RegisterChannel(newChannel, &mRedirectChannelId);
181 0 : NS_ENSURE_SUCCESS(rv, rv);
182 :
183 0 : LOG(("Registered %p channel under id=%d", newChannel, mRedirectChannelId));
184 :
185 : nsCOMPtr<nsIParentRedirectingChannel> activeRedirectingChannel =
186 0 : do_QueryInterface(mActiveChannel);
187 0 : if (!activeRedirectingChannel) {
188 : NS_RUNTIMEABORT("Channel got a redirect response, but doesn't implement "
189 0 : "nsIParentRedirectingChannel to handle it.");
190 : }
191 :
192 0 : return activeRedirectingChannel->StartRedirect(mRedirectChannelId,
193 : newChannel,
194 : redirectFlags,
195 0 : callback);
196 : }
197 :
198 : //-----------------------------------------------------------------------------
199 : // HttpChannelParentListener::nsIRedirectResultListener
200 : //-----------------------------------------------------------------------------
201 :
202 : NS_IMETHODIMP
203 0 : HttpChannelParentListener::OnRedirectResult(bool succeeded)
204 : {
205 : nsresult rv;
206 :
207 0 : nsCOMPtr<nsIParentChannel> redirectChannel;
208 0 : if (mRedirectChannelId) {
209 : nsCOMPtr<nsIRedirectChannelRegistrar> registrar =
210 0 : do_GetService("@mozilla.org/redirectchannelregistrar;1", &rv);
211 0 : NS_ENSURE_SUCCESS(rv, rv);
212 :
213 0 : rv = registrar->GetParentChannel(mRedirectChannelId,
214 0 : getter_AddRefs(redirectChannel));
215 0 : if (NS_FAILED(rv) || !redirectChannel) {
216 : // Redirect might get canceled before we got AsyncOnChannelRedirect
217 0 : LOG(("Registered parent channel not found under id=%d", mRedirectChannelId));
218 :
219 0 : nsCOMPtr<nsIChannel> newChannel;
220 0 : rv = registrar->GetRegisteredChannel(mRedirectChannelId,
221 0 : getter_AddRefs(newChannel));
222 0 : NS_ASSERTION(newChannel, "Already registered channel not found");
223 :
224 0 : if (NS_SUCCEEDED(rv))
225 0 : newChannel->Cancel(NS_BINDING_ABORTED);
226 : }
227 :
228 : // Release all previously registered channels, they are no longer need to be
229 : // kept in the registrar from this moment.
230 0 : registrar->DeregisterChannels(mRedirectChannelId);
231 :
232 0 : mRedirectChannelId = 0;
233 : }
234 :
235 : nsCOMPtr<nsIParentRedirectingChannel> activeRedirectingChannel =
236 0 : do_QueryInterface(mActiveChannel);
237 0 : NS_ABORT_IF_FALSE(activeRedirectingChannel,
238 : "Channel finished a redirect response, but doesn't implement "
239 : "nsIParentRedirectingChannel to complete it.");
240 :
241 0 : activeRedirectingChannel->CompleteRedirect(succeeded);
242 :
243 0 : if (succeeded) {
244 : // Switch to redirect channel and delete the old one.
245 0 : mActiveChannel->Delete();
246 0 : mActiveChannel = redirectChannel;
247 0 : } else if (redirectChannel) {
248 : // Delete the redirect target channel: continue using old channel
249 0 : redirectChannel->Delete();
250 : }
251 :
252 0 : return NS_OK;
253 : }
254 :
255 : }} // mozilla::net
|