OLD | NEW |
| (Empty) |
1 <script> | |
2 var getURL = chrome.extension.getURL; | |
3 var deepEq = chrome.test.checkDeepEq; | |
4 var expectedEventData; | |
5 var capturedEventData; | |
6 var expectedEventOrder; | |
7 var tabId; | |
8 var eventsCaptured; | |
9 | |
10 // PORT will be changed to the port of the test server. | |
11 var URL_HTTP_SIMPLE_LOAD = | |
12 'http://www.a.com:PORT/files/extensions/api_test/webrequest/events/simpleLoa
d/a.html'; | |
13 var URL_HTTP_SIMPLE_LOAD_REDIRECT = | |
14 'http://www.a.com:PORT/server-redirect?'+URL_HTTP_SIMPLE_LOAD; | |
15 var URL_ECHO_USER_AGENT = | |
16 'http://www.a.com:PORT/echoheader?User-Agent'; | |
17 var URL_AUTH_REQUIRED = | |
18 'http://www.a.com:PORT/auth-basic'; | |
19 var URL_HTTP_XHR = | |
20 'http://www.a.com:PORT/files/extensions/api_test/webrequest/events/xhr/a.htm
l'; | |
21 var URL_HTTP_XHR_DATA = | |
22 'http://www.a.com:PORT/files/extensions/api_test/webrequest/events/xhr/data.
json'; | |
23 | |
24 function runTests(tests) { | |
25 chrome.tabs.getSelected(null, function(tab) { | |
26 tabId = tab.id; | |
27 chrome.test.getConfig(function(config) { | |
28 var fixPort = function(url) { | |
29 return url.replace(/PORT/g, config.testServer.port); | |
30 }; | |
31 URL_HTTP_SIMPLE_LOAD = fixPort(URL_HTTP_SIMPLE_LOAD); | |
32 URL_HTTP_SIMPLE_LOAD_REDIRECT = fixPort(URL_HTTP_SIMPLE_LOAD_REDIRECT); | |
33 URL_ECHO_USER_AGENT = fixPort(URL_ECHO_USER_AGENT); | |
34 URL_AUTH_REQUIRED = fixPort(URL_AUTH_REQUIRED); | |
35 URL_HTTP_XHR = fixPort(URL_HTTP_XHR); | |
36 URL_HTTP_XHR_DATA = fixPort(URL_HTTP_XHR_DATA); | |
37 | |
38 chrome.test.runTests(tests); | |
39 }); | |
40 }); | |
41 } | |
42 | |
43 // Helper to advance to the next test only when the tab has finished loading. | |
44 // This is because tabs.update can sometimes fail if the tab is in the middle | |
45 // of a navigation (from the previous test), resulting in flakiness. | |
46 function navigateAndWait(url, callback) { | |
47 var done = chrome.test.listenForever(chrome.tabs.onUpdated, | |
48 function (_, info, tab) { | |
49 if (tab.id == tabId && info.status == "complete") { | |
50 if (callback) callback(); | |
51 done(); | |
52 } | |
53 }); | |
54 chrome.tabs.update(tabId, {url: url}); | |
55 } | |
56 | |
57 // data: array of extected events, each one is a dictionary: | |
58 // { label: "<unique identifier>", | |
59 // event: "<webrequest event type>", | |
60 // details: { <expected details of the webrequest event> }, | |
61 // retval: { <dictionary that the event handler shall return> } (optional) | |
62 // } | |
63 // order: an array of sequences, e.g. [ ["a", "b", "c"], ["d", "e"] ] means that | |
64 // event with label "a" needs to occur before event with label "b". The | |
65 // relative order of "a" and "d" does not matter. | |
66 // filter: filter dictionary passed on to the event subscription of the | |
67 // webRequest API. | |
68 // extraInfoSpec: the union of all desired extraInfoSpecs for the events. | |
69 function expect(data, order, filter, extraInfoSpec) { | |
70 expectedEventData = data; | |
71 capturedEventData = []; | |
72 expectedEventOrder = order; | |
73 eventsCaptured = chrome.test.callbackAdded(); | |
74 tabAndFrameUrls = {}; // Maps "{tabId}-{frameId}" to the URL of the frame. | |
75 removeListeners(); | |
76 initListeners(filter || {}, extraInfoSpec || []); | |
77 } | |
78 | |
79 function checkExpectations() { | |
80 if (capturedEventData.length < expectedEventData.length) { | |
81 return; | |
82 } | |
83 if (capturedEventData.length > expectedEventData.length) { | |
84 chrome.test.fail("Recorded too many events. " + | |
85 JSON.stringify(capturedEventData)); | |
86 return; | |
87 } | |
88 // We have ensured that capturedEventData contains exactly the same elements | |
89 // as expectedEventData. Now we need to verify the ordering. | |
90 // Step 1: build positions such that | |
91 // positions[<event-label>]=<position of this event in capturedEventData> | |
92 var curPos = 0; | |
93 var positions = {} | |
94 capturedEventData.forEach(function (event) { | |
95 chrome.test.assertTrue(event.hasOwnProperty("label")); | |
96 positions[event.label] = curPos; | |
97 curPos++; | |
98 }); | |
99 // Step 2: check that elements arrived in correct order | |
100 expectedEventOrder.forEach(function (order) { | |
101 var previousLabel = undefined; | |
102 order.forEach(function(label) { | |
103 if (previousLabel === undefined) { | |
104 previousLabel = label; | |
105 return; | |
106 } | |
107 chrome.test.assertTrue(positions[previousLabel] < positions[label], | |
108 "Event " + previousLabel + " is supposed to arrive before " + | |
109 label + "."); | |
110 previousLabel = label; | |
111 }); | |
112 }); | |
113 | |
114 eventsCaptured(); | |
115 } | |
116 | |
117 // Simple check to see that we have a User-Agent header, and that it contains | |
118 // an expected value. This is a basic check that the request headers are valid. | |
119 function checkUserAgent(headers) { | |
120 for (var i in headers) { | |
121 if (headers[i].name.toLowerCase() == "user-agent") | |
122 return headers[i].value.toLowerCase().indexOf("chrome") != -1; | |
123 } | |
124 return false; | |
125 } | |
126 | |
127 function captureEvent(name, details) { | |
128 // Ignore system-level requests like safebrowsing updates and favicon fetches | |
129 // since they are unpredictable. | |
130 if (details.tabId == -1 || details.type == "other" || | |
131 details.url.match(/\/favicon.ico$/) || | |
132 details.url.match(/https:\/\/dl.google.com/)) | |
133 return; | |
134 | |
135 // Pull the extra per-event options out of the expected data. These let | |
136 // us specify special return values per event. | |
137 var currentIndex = capturedEventData.length; | |
138 var extraOptions; | |
139 if (expectedEventData.length > currentIndex) { | |
140 retval = expectedEventData[currentIndex].retval; | |
141 } | |
142 | |
143 // Check that the frameId can be used to reliably determine the URL of the | |
144 // frame that caused requests. | |
145 if (name == "onBeforeRequest") { | |
146 chrome.test.assertTrue('frameId' in details && | |
147 typeof details.frameId === 'number'); | |
148 chrome.test.assertTrue('tabId' in details && | |
149 typeof details.tabId === 'number'); | |
150 var key = details.tabId + "-" + details.frameId; | |
151 if (details.type == "main_frame" || details.type == "sub_frame") { | |
152 tabAndFrameUrls[key] = details.url; | |
153 } | |
154 details.frameUrl = tabAndFrameUrls[key] || "unknown frame URL"; | |
155 } | |
156 delete details.frameId; | |
157 | |
158 delete details.requestId; | |
159 delete details.timeStamp; | |
160 if (details.requestHeaders) { | |
161 details.requestHeadersValid = checkUserAgent(details.requestHeaders); | |
162 delete details.requestHeaders; | |
163 } | |
164 if (details.responseHeaders) { | |
165 details.responseHeadersExist = true; | |
166 delete details.responseHeaders; | |
167 } | |
168 | |
169 // find |details| in expectedEventData | |
170 var found = false; | |
171 var label = undefined; | |
172 expectedEventData.forEach(function (exp) { | |
173 if (deepEq(exp.event, name) && deepEq(exp.details, details)) { | |
174 if (found) { | |
175 chrome.test.fail("Received event twice '" + name + "':" + | |
176 JSON.stringify(details)); | |
177 } else { | |
178 found = true; | |
179 label = exp.label; | |
180 } | |
181 } | |
182 }); | |
183 if (!found) { | |
184 chrome.test.fail("Received unexpected event '" + name + "':" + | |
185 JSON.stringify(details)); | |
186 } | |
187 | |
188 capturedEventData.push({label: label, event: name, details: details}); | |
189 checkExpectations(); | |
190 return retval; | |
191 } | |
192 | |
193 // Simple array intersection. We use this to filter extraInfoSpec so | |
194 // that only the allowed specs are sent to each listener. | |
195 function intersect(array1, array2) { | |
196 return array1.filter(function(x) { return array2.indexOf(x) != -1; }); | |
197 } | |
198 | |
199 function initListeners(filter, extraInfoSpec) { | |
200 chrome.experimental.webRequest.onBeforeRequest.addListener( | |
201 function(details) { | |
202 return captureEvent("onBeforeRequest", details); | |
203 }, filter, intersect(extraInfoSpec, ["blocking"])); | |
204 chrome.experimental.webRequest.onBeforeSendHeaders.addListener( | |
205 function(details) { | |
206 return captureEvent("onBeforeSendHeaders", details); | |
207 }, filter, intersect(extraInfoSpec, ["blocking", "requestHeaders"])); | |
208 chrome.experimental.webRequest.onSendHeaders.addListener( | |
209 function(details) { | |
210 return captureEvent("onSendHeaders", details); | |
211 }, filter, intersect(extraInfoSpec, ["requestHeaders"])); | |
212 chrome.experimental.webRequest.onAuthRequired.addListener( | |
213 function(details) { | |
214 return captureEvent("onAuthRequired", details); | |
215 }, filter, intersect(extraInfoSpec, ["responseHeaders", "statusLine"])); | |
216 chrome.experimental.webRequest.onResponseStarted.addListener( | |
217 function(details) { | |
218 return captureEvent("onResponseStarted", details); | |
219 }, filter, intersect(extraInfoSpec, ["responseHeaders", "statusLine"])); | |
220 chrome.experimental.webRequest.onBeforeRedirect.addListener( | |
221 function(details) { | |
222 return captureEvent("onBeforeRedirect", details); | |
223 }, filter, intersect(extraInfoSpec, ["responseHeaders", "statusLine"])); | |
224 chrome.experimental.webRequest.onCompleted.addListener( | |
225 function(details) { | |
226 return captureEvent("onCompleted", details); | |
227 }, filter, intersect(extraInfoSpec, ["responseHeaders", "statusLine"])); | |
228 chrome.experimental.webRequest.onErrorOccurred.addListener( | |
229 function(details) { | |
230 return captureEvent("onErrorOccurred", details); | |
231 }, filter); | |
232 } | |
233 | |
234 function removeListeners() { | |
235 function helper(event) { | |
236 // Note: We're poking at the internal event data, but it's easier than | |
237 // the alternative. If this starts failing, we just need to update this | |
238 // helper. | |
239 for (var cb in event.callbackMap_) { | |
240 event.removeListener(cb); | |
241 } | |
242 chrome.test.assertFalse(event.hasListeners()); | |
243 } | |
244 helper(chrome.experimental.webRequest.onBeforeRequest); | |
245 helper(chrome.experimental.webRequest.onBeforeSendHeaders); | |
246 helper(chrome.experimental.webRequest.onAuthRequired); | |
247 helper(chrome.experimental.webRequest.onSendHeaders); | |
248 helper(chrome.experimental.webRequest.onResponseStarted); | |
249 helper(chrome.experimental.webRequest.onBeforeRedirect); | |
250 helper(chrome.experimental.webRequest.onCompleted); | |
251 helper(chrome.experimental.webRequest.onErrorOccurred); | |
252 } | |
253 | |
254 runTests([ | |
255 // Navigates to a blank page. | |
256 function simpleLoad() { | |
257 expect( | |
258 [ // events | |
259 { label: "a-onBeforeRequest", | |
260 event: "onBeforeRequest", | |
261 details: { | |
262 method: "GET", | |
263 tabId: tabId, | |
264 type: "main_frame", | |
265 url: getURL("simpleLoad/a.html"), | |
266 frameUrl: getURL("simpleLoad/a.html") | |
267 } | |
268 }, | |
269 { label: "a-onResponseStarted", | |
270 event: "onResponseStarted", | |
271 details: { | |
272 url: getURL("simpleLoad/a.html"), | |
273 statusCode: 200, | |
274 fromCache: false | |
275 // Request to chrome-extension:// url has no IP. | |
276 } | |
277 }, | |
278 { label: "a-onCompleted", | |
279 event: "onCompleted", | |
280 details: { | |
281 url: getURL("simpleLoad/a.html"), | |
282 statusCode: 200, | |
283 fromCache: false | |
284 // Request to chrome-extension:// url has no IP. | |
285 } | |
286 }, | |
287 ], | |
288 [ // event order | |
289 ["a-onBeforeRequest", "a-onResponseStarted", "a-onCompleted"] ]); | |
290 navigateAndWait(getURL("simpleLoad/a.html")); | |
291 }, | |
292 | |
293 // Navigates to a blank page via HTTP. Only HTTP requests get the | |
294 // onBeforeSendHeaders event. | |
295 function simpleLoadHttp() { | |
296 expect( | |
297 [ // events | |
298 { label: "onBeforeRequest-1", | |
299 event: "onBeforeRequest", | |
300 details: { | |
301 method: "GET", | |
302 tabId: tabId, | |
303 type: "main_frame", | |
304 url: URL_HTTP_SIMPLE_LOAD_REDIRECT, | |
305 frameUrl: URL_HTTP_SIMPLE_LOAD_REDIRECT | |
306 } | |
307 }, | |
308 { label: "onBeforeSendHeaders-1", | |
309 event: "onBeforeSendHeaders", | |
310 details: { | |
311 url: URL_HTTP_SIMPLE_LOAD_REDIRECT, | |
312 requestHeadersValid: true | |
313 } | |
314 }, | |
315 { label: "onSendHeaders-1", | |
316 event: "onSendHeaders", | |
317 details: { | |
318 url: URL_HTTP_SIMPLE_LOAD_REDIRECT, | |
319 requestHeadersValid: true | |
320 } | |
321 }, | |
322 { label: "onBeforeRedirect", | |
323 event: "onBeforeRedirect", | |
324 details: { | |
325 url: URL_HTTP_SIMPLE_LOAD_REDIRECT, | |
326 redirectUrl: URL_HTTP_SIMPLE_LOAD, | |
327 statusCode: 301, | |
328 responseHeadersExist: true, | |
329 ip: "127.0.0.1", | |
330 fromCache: false, | |
331 statusLine: "HTTP/1.0 301 Moved Permanently" | |
332 } | |
333 }, | |
334 { label: "onBeforeRequest-2", | |
335 event: "onBeforeRequest", | |
336 details: { | |
337 method: "GET", | |
338 tabId: tabId, | |
339 type: "main_frame", | |
340 url: URL_HTTP_SIMPLE_LOAD, | |
341 frameUrl: URL_HTTP_SIMPLE_LOAD | |
342 } | |
343 }, | |
344 { label: "onBeforeSendHeaders-2", | |
345 event: "onBeforeSendHeaders", | |
346 details: { | |
347 url: URL_HTTP_SIMPLE_LOAD, | |
348 requestHeadersValid: true | |
349 } | |
350 }, | |
351 { label: "onSendHeaders-2", | |
352 event: "onSendHeaders", | |
353 details: { | |
354 url: URL_HTTP_SIMPLE_LOAD, | |
355 requestHeadersValid: true | |
356 } | |
357 }, | |
358 { label: "onResponseStarted", | |
359 event: "onResponseStarted", | |
360 details: { | |
361 url: URL_HTTP_SIMPLE_LOAD, | |
362 statusCode: 200, | |
363 responseHeadersExist: true, | |
364 ip: "127.0.0.1", | |
365 fromCache: false, | |
366 statusLine: "HTTP/1.0 200 OK", | |
367 } | |
368 }, | |
369 { label: "onCompleted", | |
370 event: "onCompleted", | |
371 details: { | |
372 url: URL_HTTP_SIMPLE_LOAD, | |
373 statusCode: 200, | |
374 ip: "127.0.0.1", | |
375 fromCache: false, | |
376 responseHeadersExist: true, | |
377 statusLine: "HTTP/1.0 200 OK" | |
378 } | |
379 } | |
380 ], | |
381 [ // event order | |
382 ["onBeforeRequest-1", "onBeforeSendHeaders-1", "onSendHeaders-1", | |
383 "onBeforeRedirect", | |
384 "onBeforeRequest-2", "onBeforeSendHeaders-2", "onSendHeaders-2", | |
385 "onResponseStarted", "onCompleted"] ], | |
386 {}, // filter | |
387 ["requestHeaders", "responseHeaders", "statusLine"]); | |
388 navigateAndWait(URL_HTTP_SIMPLE_LOAD_REDIRECT); | |
389 }, | |
390 | |
391 // Navigates to a page to generates an XHR. | |
392 function xhrLoad() { | |
393 expect( | |
394 [ // events | |
395 { label: "onBeforeRequest-1", | |
396 event: "onBeforeRequest", | |
397 details: { | |
398 method: "GET", | |
399 tabId: tabId, | |
400 type: "main_frame", | |
401 url: URL_HTTP_XHR, | |
402 frameUrl: URL_HTTP_XHR | |
403 } | |
404 }, | |
405 { label: "onBeforeSendHeaders-1", | |
406 event: "onBeforeSendHeaders", | |
407 details: { | |
408 url: URL_HTTP_XHR, | |
409 } | |
410 }, | |
411 { label: "onSendHeaders-1", | |
412 event: "onSendHeaders", | |
413 details: { | |
414 url: URL_HTTP_XHR, | |
415 } | |
416 }, | |
417 { label: "onResponseStarted-1", | |
418 event: "onResponseStarted", | |
419 details: { | |
420 url: URL_HTTP_XHR, | |
421 statusCode: 200, | |
422 ip: "127.0.0.1", | |
423 fromCache: false, | |
424 } | |
425 }, | |
426 { label: "onCompleted-1", | |
427 event: "onCompleted", | |
428 details: { | |
429 url: URL_HTTP_XHR, | |
430 statusCode: 200, | |
431 ip: "127.0.0.1", | |
432 fromCache: false, | |
433 } | |
434 }, | |
435 { label: "onBeforeRequest-2", | |
436 event: "onBeforeRequest", | |
437 details: { | |
438 method: "GET", | |
439 tabId: tabId, | |
440 type: "xmlhttprequest", | |
441 url: URL_HTTP_XHR_DATA, | |
442 frameUrl: URL_HTTP_XHR | |
443 } | |
444 }, | |
445 { label: "onBeforeSendHeaders-2", | |
446 event: "onBeforeSendHeaders", | |
447 details: { | |
448 url: URL_HTTP_XHR_DATA, | |
449 } | |
450 }, | |
451 { label: "onSendHeaders-2", | |
452 event: "onSendHeaders", | |
453 details: { | |
454 url: URL_HTTP_XHR_DATA, | |
455 } | |
456 }, | |
457 { label: "onResponseStarted-2", | |
458 event: "onResponseStarted", | |
459 details: { | |
460 url: URL_HTTP_XHR_DATA, | |
461 statusCode: 200, | |
462 ip: "127.0.0.1", | |
463 fromCache: false, | |
464 } | |
465 }, | |
466 { label: "onCompleted-2", | |
467 event: "onCompleted", | |
468 details: { | |
469 url: URL_HTTP_XHR_DATA, | |
470 statusCode: 200, | |
471 ip: "127.0.0.1", | |
472 fromCache: false, | |
473 } | |
474 } | |
475 ], | |
476 [ // event order | |
477 ["onBeforeRequest-1", "onBeforeSendHeaders-1", "onSendHeaders-1", | |
478 "onResponseStarted-1", "onCompleted-1", | |
479 "onBeforeRequest-2", "onBeforeSendHeaders-2", "onSendHeaders-2", | |
480 "onResponseStarted-2", "onCompleted-2"] ], | |
481 {}, []); | |
482 navigateAndWait(URL_HTTP_XHR); | |
483 }, | |
484 | |
485 // Navigates to a page with subresources. | |
486 // TODO(mpcomplete): add multiple subresources; requires support for | |
487 // recognizing partial ordering. | |
488 function complexLoad() { | |
489 expect( | |
490 [ // events | |
491 { label: "a.html-onBeforeRequest", | |
492 event: "onBeforeRequest", | |
493 details: { | |
494 method: "GET", | |
495 tabId: tabId, | |
496 type: "main_frame", | |
497 url: getURL("complexLoad/a.html"), | |
498 frameUrl: getURL("complexLoad/a.html") | |
499 } | |
500 }, | |
501 { label: "b.html-onBeforeRequest", | |
502 event: "onBeforeRequest", | |
503 details: { | |
504 method: "GET", | |
505 tabId: tabId, | |
506 type: "sub_frame", | |
507 url: getURL("complexLoad/b.html"), | |
508 frameUrl: getURL("complexLoad/b.html") | |
509 } | |
510 }, | |
511 { label: "b.jpg-onBeforeRequest", | |
512 event: "onBeforeRequest", | |
513 details: { | |
514 method: "GET", | |
515 tabId: tabId, | |
516 type: "image", | |
517 url: getURL("complexLoad/b.jpg"), | |
518 frameUrl: getURL("complexLoad/b.html") | |
519 } | |
520 }, | |
521 { label: "a.html-onResponseStarted", | |
522 event: "onResponseStarted", | |
523 details: { | |
524 url: getURL("complexLoad/a.html"), | |
525 fromCache: false, | |
526 statusCode: 200 | |
527 // Request to chrome-extension:// url has no IP. | |
528 } | |
529 }, | |
530 { label: "b.html-onResponseStarted", | |
531 event: "onResponseStarted", | |
532 details: { | |
533 url: getURL("complexLoad/b.html"), | |
534 fromCache: false, | |
535 statusCode: 200 | |
536 // Request to chrome-extension:// url has no IP. | |
537 } | |
538 }, | |
539 { label: "b.jpg-onResponseStarted", | |
540 event: "onResponseStarted", | |
541 details: { | |
542 url: getURL("complexLoad/b.jpg"), | |
543 fromCache: false, | |
544 statusCode: 200 | |
545 // Request to chrome-extension:// url has no IP. | |
546 } | |
547 }, | |
548 { label: "a.html-onCompleted", | |
549 event: "onCompleted", | |
550 details: { | |
551 url: getURL("complexLoad/a.html"), | |
552 fromCache: false, | |
553 statusCode: 200 | |
554 // Request to chrome-extension:// url has no IP. | |
555 } | |
556 }, | |
557 { label: "b.html-onCompleted", | |
558 event: "onCompleted", | |
559 details: { | |
560 url: getURL("complexLoad/b.html"), | |
561 fromCache: false, | |
562 statusCode: 200 | |
563 // Request to chrome-extension:// url has no IP. | |
564 } | |
565 }, | |
566 { label: "b.jpg-onCompleted", | |
567 event: "onCompleted", | |
568 details: { | |
569 url: getURL("complexLoad/b.jpg"), | |
570 fromCache: false, | |
571 statusCode: 200 | |
572 // Request to chrome-extension:// url has no IP. | |
573 } | |
574 }, | |
575 ], | |
576 [ // event order | |
577 ["a.html-onBeforeRequest", "a.html-onResponseStarted", | |
578 "b.html-onBeforeRequest", "b.html-onResponseStarted", | |
579 "b.jpg-onBeforeRequest", "b.jpg-onResponseStarted" ], | |
580 ["a.html-onResponseStarted", "a.html-onCompleted"], | |
581 ["b.html-onResponseStarted", "b.html-onCompleted"], | |
582 ["b.jpg-onResponseStarted", "b.jpg-onCompleted"] ] | |
583 ); | |
584 navigateAndWait(getURL("complexLoad/a.html")); | |
585 }, | |
586 | |
587 // Navigates to a page with subresources, with a blocking handler that | |
588 // cancels the page request. The page will not load, and we should not | |
589 // see the subresources. | |
590 function complexLoadCancelled() { | |
591 expect( | |
592 [ // events | |
593 { label: "onBeforeRequest", | |
594 event: "onBeforeRequest", | |
595 details: { | |
596 method: "GET", | |
597 tabId: tabId, | |
598 type: "main_frame", | |
599 url: getURL("complexLoad/a.html"), | |
600 frameUrl: getURL("complexLoad/a.html") | |
601 }, | |
602 retval: {cancel: true} | |
603 }, | |
604 // Cancelling is considered an error. | |
605 { label: "onErrorOccurred", | |
606 event: "onErrorOccurred", | |
607 details: { | |
608 url: getURL("complexLoad/a.html"), | |
609 fromCache: false, | |
610 error: "net::ERR_EMPTY_RESPONSE" | |
611 // Request to chrome-extension:// url has no IP. | |
612 } | |
613 }, | |
614 ], | |
615 [ // event order | |
616 ["onBeforeRequest"] | |
617 ], | |
618 {}, // filter | |
619 ["blocking"]); | |
620 navigateAndWait(getURL("complexLoad/a.html")); | |
621 }, | |
622 | |
623 // Navigates to a page with a blocking handler that redirects to a different | |
624 // page. | |
625 // TODO(mpcomplete): We should see an onBeforeRedirect as well, but our | |
626 // process switching logic cancels the original redirect request and | |
627 // starts a new one instead. See http://crbug.com/79520. | |
628 function complexLoadRedirected() { | |
629 expect( | |
630 [ // events | |
631 { label: "onBeforeRequest-1", | |
632 event: "onBeforeRequest", | |
633 details: { | |
634 method: "GET", | |
635 tabId: tabId, | |
636 type: "main_frame", | |
637 url: getURL("complexLoad/a.html"), | |
638 frameUrl: getURL("complexLoad/a.html") | |
639 }, | |
640 retval: {redirectUrl: getURL("simpleLoad/a.html")} | |
641 }, | |
642 { label: "onErrorOccurred-1", | |
643 event: "onErrorOccurred", | |
644 details: { | |
645 url: getURL("complexLoad/a.html"), | |
646 fromCache: false, | |
647 error: "net::ERR_ABORTED" | |
648 // Request to chrome-extension:// url has no IP. | |
649 } | |
650 }, | |
651 { label: "onBeforeRequest-2", | |
652 event: "onBeforeRequest", | |
653 details: { | |
654 method: "GET", | |
655 tabId: tabId, | |
656 type: "main_frame", | |
657 url: getURL("simpleLoad/a.html"), | |
658 frameUrl: getURL("simpleLoad/a.html"), | |
659 }, | |
660 }, | |
661 { label: "onResponseStarted", | |
662 event: "onResponseStarted", | |
663 details: { | |
664 url: getURL("simpleLoad/a.html"), | |
665 fromCache: false, | |
666 statusCode: 200 | |
667 // Request to chrome-extension:// url has no IP. | |
668 } | |
669 }, | |
670 { label: "onCompleted", | |
671 event: "onCompleted", | |
672 details: { | |
673 url: getURL("simpleLoad/a.html"), | |
674 fromCache: false, | |
675 statusCode: 200 | |
676 // Request to chrome-extension:// url has no IP. | |
677 } | |
678 }, | |
679 ], | |
680 [ // event order | |
681 ["onBeforeRequest-1", "onErrorOccurred-1", "onBeforeRequest-2", | |
682 "onResponseStarted", "onCompleted"], | |
683 ], | |
684 {}, // filter | |
685 ["blocking"]); | |
686 navigateAndWait(getURL("complexLoad/a.html")); | |
687 }, | |
688 | |
689 // Loads several resources, but should only see the complexLoad main_frame | |
690 // and image due to the filter. | |
691 function complexLoadFiltered() { | |
692 expect( | |
693 [ // events | |
694 { label: "a-onBeforeRequest", | |
695 event: "onBeforeRequest", | |
696 details: { | |
697 method: "GET", | |
698 tabId: tabId, | |
699 type: "main_frame", | |
700 url: getURL("complexLoad/a.html"), | |
701 frameUrl: getURL("complexLoad/a.html") | |
702 } | |
703 }, | |
704 { label: "b-onBeforeRequest", | |
705 event: "onBeforeRequest", | |
706 details: { | |
707 method: "GET", | |
708 tabId: tabId, | |
709 type: "image", | |
710 url: getURL("complexLoad/b.jpg"), | |
711 // As we do not listed to sub-frames we do not know the frameUrl. | |
712 frameUrl: "unknown frame URL" | |
713 } | |
714 }, | |
715 { label: "a-onResponseStarted", | |
716 event: "onResponseStarted", | |
717 details: { | |
718 url: getURL("complexLoad/a.html"), | |
719 fromCache: false, | |
720 statusCode: 200 | |
721 // Request to chrome-extension:// url has no IP. | |
722 } | |
723 }, | |
724 { label: "b-onResponseStarted", | |
725 event: "onResponseStarted", | |
726 details: { | |
727 url: getURL("complexLoad/b.jpg"), | |
728 fromCache: false, | |
729 statusCode: 200 | |
730 // Request to chrome-extension:// url has no IP. | |
731 } | |
732 }, | |
733 { label: "a-onCompleted", | |
734 event: "onCompleted", | |
735 details: { | |
736 url: getURL("complexLoad/a.html"), | |
737 fromCache: false, | |
738 statusCode: 200 | |
739 // Request to chrome-extension:// url has no IP. | |
740 } | |
741 }, | |
742 { label: "b-onCompleted", | |
743 event: "onCompleted", | |
744 details: { | |
745 url: getURL("complexLoad/b.jpg"), | |
746 fromCache: false, | |
747 statusCode: 200 | |
748 // Request to chrome-extension:// url has no IP. | |
749 } | |
750 }, | |
751 ], | |
752 [ // event order | |
753 ["a-onBeforeRequest", "a-onResponseStarted", | |
754 "b-onBeforeRequest", "b-onResponseStarted"], | |
755 ["a-onResponseStarted", "a-onCompleted"], | |
756 ["b-onResponseStarted", "b-onCompleted"] ], | |
757 { // filters | |
758 urls: [getURL("complexLoad/*")], | |
759 types: ["main_frame", "image"], | |
760 tabId: tabId | |
761 }); | |
762 chrome.tabs.create({ url: getURL("simpleLoad/a.html") }, | |
763 function(newTab) { | |
764 chrome.tabs.remove(newTab.id); | |
765 navigateAndWait(getURL("complexLoad/a.html")); | |
766 }); | |
767 }, | |
768 | |
769 // Navigates to a non-existing page. | |
770 function nonExistingLoad() { | |
771 expect( | |
772 [ // events | |
773 { label: "onBeforeRequest", | |
774 event: "onBeforeRequest", | |
775 details: { | |
776 method: "GET", | |
777 tabId: tabId, | |
778 type: "main_frame", | |
779 url: getURL("does_not_exist.html"), | |
780 frameUrl: getURL("does_not_exist.html") | |
781 } | |
782 }, | |
783 { label: "onErrorOccurred", | |
784 event: "onErrorOccurred", | |
785 details: { | |
786 url: getURL("does_not_exist.html"), | |
787 fromCache: false, | |
788 error: "net::ERR_FILE_NOT_FOUND", | |
789 // Request to chrome-extension:// url has no IP. | |
790 } | |
791 }, | |
792 ], | |
793 [ // event order | |
794 ["onBeforeRequest", "onErrorOccurred"] ]); | |
795 navigateAndWait(getURL("does_not_exist.html")); | |
796 }, | |
797 | |
798 // Loads a testserver page that echoes the User-Agent header that was | |
799 // sent to fetch it. We modify the outgoing User-Agent in | |
800 // onBeforeSendHeaders, so we should see that modified version. | |
801 function modifyRequestHeaders() { | |
802 expect( | |
803 [ // events | |
804 { label: "onBeforeRequest", | |
805 event: "onBeforeRequest", | |
806 details: { | |
807 method: "GET", | |
808 tabId: tabId, | |
809 type: "main_frame", | |
810 url: URL_ECHO_USER_AGENT, | |
811 frameUrl: URL_ECHO_USER_AGENT | |
812 } | |
813 }, | |
814 { label: "onBeforeSendHeaders", | |
815 event: "onBeforeSendHeaders", | |
816 details: { | |
817 url: URL_ECHO_USER_AGENT, | |
818 // Note: no requestHeaders because we don't ask for them. | |
819 }, | |
820 retval: {requestHeaders: [{name: "User-Agent", value: "FoobarUA"}]} | |
821 }, | |
822 { label: "onSendHeaders", | |
823 event: "onSendHeaders", | |
824 details: { | |
825 url: URL_ECHO_USER_AGENT | |
826 } | |
827 }, | |
828 { label: "onResponseStarted", | |
829 event: "onResponseStarted", | |
830 details: { | |
831 url: URL_ECHO_USER_AGENT, | |
832 fromCache: false, | |
833 statusCode: 200, | |
834 ip: "127.0.0.1" | |
835 } | |
836 }, | |
837 { label: "onCompleted", | |
838 event: "onCompleted", | |
839 details: { | |
840 url: URL_ECHO_USER_AGENT, | |
841 fromCache: false, | |
842 statusCode: 200, | |
843 ip: "127.0.0.1" | |
844 } | |
845 }, | |
846 ], | |
847 [ // event order | |
848 ["onBeforeRequest", "onBeforeSendHeaders", "onSendHeaders", | |
849 "onResponseStarted", "onCompleted"] | |
850 ], | |
851 {}, ["blocking"]); | |
852 // Check the page content for our modified User-Agent string. | |
853 navigateAndWait(URL_ECHO_USER_AGENT, function() { | |
854 chrome.test.listenOnce(chrome.extension.onRequest, function(request) { | |
855 chrome.test.assertTrue(request.pass, "Request header was not set."); | |
856 }); | |
857 chrome.tabs.executeScript(tabId, | |
858 { | |
859 code: "chrome.extension.sendRequest(" + | |
860 "{pass: document.body.innerText.indexOf('FoobarUA') >= 0});" | |
861 }); | |
862 }); | |
863 }, | |
864 | |
865 // Loads a testserver page that requires authentication. | |
866 function authRequired() { | |
867 expect( | |
868 [ // events | |
869 { label: "onBeforeRequest", | |
870 event: "onBeforeRequest", | |
871 details: { | |
872 method: "GET", | |
873 tabId: tabId, | |
874 type: "main_frame", | |
875 url: URL_AUTH_REQUIRED, | |
876 frameUrl: URL_AUTH_REQUIRED | |
877 } | |
878 }, | |
879 { label: "onBeforeSendHeaders", | |
880 event: "onBeforeSendHeaders", | |
881 details: { | |
882 url: URL_AUTH_REQUIRED, | |
883 // Note: no requestHeaders because we don't ask for them. | |
884 }, | |
885 }, | |
886 { label: "onSendHeaders", | |
887 event: "onSendHeaders", | |
888 details: { | |
889 url: URL_AUTH_REQUIRED, | |
890 } | |
891 }, | |
892 { label: "onAuthRequired", | |
893 event: "onAuthRequired", | |
894 details: { | |
895 url: URL_AUTH_REQUIRED, | |
896 isProxy: false, | |
897 scheme: "basic", | |
898 realm: "testrealm", | |
899 } | |
900 }, | |
901 { label: "onResponseStarted", | |
902 event: "onResponseStarted", | |
903 details: { | |
904 url: URL_AUTH_REQUIRED, | |
905 fromCache: false, | |
906 statusCode: 401, | |
907 ip: "127.0.0.1" | |
908 } | |
909 }, | |
910 { label: "onCompleted", | |
911 event: "onCompleted", | |
912 details: { | |
913 url: URL_AUTH_REQUIRED, | |
914 fromCache: false, | |
915 statusCode: 401, | |
916 ip: "127.0.0.1" | |
917 } | |
918 }, | |
919 ], | |
920 [ // event order | |
921 ["onBeforeRequest", "onBeforeSendHeaders", "onSendHeaders", | |
922 "onAuthRequired", "onResponseStarted", "onCompleted"] | |
923 ], | |
924 {}, []); | |
925 navigateAndWait(URL_AUTH_REQUIRED); | |
926 }, | |
927 ]); | |
928 </script> | |
OLD | NEW |