|
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
|
2 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
3 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
5 |
|
6 #include "TestCommon.h" |
|
7 #include <stdio.h> |
|
8 #ifdef WIN32 |
|
9 #include <windows.h> |
|
10 #endif |
|
11 #include "nspr.h" |
|
12 #include "nscore.h" |
|
13 #include "nsCOMPtr.h" |
|
14 #include "nsIIOService.h" |
|
15 #include "nsIServiceManager.h" |
|
16 #include "nsIStreamListener.h" |
|
17 #include "nsIInputStream.h" |
|
18 #include "nsIChannel.h" |
|
19 #include "nsIURL.h" |
|
20 #include "nsIInterfaceRequestor.h" |
|
21 #include "nsIInterfaceRequestorUtils.h" |
|
22 #include "nsIDNSService.h" |
|
23 #include "mozilla/Attributes.h" |
|
24 |
|
25 #include "nsISimpleEnumerator.h" |
|
26 #include "nsNetUtil.h" |
|
27 #include "nsStringAPI.h" |
|
28 |
|
29 static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID); |
|
30 |
|
31 static bool gError = false; |
|
32 static int32_t gKeepRunning = 0; |
|
33 |
|
34 #define NS_IEQUALS_IID \ |
|
35 { 0x11c5c8ee, 0x1dd2, 0x11b2, \ |
|
36 { 0xa8, 0x93, 0xbb, 0x23, 0xa1, 0xb6, 0x27, 0x76 }} |
|
37 |
|
38 class nsIEquals : public nsISupports { |
|
39 public: |
|
40 NS_DECLARE_STATIC_IID_ACCESSOR(NS_IEQUALS_IID) |
|
41 NS_IMETHOD Equals(void *aPtr, bool *_retval) = 0; |
|
42 }; |
|
43 |
|
44 NS_DEFINE_STATIC_IID_ACCESSOR(nsIEquals, NS_IEQUALS_IID) |
|
45 |
|
46 class ConsumerContext MOZ_FINAL : public nsIEquals { |
|
47 public: |
|
48 NS_DECL_THREADSAFE_ISUPPORTS |
|
49 |
|
50 ConsumerContext() { } |
|
51 |
|
52 NS_IMETHOD Equals(void *aPtr, bool *_retval) { |
|
53 *_retval = true; |
|
54 if (aPtr != this) *_retval = false; |
|
55 return NS_OK; |
|
56 } |
|
57 }; |
|
58 |
|
59 NS_IMPL_ISUPPORTS(ConsumerContext, nsIEquals) |
|
60 |
|
61 class Consumer : public nsIStreamListener { |
|
62 public: |
|
63 NS_DECL_THREADSAFE_ISUPPORTS |
|
64 NS_DECL_NSIREQUESTOBSERVER |
|
65 NS_DECL_NSISTREAMLISTENER |
|
66 |
|
67 Consumer(); |
|
68 virtual ~Consumer(); |
|
69 nsresult Init(nsIURI *aURI, nsIChannel *aChannel, nsISupports *aContext); |
|
70 nsresult Validate(nsIRequest *request, nsISupports *aContext); |
|
71 |
|
72 // member data |
|
73 bool mOnStart; // have we received an OnStart? |
|
74 bool mOnStop; // have we received an onStop? |
|
75 int32_t mOnDataCount; // number of times OnData was called. |
|
76 nsCOMPtr<nsIURI> mURI; |
|
77 nsCOMPtr<nsIChannel> mChannel; |
|
78 nsCOMPtr<nsIEquals> mContext; |
|
79 }; |
|
80 |
|
81 // nsISupports implementation |
|
82 NS_IMPL_ISUPPORTS(Consumer, nsIStreamListener, nsIRequestObserver) |
|
83 |
|
84 |
|
85 // nsIRequestObserver implementation |
|
86 NS_IMETHODIMP |
|
87 Consumer::OnStartRequest(nsIRequest *request, nsISupports* aContext) { |
|
88 fprintf(stderr, "Consumer::OnStart() -> in\n\n"); |
|
89 |
|
90 if (mOnStart) { |
|
91 fprintf(stderr, "INFO: multiple OnStarts received\n"); |
|
92 } |
|
93 mOnStart = true; |
|
94 |
|
95 nsresult rv = Validate(request, aContext); |
|
96 if (NS_FAILED(rv)) return rv; |
|
97 |
|
98 fprintf(stderr, "Consumer::OnStart() -> out\n\n"); |
|
99 return rv; |
|
100 } |
|
101 |
|
102 NS_IMETHODIMP |
|
103 Consumer::OnStopRequest(nsIRequest *request, nsISupports *aContext, |
|
104 nsresult aStatus) { |
|
105 fprintf(stderr, "Consumer::OnStop() -> in\n\n"); |
|
106 |
|
107 if (!mOnStart) { |
|
108 gError = true; |
|
109 fprintf(stderr, "ERROR: No OnStart received\n"); |
|
110 } |
|
111 |
|
112 if (mOnStop) { |
|
113 fprintf(stderr, "INFO: multiple OnStops received\n"); |
|
114 } |
|
115 |
|
116 fprintf(stderr, "INFO: received %d OnData()s\n", mOnDataCount); |
|
117 |
|
118 mOnStop = true; |
|
119 |
|
120 nsresult rv = Validate(request, aContext); |
|
121 if (NS_FAILED(rv)) return rv; |
|
122 |
|
123 fprintf(stderr, "Consumer::OnStop() -> out\n\n"); |
|
124 return rv; |
|
125 } |
|
126 |
|
127 |
|
128 // nsIStreamListener implementation |
|
129 NS_IMETHODIMP |
|
130 Consumer::OnDataAvailable(nsIRequest *request, nsISupports *aContext, |
|
131 nsIInputStream *aIStream, |
|
132 uint64_t aOffset, uint32_t aLength) { |
|
133 fprintf(stderr, "Consumer::OnData() -> in\n\n"); |
|
134 |
|
135 if (!mOnStart) { |
|
136 gError = true; |
|
137 fprintf(stderr, "ERROR: No OnStart received\n"); |
|
138 } |
|
139 |
|
140 mOnDataCount += 1; |
|
141 |
|
142 nsresult rv = Validate(request, aContext); |
|
143 if (NS_FAILED(rv)) return rv; |
|
144 |
|
145 fprintf(stderr, "Consumer::OnData() -> out\n\n"); |
|
146 return rv; |
|
147 } |
|
148 |
|
149 // Consumer implementation |
|
150 Consumer::Consumer() { |
|
151 mOnStart = mOnStop = false; |
|
152 mOnDataCount = 0; |
|
153 gKeepRunning++; |
|
154 } |
|
155 |
|
156 Consumer::~Consumer() { |
|
157 fprintf(stderr, "Consumer::~Consumer -> in\n\n"); |
|
158 |
|
159 if (!mOnStart) { |
|
160 gError = true; |
|
161 fprintf(stderr, "ERROR: Never got an OnStart\n"); |
|
162 } |
|
163 |
|
164 if (!mOnStop) { |
|
165 gError = true; |
|
166 fprintf(stderr, "ERROR: Never got an OnStop \n"); |
|
167 } |
|
168 |
|
169 fprintf(stderr, "Consumer::~Consumer -> out\n\n"); |
|
170 if (--gKeepRunning == 0) |
|
171 QuitPumpingEvents(); |
|
172 } |
|
173 |
|
174 nsresult |
|
175 Consumer::Init(nsIURI *aURI, nsIChannel* aChannel, nsISupports *aContext) { |
|
176 mURI = aURI; |
|
177 mChannel = aChannel; |
|
178 mContext = do_QueryInterface(aContext); |
|
179 return NS_OK; |
|
180 } |
|
181 |
|
182 nsresult |
|
183 Consumer::Validate(nsIRequest* request, nsISupports *aContext) { |
|
184 nsresult rv = NS_OK; |
|
185 nsCOMPtr<nsIURI> uri; |
|
186 nsCOMPtr<nsIChannel> aChannel = do_QueryInterface(request); |
|
187 |
|
188 rv = aChannel->GetURI(getter_AddRefs(uri)); |
|
189 if (NS_FAILED(rv)) return rv; |
|
190 |
|
191 bool same = false; |
|
192 |
|
193 rv = mURI->Equals(uri, &same); |
|
194 if (NS_FAILED(rv)) return rv; |
|
195 |
|
196 if (!same) |
|
197 fprintf(stderr, "INFO: URIs do not match\n"); |
|
198 |
|
199 rv = mContext->Equals((void*)aContext, &same); |
|
200 if (NS_FAILED(rv)) return rv; |
|
201 |
|
202 if (!same) { |
|
203 gError = true; |
|
204 fprintf(stderr, "ERROR: Contexts do not match\n"); |
|
205 } |
|
206 return rv; |
|
207 } |
|
208 |
|
209 nsresult StartLoad(const char *); |
|
210 |
|
211 int main(int argc, char *argv[]) { |
|
212 if (test_common_init(&argc, &argv) != 0) |
|
213 return -1; |
|
214 |
|
215 nsresult rv = NS_OK; |
|
216 bool cmdLineURL = false; |
|
217 |
|
218 if (argc > 1) { |
|
219 // run in signle url mode |
|
220 cmdLineURL = true; |
|
221 } |
|
222 |
|
223 rv = NS_InitXPCOM2(nullptr, nullptr, nullptr); |
|
224 if (NS_FAILED(rv)) return -1; |
|
225 |
|
226 if (cmdLineURL) { |
|
227 rv = StartLoad(argv[1]); |
|
228 } else { |
|
229 rv = StartLoad("http://badhostnamexyz/test.txt"); |
|
230 } |
|
231 if (NS_FAILED(rv)) return -1; |
|
232 |
|
233 // Enter the message pump to allow the URL load to proceed. |
|
234 PumpEvents(); |
|
235 |
|
236 NS_ShutdownXPCOM(nullptr); |
|
237 if (gError) { |
|
238 fprintf(stderr, "\n\n-------ERROR-------\n\n"); |
|
239 } |
|
240 return 0; |
|
241 } |
|
242 |
|
243 nsresult StartLoad(const char *aURISpec) { |
|
244 nsresult rv = NS_OK; |
|
245 |
|
246 // create a context |
|
247 ConsumerContext *context = new ConsumerContext; |
|
248 nsCOMPtr<nsISupports> contextSup = do_QueryInterface(context, &rv); |
|
249 if (NS_FAILED(rv)) return rv; |
|
250 |
|
251 |
|
252 nsCOMPtr<nsIIOService> serv = do_GetService(kIOServiceCID, &rv); |
|
253 if (NS_FAILED(rv)) return rv; |
|
254 |
|
255 // create a uri |
|
256 nsCOMPtr<nsIURI> uri; |
|
257 rv = NS_NewURI(getter_AddRefs(uri), aURISpec); |
|
258 if (NS_FAILED(rv)) return rv; |
|
259 |
|
260 // create a channel |
|
261 nsCOMPtr<nsIChannel> channel; |
|
262 rv = serv->NewChannelFromURI(uri, getter_AddRefs(channel)); |
|
263 if (NS_FAILED(rv)) return rv; |
|
264 |
|
265 Consumer *consumer = new Consumer; |
|
266 rv = consumer->Init(uri, channel, contextSup); |
|
267 if (NS_FAILED(rv)) return rv; |
|
268 |
|
269 // kick off the load |
|
270 nsCOMPtr<nsIRequest> request; |
|
271 return channel->AsyncOpen(static_cast<nsIStreamListener*>(consumer), contextSup); |
|
272 } |