|
1 /* -*- Mode: C++; tab-width: 4; 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 "nsNetUtil.h" |
|
8 #include "nsIServiceManager.h" |
|
9 #include "nsIInterfaceRequestor.h" |
|
10 #include "nsIInterfaceRequestorUtils.h" |
|
11 #include "nsIProgressEventSink.h" |
|
12 #include "nsIComponentManager.h" |
|
13 #include "prprf.h" |
|
14 #include "nsXPCOM.h" |
|
15 #include "nsISupportsPrimitives.h" |
|
16 #include "plstr.h" |
|
17 #include "nsCOMArray.h" |
|
18 #include "nsIComponentRegistrar.h" |
|
19 #include <algorithm> |
|
20 |
|
21 namespace TestPageLoad { |
|
22 |
|
23 int getStrLine(const char *src, char *str, int ind, int max); |
|
24 nsresult auxLoad(char *uriBuf); |
|
25 //---------------------------------------------------------------------- |
|
26 |
|
27 |
|
28 #define RETURN_IF_FAILED(rv, ret, step) \ |
|
29 PR_BEGIN_MACRO \ |
|
30 if (NS_FAILED(rv)) { \ |
|
31 printf(">>> %s failed: rv=%x\n", step, static_cast<uint32_t>(rv)); \ |
|
32 return ret;\ |
|
33 } \ |
|
34 PR_END_MACRO |
|
35 |
|
36 static nsCString globalStream; |
|
37 //static char urlBuf[256]; |
|
38 static nsCOMPtr<nsIURI> baseURI; |
|
39 static nsCOMArray<nsIURI> uriList; |
|
40 |
|
41 //Temp, should remove: |
|
42 static int numStart=0; |
|
43 static int numFound=0; |
|
44 |
|
45 static int32_t gKeepRunning = 0; |
|
46 |
|
47 |
|
48 //--------writer fun---------------------- |
|
49 |
|
50 static NS_METHOD streamParse (nsIInputStream* in, |
|
51 void* closure, |
|
52 const char* fromRawSegment, |
|
53 uint32_t toOffset, |
|
54 uint32_t count, |
|
55 uint32_t *writeCount) { |
|
56 |
|
57 char parseBuf[2048], loc[2048], lineBuf[2048]; |
|
58 char *loc_t, *loc_t2; |
|
59 int i = 0; |
|
60 const char *tmp; |
|
61 |
|
62 if(!globalStream.IsEmpty()) { |
|
63 globalStream.Append(fromRawSegment); |
|
64 tmp = globalStream.get(); |
|
65 //printf("\n>>NOW:\n^^^^^\n%s\n^^^^^^^^^^^^^^", tmp); |
|
66 } else { |
|
67 tmp = fromRawSegment; |
|
68 } |
|
69 |
|
70 while(i < (int)count) { |
|
71 i = getStrLine(tmp, lineBuf, i, count); |
|
72 if(i < 0) { |
|
73 *writeCount = count; |
|
74 return NS_OK; |
|
75 } |
|
76 parseBuf[0]='\0'; |
|
77 if((loc_t=PL_strcasestr(lineBuf, "img"))!= nullptr |
|
78 || (loc_t=PL_strcasestr(lineBuf, "script"))!=nullptr) { |
|
79 loc_t2=PL_strcasestr(loc_t, "src"); |
|
80 if(loc_t2!=nullptr) { |
|
81 loc_t2+=3; |
|
82 strcpy(loc, loc_t2); |
|
83 sscanf(loc, "=\"%[^\"]", parseBuf); |
|
84 if(parseBuf[0]=='\0') |
|
85 sscanf(loc, "=%s", parseBuf); |
|
86 if(parseBuf[0]!='\0'){ |
|
87 numFound++; |
|
88 auxLoad(parseBuf); |
|
89 } |
|
90 } |
|
91 } |
|
92 |
|
93 /***NEED BETTER CHECK FOR STYLESHEETS |
|
94 if((loc_t=PL_strcasestr(lineBuf, "link"))!= nullptr) { |
|
95 loc_t2=PL_strcasestr(loc_t, "href"); |
|
96 if(loc_t2!=nullptr) { |
|
97 loc_t2+=4; |
|
98 strcpy(loc, loc_t2); |
|
99 //printf("%s\n", loc); |
|
100 sscanf(loc, "=\"%[^\"]", parseBuf); |
|
101 if(parseBuf[0]!='\0'){ |
|
102 //printf("%s\n", parseBuf); |
|
103 numFound++; |
|
104 auxLoad(parseBuf); |
|
105 } |
|
106 } |
|
107 } |
|
108 */ |
|
109 if((loc_t=PL_strcasestr(lineBuf, "background"))!=nullptr) { |
|
110 loc_t+=10; |
|
111 strcpy(loc, loc_t); |
|
112 sscanf(loc, "=\"%[^\"]", parseBuf); |
|
113 if(parseBuf[0]!='\0') { |
|
114 numFound++; |
|
115 auxLoad(parseBuf); |
|
116 } |
|
117 } |
|
118 i++; |
|
119 |
|
120 } |
|
121 *writeCount = count; |
|
122 return NS_OK; |
|
123 } |
|
124 |
|
125 //----------------------------------------------------------------------------- |
|
126 // nsIStreamListener implementation |
|
127 //----------------------------------------------------------------------------- |
|
128 |
|
129 class MyListener : public nsIStreamListener |
|
130 { |
|
131 public: |
|
132 NS_DECL_ISUPPORTS |
|
133 NS_DECL_NSIREQUESTOBSERVER |
|
134 NS_DECL_NSISTREAMLISTENER |
|
135 |
|
136 MyListener() { } |
|
137 virtual ~MyListener() {} |
|
138 }; |
|
139 |
|
140 NS_IMPL_ISUPPORTS(MyListener, |
|
141 nsIRequestObserver, |
|
142 nsIStreamListener) |
|
143 |
|
144 NS_IMETHODIMP |
|
145 MyListener::OnStartRequest(nsIRequest *req, nsISupports *ctxt) |
|
146 { |
|
147 //printf(">>> OnStartRequest\n"); |
|
148 numStart++; |
|
149 return NS_OK; |
|
150 } |
|
151 |
|
152 NS_IMETHODIMP |
|
153 MyListener::OnStopRequest(nsIRequest *req, nsISupports *ctxt, nsresult status) |
|
154 { |
|
155 //printf(">>> OnStopRequest status=%x\n", status); |
|
156 if (--gKeepRunning == 0) |
|
157 QuitPumpingEvents(); |
|
158 return NS_OK; |
|
159 } |
|
160 |
|
161 NS_IMETHODIMP |
|
162 MyListener::OnDataAvailable(nsIRequest *req, nsISupports *ctxt, |
|
163 nsIInputStream *stream, |
|
164 uint64_t offset, uint32_t count) |
|
165 { |
|
166 //printf(">>> OnDataAvailable [count=%u]\n", count); |
|
167 nsresult rv = NS_ERROR_FAILURE; |
|
168 uint32_t bytesRead=0; |
|
169 char buf[1024]; |
|
170 |
|
171 if(ctxt == nullptr) { |
|
172 bytesRead=0; |
|
173 rv = stream->ReadSegments(streamParse, nullptr, count, &bytesRead); |
|
174 } else { |
|
175 while (count) { |
|
176 uint32_t amount = std::min<uint32_t>(count, sizeof(buf)); |
|
177 rv = stream->Read(buf, amount, &bytesRead); |
|
178 count -= bytesRead; |
|
179 } |
|
180 } |
|
181 |
|
182 if (NS_FAILED(rv)) { |
|
183 printf(">>> stream->Read failed with rv=%x\n", |
|
184 static_cast<uint32_t>(rv)); |
|
185 return rv; |
|
186 } |
|
187 |
|
188 return NS_OK; |
|
189 } |
|
190 |
|
191 //----------------------------------------------------------------------------- |
|
192 // NotificationCallbacks implementation |
|
193 //----------------------------------------------------------------------------- |
|
194 |
|
195 class MyNotifications : public nsIInterfaceRequestor |
|
196 , public nsIProgressEventSink |
|
197 { |
|
198 public: |
|
199 NS_DECL_THREADSAFE_ISUPPORTS |
|
200 NS_DECL_NSIINTERFACEREQUESTOR |
|
201 NS_DECL_NSIPROGRESSEVENTSINK |
|
202 |
|
203 MyNotifications() { } |
|
204 virtual ~MyNotifications() {} |
|
205 }; |
|
206 |
|
207 NS_IMPL_ISUPPORTS(MyNotifications, |
|
208 nsIInterfaceRequestor, |
|
209 nsIProgressEventSink) |
|
210 |
|
211 NS_IMETHODIMP |
|
212 MyNotifications::GetInterface(const nsIID &iid, void **result) |
|
213 { |
|
214 return QueryInterface(iid, result); |
|
215 } |
|
216 |
|
217 NS_IMETHODIMP |
|
218 MyNotifications::OnStatus(nsIRequest *req, nsISupports *ctx, |
|
219 nsresult status, const char16_t *statusText) |
|
220 { |
|
221 //printf("status: %x\n", status); |
|
222 return NS_OK; |
|
223 } |
|
224 |
|
225 NS_IMETHODIMP |
|
226 MyNotifications::OnProgress(nsIRequest *req, nsISupports *ctx, |
|
227 uint64_t progress, uint64_t progressMax) |
|
228 { |
|
229 // char buf[100]; |
|
230 // PR_snprintf(buf, sizeof(buf), "%llu/%llu\n", progress, progressMax); |
|
231 // printf("%s", buf); |
|
232 return NS_OK; |
|
233 } |
|
234 |
|
235 //----------------------------------------------------------------------------- |
|
236 // main, etc.. |
|
237 //----------------------------------------------------------------------------- |
|
238 |
|
239 //---------getStrLine Helper function--------------- |
|
240 //Finds a newline in src starting at ind. Puts the |
|
241 //line in str (must be big enough). Returns the index |
|
242 //of the newline, or -1 if at end of string. If reaches |
|
243 //end of string ('\0'), then will copy contents to |
|
244 //globalStream. |
|
245 int getStrLine(const char *src, char *str, int ind, int max) { |
|
246 char c = src[ind]; |
|
247 int i=0; |
|
248 globalStream.Assign('\0'); |
|
249 while(c!='\n' && c!='\0' && i<max) { |
|
250 str[i] = src[ind]; |
|
251 i++; ind++; |
|
252 c = src[ind]; |
|
253 } |
|
254 str[i]='\0'; |
|
255 if(i==max || c=='\0') { |
|
256 globalStream.Assign(str); |
|
257 //printf("\nCarryover (%d|%d):\n------------\n%s\n-------\n",i,max,str); |
|
258 return -1; |
|
259 } |
|
260 return ind; |
|
261 } |
|
262 |
|
263 //----------AUX LOAD----------- |
|
264 nsresult auxLoad(char *uriBuf) |
|
265 { |
|
266 nsresult rv; |
|
267 |
|
268 nsCOMPtr<nsISupportsPRBool> myBool = do_CreateInstance(NS_SUPPORTS_PRBOOL_CONTRACTID); |
|
269 |
|
270 nsCOMPtr<nsIURI> uri; |
|
271 nsCOMPtr<nsIChannel> chan; |
|
272 nsCOMPtr<nsIStreamListener> listener = new MyListener(); |
|
273 nsCOMPtr<nsIInterfaceRequestor> callbacks = new MyNotifications(); |
|
274 |
|
275 printf("Getting: %s", uriBuf); |
|
276 |
|
277 //If relative link |
|
278 if(strncmp(uriBuf, "http:", 5)) { |
|
279 //Relative link |
|
280 rv = NS_NewURI(getter_AddRefs(uri), uriBuf, baseURI); |
|
281 if (NS_FAILED(rv)) return(rv); |
|
282 } else { |
|
283 //Absolute link, no base needed |
|
284 rv = NS_NewURI(getter_AddRefs(uri), uriBuf); |
|
285 if (NS_FAILED(rv)) return(rv); |
|
286 } |
|
287 |
|
288 //Compare to see if exists |
|
289 bool equal; |
|
290 for(int32_t i = 0; i < uriList.Count(); i++) { |
|
291 uri->Equals(uriList[i], &equal); |
|
292 if(equal) { |
|
293 printf("(duplicate, canceling) %s\n",uriBuf); |
|
294 return NS_OK; |
|
295 } |
|
296 } |
|
297 printf("\n"); |
|
298 uriList.AppendObject(uri); |
|
299 rv = NS_NewChannel(getter_AddRefs(chan), uri, nullptr, nullptr, callbacks); |
|
300 RETURN_IF_FAILED(rv, rv, "NS_NewChannel"); |
|
301 |
|
302 gKeepRunning++; |
|
303 rv = chan->AsyncOpen(listener, myBool); |
|
304 RETURN_IF_FAILED(rv, rv, "AsyncOpen"); |
|
305 |
|
306 return NS_OK; |
|
307 |
|
308 } |
|
309 |
|
310 //---------Buffer writer fun--------- |
|
311 |
|
312 } // namespace |
|
313 |
|
314 using namespace TestPageLoad; |
|
315 |
|
316 //---------MAIN----------- |
|
317 |
|
318 int main(int argc, char **argv) |
|
319 { |
|
320 if (test_common_init(&argc, &argv) != 0) |
|
321 return -1; |
|
322 |
|
323 nsresult rv; |
|
324 |
|
325 if (argc == 1) { |
|
326 printf("usage: TestPageLoad <url>\n"); |
|
327 return -1; |
|
328 } |
|
329 { |
|
330 nsCOMPtr<nsIServiceManager> servMan; |
|
331 NS_InitXPCOM2(getter_AddRefs(servMan), nullptr, nullptr); |
|
332 |
|
333 PRTime start, finish; |
|
334 |
|
335 printf("Loading necko ... \n"); |
|
336 nsCOMPtr<nsIChannel> chan; |
|
337 nsCOMPtr<nsIStreamListener> listener = new MyListener(); |
|
338 nsCOMPtr<nsIInterfaceRequestor> callbacks = new MyNotifications(); |
|
339 |
|
340 rv = NS_NewURI(getter_AddRefs(baseURI), argv[1]); |
|
341 RETURN_IF_FAILED(rv, -1, "NS_NewURI"); |
|
342 |
|
343 rv = NS_NewChannel(getter_AddRefs(chan), baseURI, nullptr, nullptr, callbacks); |
|
344 RETURN_IF_FAILED(rv, -1, "NS_OpenURI"); |
|
345 gKeepRunning++; |
|
346 |
|
347 //TIMER STARTED----------------------- |
|
348 printf("Starting clock ... \n"); |
|
349 start = PR_Now(); |
|
350 rv = chan->AsyncOpen(listener, nullptr); |
|
351 RETURN_IF_FAILED(rv, -1, "AsyncOpen"); |
|
352 |
|
353 PumpEvents(); |
|
354 |
|
355 finish = PR_Now(); |
|
356 uint32_t totalTime32 = uint32_t(finish - start); |
|
357 |
|
358 printf("\n\n--------------------\nAll done:\nnum found:%d\nnum start:%d\n", numFound, numStart); |
|
359 |
|
360 printf("\n\n>>PageLoadTime>>%u>>\n\n", totalTime32); |
|
361 } // this scopes the nsCOMPtrs |
|
362 // no nsCOMPtrs are allowed to be alive when you call NS_ShutdownXPCOM |
|
363 rv = NS_ShutdownXPCOM(nullptr); |
|
364 NS_ASSERTION(NS_SUCCEEDED(rv), "NS_ShutdownXPCOM failed"); |
|
365 return 0; |
|
366 } |