Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / chrome / test / data / extensions / api_test / webrequest / test_blocking.js
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 var pass = chrome.test.callbackPass;
6
7 // Constants as functions, not to be called until after runTests.
8 function getURLEchoUserAgent() {
9   return getServerURL('echoheader?User-Agent');
10 }
11
12 function getURLSetCookie() {
13   return getServerURL('set-cookie?Foo=Bar');
14 }
15
16 function getURLNonUTF8SetCookie() {
17   return getServerURL('set-header?Set-Cookie%3A%20Foo%3D%FE%D1');
18 }
19
20 function getURLHttpSimpleLoad() {
21   return getServerURL('extensions/api_test/webrequest/simpleLoad/a.html');
22 }
23 function getURLHttpXHRData() {
24   return getServerURL('extensions/api_test/webrequest/xhr/data.json');
25 }
26
27 function toCharCodes(str) {
28   var result = [];
29   for (var i = 0; i < str.length; ++i) {
30     result[i] = str.charCodeAt(i);
31   }
32   return result;
33 }
34
35 runTests([
36   // Navigates to a page with subresources, with a blocking handler that
37   // cancels the page request. The page will not load, and we should not
38   // see the subresources.
39   function complexLoadCancelled() {
40     expect(
41       [  // events
42         { label: "onBeforeRequest",
43           event: "onBeforeRequest",
44           details: {
45             type: "main_frame",
46             url: getURL("complexLoad/b.html"),
47             frameUrl: getURL("complexLoad/b.html")
48           },
49           retval: {cancel: true}
50         },
51         // Cancelling is considered an error.
52         { label: "onErrorOccurred",
53           event: "onErrorOccurred",
54           details: {
55             url: getURL("complexLoad/b.html"),
56             fromCache: false,
57             error: "net::ERR_BLOCKED_BY_CLIENT"
58             // Request to chrome-extension:// url has no IP.
59           }
60         },
61       ],
62       [  // event order
63         ["onBeforeRequest", "onErrorOccurred"]
64       ],
65       {urls: ["<all_urls>"]},  // filter
66       ["blocking"]);
67     navigateAndWait(getURL("complexLoad/b.html"));
68   },
69
70   // Navigates to a page with subresources, with a blocking handler that
71   // cancels the page request. The page will not load, and we should not
72   // see the subresources.
73   function simpleLoadCancelledOnReceiveHeaders() {
74     expect(
75       [  // events
76         { label: "onBeforeRequest",
77           event: "onBeforeRequest",
78           details: {
79             method: "GET",
80             type: "main_frame",
81             url: getURLHttpSimpleLoad(),
82             frameUrl: getURLHttpSimpleLoad()
83           },
84           retval: {cancel: false}
85         },
86         { label: "onBeforeSendHeaders",
87           event: "onBeforeSendHeaders",
88           details: {
89             url: getURLHttpSimpleLoad(),
90             // Note: no requestHeaders because we don't ask for them.
91           },
92         },
93         { label: "onSendHeaders",
94           event: "onSendHeaders",
95           details: {
96             url: getURLHttpSimpleLoad()
97           }
98         },
99         { label: "onHeadersReceived",
100           event: "onHeadersReceived",
101           details: {
102             url: getURLHttpSimpleLoad(),
103             statusLine: "HTTP/1.1 200 OK",
104           },
105           retval: {cancel: true}
106         },
107         // Cancelling is considered an error.
108         { label: "onErrorOccurred",
109           event: "onErrorOccurred",
110           details: {
111             url: getURLHttpSimpleLoad(),
112             fromCache: false,
113             error: "net::ERR_BLOCKED_BY_CLIENT"
114             // Request to chrome-extension:// url has no IP.
115           }
116         },
117       ],
118       [  // event order
119         ["onBeforeRequest", "onBeforeSendHeaders", "onSendHeaders",
120          "onHeadersReceived", "onErrorOccurred"]
121       ],
122       {urls: ["<all_urls>"]},  // filter
123       ["blocking"]);
124     navigateAndWait(getURLHttpSimpleLoad());
125   },
126
127   // Navigates to a page and provides invalid header information. The request
128   // should continue as if the headers were not changed.
129   function simpleLoadIgnoreOnBeforeSendHeadersInvalidHeaders() {
130     expect(
131       [  // events
132         { label: "onBeforeRequest",
133           event: "onBeforeRequest",
134           details: {
135             method: "GET",
136             type: "main_frame",
137             url: getURLHttpSimpleLoad(),
138             frameUrl: getURLHttpSimpleLoad()
139           },
140         },
141         { label: "onBeforeSendHeaders",
142           event: "onBeforeSendHeaders",
143           details: {
144             url: getURLHttpSimpleLoad(),
145             requestHeadersValid: true
146           },
147           retval: {requestHeaders: [{name: "User-Agent"}]}
148         },
149         // The headers were invalid, so they should not be modified.
150         // TODO(robwu): Test whether an error is logged to the console.
151         { label: "onSendHeaders",
152           event: "onSendHeaders",
153           details: {
154             url: getURLHttpSimpleLoad(),
155             requestHeadersValid: true
156           }
157         },
158         { label: "onHeadersReceived",
159           event: "onHeadersReceived",
160           details: {
161             url: getURLHttpSimpleLoad(),
162             statusLine: "HTTP/1.1 200 OK",
163           }
164         },
165         { label: "onResponseStarted",
166           event: "onResponseStarted",
167           details: {
168             url: getURLHttpSimpleLoad(),
169             fromCache: false,
170             statusCode: 200,
171             ip: "127.0.0.1",
172             statusLine: "HTTP/1.1 200 OK",
173           }
174         },
175         { label: "onCompleted",
176           event: "onCompleted",
177           details: {
178             url: getURLHttpSimpleLoad(),
179             fromCache: false,
180             statusCode: 200,
181             ip: "127.0.0.1",
182             statusLine: "HTTP/1.1 200 OK",
183           }
184         },
185       ],
186       [  // event order
187         ["onBeforeRequest", "onBeforeSendHeaders", "onSendHeaders",
188          "onHeadersReceived", "onResponseStarted", "onCompleted"]
189       ],
190       {urls: ["<all_urls>"]},  // filter
191       ["blocking", "requestHeaders"]);
192     navigateAndWait(getURLHttpSimpleLoad());
193   },
194
195   // Navigates to a page and provides invalid header information. The request
196   // should continue as if the headers were not changed.
197   function simpleLoadIgnoreOnBeforeSendHeadersInvalidResponse() {
198     // Exception handling seems to break this test, so disable it.
199     // See http://crbug.com/370897. TODO(robwu): Fix me.
200     chrome.test.setExceptionHandler(function(){});
201     expect(
202       [  // events
203         { label: "onBeforeRequest",
204           event: "onBeforeRequest",
205           details: {
206             method: "GET",
207             type: "main_frame",
208             url: getURLHttpSimpleLoad(),
209             frameUrl: getURLHttpSimpleLoad()
210           },
211         },
212         { label: "onBeforeSendHeaders",
213           event: "onBeforeSendHeaders",
214           details: {
215             url: getURLHttpSimpleLoad(),
216             requestHeadersValid: true
217           },
218           retval: {foo: "bar"}
219         },
220         // TODO(robwu): Test whether an error is logged to the console.
221         { label: "onSendHeaders",
222           event: "onSendHeaders",
223           details: {
224             url: getURLHttpSimpleLoad(),
225             requestHeadersValid: true
226           }
227         },
228         { label: "onHeadersReceived",
229           event: "onHeadersReceived",
230           details: {
231             url: getURLHttpSimpleLoad(),
232             statusLine: "HTTP/1.1 200 OK",
233           }
234         },
235         { label: "onResponseStarted",
236           event: "onResponseStarted",
237           details: {
238             url: getURLHttpSimpleLoad(),
239             fromCache: false,
240             statusCode: 200,
241             ip: "127.0.0.1",
242             statusLine: "HTTP/1.1 200 OK",
243           }
244         },
245         { label: "onCompleted",
246           event: "onCompleted",
247           details: {
248             url: getURLHttpSimpleLoad(),
249             fromCache: false,
250             statusCode: 200,
251             ip: "127.0.0.1",
252             statusLine: "HTTP/1.1 200 OK",
253           }
254         },
255       ],
256       [  // event order
257         ["onBeforeRequest", "onBeforeSendHeaders", "onSendHeaders",
258          "onHeadersReceived", "onResponseStarted", "onCompleted"]
259       ],
260       {urls: ["<all_urls>"]},  // filter
261       ["blocking", "requestHeaders"]);
262     navigateAndWait(getURLHttpSimpleLoad());
263   },
264
265   // Navigates to a page with a blocking handler that redirects to a different
266   // page.
267   function complexLoadRedirected() {
268     expect(
269       [  // events
270         { label: "onBeforeRequest-1",
271           event: "onBeforeRequest",
272           details: {
273             url: getURL("complexLoad/a.html"),
274             frameUrl: getURL("complexLoad/a.html")
275           },
276           retval: {redirectUrl: getURL("simpleLoad/a.html")}
277         },
278         { label: "onBeforeRedirect",
279           event: "onBeforeRedirect",
280           details: {
281             url: getURL("complexLoad/a.html"),
282             redirectUrl: getURL("simpleLoad/a.html"),
283             fromCache: false,
284             statusLine: "HTTP/1.1 307 Internal Redirect",
285             statusCode: 307,
286           }
287         },
288         { label: "onBeforeRequest-2",
289           event: "onBeforeRequest",
290           details: {
291             url: getURL("simpleLoad/a.html"),
292             frameUrl: getURL("simpleLoad/a.html"),
293           },
294         },
295         { label: "onResponseStarted",
296           event: "onResponseStarted",
297           details: {
298             url: getURL("simpleLoad/a.html"),
299             fromCache: false,
300             statusCode: 200,
301             statusLine: "HTTP/1.1 200 OK",
302             // Request to chrome-extension:// url has no IP.
303           }
304         },
305         { label: "onCompleted",
306           event: "onCompleted",
307           details: {
308             url: getURL("simpleLoad/a.html"),
309             fromCache: false,
310             statusCode: 200,
311             statusLine: "HTTP/1.1 200 OK",
312             // Request to chrome-extension:// url has no IP.
313           }
314         },
315       ],
316       [  // event order
317         ["onBeforeRequest-1", "onBeforeRedirect", "onBeforeRequest-2",
318          "onResponseStarted", "onCompleted"],
319       ],
320       {urls: ["<all_urls>"]}, // filter
321       ["blocking"]);
322     navigateAndWait(getURL("complexLoad/a.html"));
323   },
324
325   // Tests redirect of <img crossorigin="anonymous" src="...">
326   function crossOriginAnonymousRedirect() {
327     testLoadCORSImage("anonymous");
328   },
329
330   // Tests redirect of <img crossorigin="use-credentials" src="...">
331   function crossOriginCredentialedRedirect() {
332     testLoadCORSImage("use-credentials");
333   },
334
335   // Loads a testserver page that echoes the User-Agent header that was
336   // sent to fetch it. We modify the outgoing User-Agent in
337   // onBeforeSendHeaders, so we should see that modified version.
338   function modifyRequestHeaders() {
339     expect(
340       [  // events
341         { label: "onBeforeRequest",
342           event: "onBeforeRequest",
343           details: {
344             url: getURLEchoUserAgent(),
345             frameUrl: getURLEchoUserAgent()
346           }
347         },
348         { label: "onBeforeSendHeaders",
349           event: "onBeforeSendHeaders",
350           details: {
351             url: getURLEchoUserAgent(),
352             // Note: no requestHeaders because we don't ask for them.
353           },
354           retval: {requestHeaders: [{name: "User-Agent", value: "FoobarUA"}]}
355         },
356         { label: "onSendHeaders",
357           event: "onSendHeaders",
358           details: {
359             url: getURLEchoUserAgent()
360           }
361         },
362         { label: "onHeadersReceived",
363           event: "onHeadersReceived",
364           details: {
365             url: getURLEchoUserAgent(),
366             statusLine: "HTTP/1.1 200 OK",
367           }
368         },
369         { label: "onResponseStarted",
370           event: "onResponseStarted",
371           details: {
372             url: getURLEchoUserAgent(),
373             fromCache: false,
374             statusCode: 200,
375             ip: "127.0.0.1",
376             statusLine: "HTTP/1.1 200 OK",
377           }
378         },
379         { label: "onCompleted",
380           event: "onCompleted",
381           details: {
382             url: getURLEchoUserAgent(),
383             fromCache: false,
384             statusCode: 200,
385             ip: "127.0.0.1",
386             statusLine: "HTTP/1.1 200 OK",
387           }
388         },
389       ],
390       [  // event order
391         ["onBeforeRequest", "onBeforeSendHeaders", "onSendHeaders",
392          "onHeadersReceived", "onResponseStarted", "onCompleted"]
393       ],
394       {urls: ["<all_urls>"]}, ["blocking"]);
395     // Check the page content for our modified User-Agent string.
396     navigateAndWait(getURLEchoUserAgent(), function() {
397       chrome.test.listenOnce(chrome.extension.onRequest, function(request) {
398         chrome.test.assertTrue(request.pass, "Request header was not set.");
399       });
400       chrome.tabs.executeScript(tabId,
401         {
402           code: "chrome.extension.sendRequest(" +
403               "{pass: document.body.innerText.indexOf('FoobarUA') >= 0});"
404         });
405     });
406   },
407
408   // Loads a testserver page that echoes the User-Agent header that was
409   // sent to fetch it. We modify the outgoing User-Agent in
410   // onBeforeSendHeaders, so we should see that modified version.
411   // In this version we check whether we can set binary header values.
412   function modifyBinaryRequestHeaders() {
413     expect(
414       [  // events
415         { label: "onBeforeRequest",
416           event: "onBeforeRequest",
417           details: {
418             url: getURLEchoUserAgent(),
419             frameUrl: getURLEchoUserAgent()
420           }
421         },
422         { label: "onBeforeSendHeaders",
423           event: "onBeforeSendHeaders",
424           details: {
425             url: getURLEchoUserAgent(),
426             // Note: no requestHeaders because we don't ask for them.
427           },
428           retval: {requestHeaders: [{name: "User-Agent",
429                                      binaryValue: toCharCodes("FoobarUA")}]}
430         },
431         { label: "onSendHeaders",
432           event: "onSendHeaders",
433           details: {
434             url: getURLEchoUserAgent()
435           }
436         },
437         { label: "onHeadersReceived",
438           event: "onHeadersReceived",
439           details: {
440             url: getURLEchoUserAgent(),
441             statusLine: "HTTP/1.1 200 OK",
442           }
443         },
444         { label: "onResponseStarted",
445           event: "onResponseStarted",
446           details: {
447             url: getURLEchoUserAgent(),
448             fromCache: false,
449             statusCode: 200,
450             ip: "127.0.0.1",
451             statusLine: "HTTP/1.1 200 OK",
452           }
453         },
454         { label: "onCompleted",
455           event: "onCompleted",
456           details: {
457             url: getURLEchoUserAgent(),
458             fromCache: false,
459             statusCode: 200,
460             ip: "127.0.0.1",
461             statusLine: "HTTP/1.1 200 OK",
462           }
463         },
464       ],
465       [  // event order
466         ["onBeforeRequest", "onBeforeSendHeaders", "onSendHeaders",
467          "onHeadersReceived", "onResponseStarted", "onCompleted"]
468       ],
469       {urls: ["<all_urls>"]}, ["blocking"]);
470     // Check the page content for our modified User-Agent string.
471     navigateAndWait(getURLEchoUserAgent(), function() {
472       chrome.test.listenOnce(chrome.extension.onRequest, function(request) {
473         chrome.test.assertTrue(request.pass, "Request header was not set.");
474       });
475       chrome.tabs.executeScript(tabId,
476         {
477           code: "chrome.extension.sendRequest(" +
478               "{pass: document.body.innerText.indexOf('FoobarUA') >= 0});"
479         });
480     });
481   },
482
483   // Loads a testserver page that sets a cookie "Foo=Bar" but removes
484   // the cookies from the response headers so that they are not set.
485   function modifyResponseHeaders() {
486     expect(
487       [  // events
488         { label: "onBeforeRequest",
489           event: "onBeforeRequest",
490           details: {
491             method: "GET",
492             type: "main_frame",
493             url: getURLSetCookie(),
494             frameUrl: getURLSetCookie()
495           }
496         },
497         { label: "onBeforeSendHeaders",
498           event: "onBeforeSendHeaders",
499           details: {
500             url: getURLSetCookie(),
501             // Note: no requestHeaders because we don't ask for them.
502           },
503         },
504         { label: "onSendHeaders",
505           event: "onSendHeaders",
506           details: {
507             url: getURLSetCookie(),
508           }
509         },
510         { label: "onHeadersReceived",
511           event: "onHeadersReceived",
512           details: {
513             url: getURLSetCookie(),
514             statusLine: "HTTP/1.1 200 OK",
515             responseHeadersExist: true,
516           },
517           retval_function: function(name, details) {
518             responseHeaders = details.responseHeaders;
519             var found = false;
520             for (var i = 0; i < responseHeaders.length; ++i) {
521               if (responseHeaders[i].name === "Set-Cookie" &&
522                   responseHeaders[i].value.indexOf("Foo") != -1) {
523                 found = true;
524                 responseHeaders.splice(i);
525                 break;
526               }
527             }
528             chrome.test.assertTrue(found);
529             return {responseHeaders: responseHeaders};
530           }
531         },
532         { label: "onResponseStarted",
533           event: "onResponseStarted",
534           details: {
535             url: getURLSetCookie(),
536             fromCache: false,
537             statusCode: 200,
538             statusLine: "HTTP/1.1 200 OK",
539             ip: "127.0.0.1",
540             responseHeadersExist: true,
541           }
542         },
543         { label: "onCompleted",
544           event: "onCompleted",
545           details: {
546             url: getURLSetCookie(),
547             fromCache: false,
548             statusCode: 200,
549             statusLine: "HTTP/1.1 200 OK",
550             ip: "127.0.0.1",
551             responseHeadersExist: true,
552           }
553         },
554       ],
555       [  // event order
556         ["onBeforeRequest", "onBeforeSendHeaders", "onSendHeaders",
557          "onHeadersReceived", "onResponseStarted", "onCompleted"]
558       ],
559       {urls: ["<all_urls>"]}, ["blocking", "responseHeaders"]);
560     // Check that the cookie was really removed.
561     navigateAndWait(getURLSetCookie(), function() {
562       chrome.test.listenOnce(chrome.extension.onRequest, function(request) {
563         chrome.test.assertTrue(request.pass, "Cookie was not removed.");
564       });
565       chrome.tabs.executeScript(tabId,
566       { code: "chrome.extension.sendRequest(" +
567             "{pass: document.cookie.indexOf('Foo') == -1});"
568         });
569     });
570   },
571
572   // Loads a testserver page that sets a cookie "Foo=U+FDD1" which is not a
573   // valid UTF-8 code point. Therefore, it cannot be passed to JavaScript
574   // as a normal string.
575   function handleNonUTF8InModifyResponseHeaders() {
576     expect(
577       [  // events
578         { label: "onBeforeRequest",
579           event: "onBeforeRequest",
580           details: {
581             method: "GET",
582             type: "main_frame",
583             url: getURLNonUTF8SetCookie(),
584             frameUrl: getURLNonUTF8SetCookie()
585           }
586         },
587         { label: "onBeforeSendHeaders",
588           event: "onBeforeSendHeaders",
589           details: {
590             url: getURLNonUTF8SetCookie(),
591             // Note: no requestHeaders because we don't ask for them.
592           },
593         },
594         { label: "onSendHeaders",
595           event: "onSendHeaders",
596           details: {
597             url: getURLNonUTF8SetCookie(),
598           }
599         },
600         { label: "onHeadersReceived",
601           event: "onHeadersReceived",
602           details: {
603             url: getURLNonUTF8SetCookie(),
604             statusLine: "HTTP/1.1 200 OK",
605             responseHeadersExist: true,
606           },
607           retval_function: function(name, details) {
608             responseHeaders = details.responseHeaders;
609             var found = false;
610             var expectedValue = [
611               "F".charCodeAt(0),
612               "o".charCodeAt(0),
613               "o".charCodeAt(0),
614               0x3D, 0xFE, 0xD1
615               ];
616
617             for (var i = 0; i < responseHeaders.length; ++i) {
618               if (responseHeaders[i].name === "Set-Cookie" &&
619                   deepEq(responseHeaders[i].binaryValue, expectedValue)) {
620                 found = true;
621                 responseHeaders.splice(i);
622                 break;
623               }
624             }
625             chrome.test.assertTrue(found);
626             return {responseHeaders: responseHeaders};
627           }
628         },
629         { label: "onResponseStarted",
630           event: "onResponseStarted",
631           details: {
632             url: getURLNonUTF8SetCookie(),
633             fromCache: false,
634             statusCode: 200,
635             statusLine: "HTTP/1.1 200 OK",
636             ip: "127.0.0.1",
637             responseHeadersExist: true,
638           }
639         },
640         { label: "onCompleted",
641           event: "onCompleted",
642           details: {
643             url: getURLNonUTF8SetCookie(),
644             fromCache: false,
645             statusCode: 200,
646             statusLine: "HTTP/1.1 200 OK",
647             ip: "127.0.0.1",
648             responseHeadersExist: true,
649           }
650         },
651       ],
652       [  // event order
653         ["onBeforeRequest", "onBeforeSendHeaders", "onSendHeaders",
654          "onHeadersReceived", "onResponseStarted", "onCompleted"]
655       ],
656       {urls: ["<all_urls>"]}, ["blocking", "responseHeaders"]);
657     // Check that the cookie was really removed.
658     navigateAndWait(getURLNonUTF8SetCookie(), function() {
659       chrome.test.listenOnce(chrome.extension.onRequest, function(request) {
660         chrome.test.assertTrue(request.pass, "Cookie was not removed.");
661       });
662       chrome.tabs.executeScript(tabId,
663       { code: "chrome.extension.sendRequest(" +
664             "{pass: document.cookie.indexOf('Foo') == -1});"
665         });
666     });
667   },
668
669   // Navigates to a page with a blocking handler that redirects to a different
670   // non-http page during onHeadersReceived. The requested page should not be
671   // loaded, and the redirect should succeed.
672   function simpleLoadRedirectOnReceiveHeaders() {
673     expect(
674       [  // events
675         { label: "onBeforeRequest-1",
676           event: "onBeforeRequest",
677           details: {
678             method: "GET",
679             type: "main_frame",
680             url: getURLHttpSimpleLoad(),
681             frameUrl: getURLHttpSimpleLoad()
682           },
683         },
684         { label: "onBeforeSendHeaders",
685           event: "onBeforeSendHeaders",
686           details: {
687             url: getURLHttpSimpleLoad(),
688             // Note: no requestHeaders because we don't ask for them.
689           },
690         },
691         { label: "onSendHeaders",
692           event: "onSendHeaders",
693           details: {
694             url: getURLHttpSimpleLoad()
695           }
696         },
697         { label: "onHeadersReceived",
698           event: "onHeadersReceived",
699           details: {
700             url: getURLHttpSimpleLoad(),
701             statusLine: "HTTP/1.1 200 OK",
702           },
703           retval: {redirectUrl: getURL("simpleLoad/a.html")}
704         },
705         { label: "onBeforeRedirect",
706           event: "onBeforeRedirect",
707           details: {
708             url: getURLHttpSimpleLoad(),
709             redirectUrl: getURL("simpleLoad/a.html"),
710             statusLine: "HTTP/1.1 302 Found",
711             statusCode: 302,
712             fromCache: false,
713             ip: "127.0.0.1",
714           }
715         },
716         { label: "onBeforeRequest-2",
717           event: "onBeforeRequest",
718           details: {
719             url: getURL("simpleLoad/a.html"),
720             frameUrl: getURL("simpleLoad/a.html"),
721           },
722         },
723         { label: "onResponseStarted",
724           event: "onResponseStarted",
725           details: {
726             url: getURL("simpleLoad/a.html"),
727             fromCache: false,
728             statusCode: 200,
729             statusLine: "HTTP/1.1 200 OK",
730             // Request to chrome-extension:// url has no IP.
731           }
732         },
733         { label: "onCompleted",
734           event: "onCompleted",
735           details: {
736             url: getURL("simpleLoad/a.html"),
737             fromCache: false,
738             statusCode: 200,
739             statusLine: "HTTP/1.1 200 OK",
740             // Request to chrome-extension:// url has no IP.
741           }
742         },
743       ],
744       [  // event order
745         ["onBeforeRequest-1", "onBeforeSendHeaders", "onSendHeaders",
746          "onHeadersReceived", "onBeforeRedirect", "onBeforeRequest-2",
747          "onResponseStarted", "onCompleted"]
748       ],
749       {urls: ["<all_urls>"]},  // filter
750       ["blocking"]);
751     navigateAndWait(getURLHttpSimpleLoad());
752   },
753
754   // Checks that synchronous XHR requests from ourself are invisible to blocking
755   // handlers.
756   function syncXhrsFromOurselfAreInvisible() {
757     expect(
758       [  // events
759         { label: "a-onBeforeRequest",
760           event: "onBeforeRequest",
761           details: {
762             url: getURL("simpleLoad/a.html"),
763             frameUrl: getURL("simpleLoad/a.html")
764           }
765         },
766         { label: "a-onResponseStarted",
767           event: "onResponseStarted",
768           details: {
769             url: getURL("simpleLoad/a.html"),
770             statusCode: 200,
771             fromCache: false,
772             statusLine: "HTTP/1.1 200 OK",
773             // Request to chrome-extension:// url has no IP.
774           }
775         },
776         { label: "a-onCompleted",
777           event: "onCompleted",
778           details: {
779             url: getURL("simpleLoad/a.html"),
780             statusCode: 200,
781             fromCache: false,
782             statusLine: "HTTP/1.1 200 OK",
783             // Request to chrome-extension:// url has no IP.
784           }
785         },
786         // We do not see onBeforeRequest for the XHR request here because it is
787         // handled by a blocking handler.
788         { label: "x-onSendHeaders",
789           event: "onSendHeaders",
790           details: {
791             url: getURLHttpXHRData(),
792             tabId: 1,
793             type: "xmlhttprequest",
794           }
795         },
796         { label: "x-onResponseStarted",
797           event: "onResponseStarted",
798           details: {
799             url: getURLHttpXHRData(),
800             statusCode: 200,
801             fromCache: false,
802             statusLine: "HTTP/1.1 200 OK",
803             tabId: 1,
804             type: "xmlhttprequest",
805             ip: "127.0.0.1",
806             // Request to chrome-extension:// url has no IP.
807           }
808         },
809         { label: "x-onCompleted",
810           event: "onCompleted",
811           details: {
812             url: getURLHttpXHRData(),
813             statusCode: 200,
814             fromCache: false,
815             statusLine: "HTTP/1.1 200 OK",
816             tabId: 1,
817             type: "xmlhttprequest",
818             ip: "127.0.0.1",
819             // Request to chrome-extension:// url has no IP.
820           }
821         },
822         { label: "b-onBeforeRequest",
823           event: "onBeforeRequest",
824           details: {
825             url: getURL("complexLoad/b.jpg"),
826             frameUrl: getURL("complexLoad/b.jpg")
827           }
828         },
829         { label: "b-onResponseStarted",
830           event: "onResponseStarted",
831           details: {
832             url: getURL("complexLoad/b.jpg"),
833             statusCode: 200,
834             fromCache: false,
835             statusLine: "HTTP/1.1 200 OK",
836             // Request to chrome-extension:// url has no IP.
837           }
838         },
839         { label: "b-onCompleted",
840           event: "onCompleted",
841           details: {
842             url: getURL("complexLoad/b.jpg"),
843             statusCode: 200,
844             fromCache: false,
845             statusLine: "HTTP/1.1 200 OK",
846             // Request to chrome-extension:// url has no IP.
847           }
848         },
849       ],
850       [  // event order
851         ["a-onBeforeRequest", "a-onResponseStarted", "a-onCompleted",
852          "x-onSendHeaders", "x-onResponseStarted", "x-onCompleted",
853          "b-onBeforeRequest", "b-onResponseStarted", "b-onCompleted"]
854       ],
855       {urls: ["<all_urls>"]}, ["blocking"]);
856     // Check the page content for our modified User-Agent string.
857     navigateAndWait(getURL("simpleLoad/a.html"), function() {
858         var req = new XMLHttpRequest();
859         var asynchronous = false;
860         req.open("GET", getURLHttpXHRData(), asynchronous);
861         req.send(null);
862         navigateAndWait(getURL("complexLoad/b.jpg"));
863     });
864   },
865
866   // Checks that asynchronous XHR requests from ourself are visible to blocking
867   // handlers.
868   function asyncXhrsFromOurselfAreVisible() {
869     expect(
870       [  // events
871         { label: "a-onBeforeRequest",
872           event: "onBeforeRequest",
873           details: {
874             url: getURL("simpleLoad/a.html"),
875             frameUrl: getURL("simpleLoad/a.html")
876           }
877         },
878         { label: "a-onResponseStarted",
879           event: "onResponseStarted",
880           details: {
881             url: getURL("simpleLoad/a.html"),
882             statusCode: 200,
883             fromCache: false,
884             statusLine: "HTTP/1.1 200 OK",
885             // Request to chrome-extension:// url has no IP.
886           }
887         },
888         { label: "a-onCompleted",
889           event: "onCompleted",
890           details: {
891             url: getURL("simpleLoad/a.html"),
892             statusCode: 200,
893             fromCache: false,
894             statusLine: "HTTP/1.1 200 OK",
895             // Request to chrome-extension:// url has no IP.
896           }
897         },
898         {
899           label: "x-onBeforeRequest",
900           event: "onBeforeRequest",
901           details: {
902             url: getURLHttpXHRData(),
903             tabId: 1,
904             type: "xmlhttprequest",
905             frameUrl: "unknown frame URL",
906           }
907         },
908         {
909           label: "x-onBeforeSendHeaders",
910           event: "onBeforeSendHeaders",
911           details: {
912             url: getURLHttpXHRData(),
913             tabId: 1,
914             type: "xmlhttprequest",
915           }
916         },
917         { label: "x-onSendHeaders",
918           event: "onSendHeaders",
919           details: {
920             url: getURLHttpXHRData(),
921             tabId: 1,
922             type: "xmlhttprequest",
923           }
924         },
925         { label: "x-onResponseStarted",
926           event: "onResponseStarted",
927           details: {
928             url: getURLHttpXHRData(),
929             statusCode: 200,
930             fromCache: false,
931             statusLine: "HTTP/1.1 200 OK",
932             tabId: 1,
933             type: "xmlhttprequest",
934             ip: "127.0.0.1",
935             // Request to chrome-extension:// url has no IP.
936           }
937         },
938         {
939           label: "x-onHeadersReceived",
940           event: "onHeadersReceived",
941           details: {
942             url: getURLHttpXHRData(),
943             tabId: 1,
944             type: "xmlhttprequest",
945             statusLine: "HTTP/1.1 200 OK",
946           }
947         },
948         { label: "x-onCompleted",
949           event: "onCompleted",
950           details: {
951             url: getURLHttpXHRData(),
952             statusCode: 200,
953             fromCache: false,
954             statusLine: "HTTP/1.1 200 OK",
955             tabId: 1,
956             type: "xmlhttprequest",
957             ip: "127.0.0.1",
958             // Request to chrome-extension:// url has no IP.
959           }
960         },
961         { label: "b-onBeforeRequest",
962           event: "onBeforeRequest",
963           details: {
964             url: getURL("complexLoad/b.jpg"),
965             frameUrl: getURL("complexLoad/b.jpg")
966           }
967         },
968         { label: "b-onResponseStarted",
969           event: "onResponseStarted",
970           details: {
971             url: getURL("complexLoad/b.jpg"),
972             statusCode: 200,
973             fromCache: false,
974             statusLine: "HTTP/1.1 200 OK",
975             // Request to chrome-extension:// url has no IP.
976           }
977         },
978         { label: "b-onCompleted",
979           event: "onCompleted",
980           details: {
981             url: getURL("complexLoad/b.jpg"),
982             statusCode: 200,
983             fromCache: false,
984             statusLine: "HTTP/1.1 200 OK",
985             // Request to chrome-extension:// url has no IP.
986           }
987         },
988       ],
989       [  // event order
990         ["a-onBeforeRequest", "a-onResponseStarted", "a-onCompleted",
991          "x-onBeforeRequest", "x-onBeforeSendHeaders", "x-onSendHeaders",
992          "x-onHeadersReceived", "x-onResponseStarted", "x-onCompleted"],
993         ["a-onCompleted", "x-onBeforeRequest",
994          "b-onBeforeRequest", "b-onResponseStarted", "b-onCompleted"]
995       ],
996       {urls: ["<all_urls>"]}, ["blocking"]);
997     // Check the page content for our modified User-Agent string.
998     navigateAndWait(getURL("simpleLoad/a.html"), function() {
999         var req = new XMLHttpRequest();
1000         var asynchronous = true;
1001         req.open("GET", getURLHttpXHRData(), asynchronous);
1002         req.send(null);
1003         navigateAndWait(getURL("complexLoad/b.jpg"));
1004     });
1005   },
1006 ]);
1007
1008
1009 // This helper verifies that extensions can successfully redirect resources even
1010 // if cross-origin access control is in effect via the crossorigin attribute.
1011 // Used by crossOriginAnonymousRedirect and crossOriginCredentialedRedirect.
1012 function testLoadCORSImage(crossOriginAttributeValue) {
1013   // (Non-existent) image URL, with random query string to bust the cache.
1014   var requestedUrl = getServerURL("cors/intercepted_by_extension.gif?" +
1015                                   Math.random(), "original.tld");
1016   var frameUrl = getServerURL(
1017       "extensions/api_test/webrequest/cors/load_image.html?" +
1018       "crossOrigin=" + crossOriginAttributeValue +
1019       "&src=" + encodeURIComponent(requestedUrl));
1020   var redirectTarget = getServerURL(
1021       "extensions/api_test/webrequest/cors/redirect_target.gif", "domain.tld");
1022   expect(
1023     [  // events
1024       { label: "onBeforeRequest-1",
1025         event: "onBeforeRequest",
1026         details: {
1027           type: "image",
1028           url: requestedUrl,
1029           // Frame URL unavailable because requests are filtered by type=image.
1030           frameUrl: "unknown frame URL",
1031         },
1032         retval: {redirectUrl: redirectTarget}
1033       },
1034       { label: "onBeforeRedirect",
1035         event: "onBeforeRedirect",
1036         details: {
1037           type: "image",
1038           url: requestedUrl,
1039           redirectUrl: redirectTarget,
1040           statusLine: "HTTP/1.1 307 Internal Redirect",
1041           statusCode: 307,
1042           fromCache: false,
1043         }
1044       },
1045       { label: "onBeforeRequest-2",
1046         event: "onBeforeRequest",
1047         details: {
1048           type: "image",
1049           url: redirectTarget,
1050           // Frame URL unavailable because requests are filtered by type=image.
1051           frameUrl: "unknown frame URL",
1052         },
1053       },
1054       {
1055         label: "onBeforeSendHeaders",
1056         event: "onBeforeSendHeaders",
1057         details: {
1058           type: "image",
1059           url: redirectTarget,
1060         }
1061       },
1062       {
1063         label: "onSendHeaders",
1064         event: "onSendHeaders",
1065         details: {
1066           type: "image",
1067           url: redirectTarget,
1068         }
1069       },
1070       {
1071         label: "onHeadersReceived",
1072         event: "onHeadersReceived",
1073         details: {
1074           type: "image",
1075           url: redirectTarget,
1076           statusLine: "HTTP/1.1 200 OK",
1077         }
1078       },
1079       { label: "onResponseStarted",
1080         event: "onResponseStarted",
1081         details: {
1082           type: "image",
1083           url: redirectTarget,
1084           fromCache: false,
1085           statusCode: 200,
1086           ip: "127.0.0.1",
1087           statusLine: "HTTP/1.1 200 OK",
1088         }
1089       },
1090       { label: "onCompleted",
1091         event: "onCompleted",
1092         details: {
1093           type: "image",
1094           url: redirectTarget,
1095           fromCache: false,
1096           statusCode: 200,
1097           ip: "127.0.0.1",
1098           statusLine: "HTTP/1.1 200 OK",
1099         }
1100       },
1101       // After the image loads, the test will load the following URL
1102       // to signal that the test succeeded.
1103       {
1104         label: "onBeforeRequest-3",
1105         event: "onBeforeRequest",
1106         details: {
1107           type: "image",
1108           url: getServerURL("signal_that_image_loaded_successfully"),
1109           // Frame URL unavailable because requests are filtered by type=image.
1110           frameUrl: "unknown frame URL",
1111         },
1112         retval: {cancel: true}
1113       },
1114       { label: "onErrorOccurred",
1115         event: "onErrorOccurred",
1116         details: {
1117           type: "image",
1118           url: getServerURL("signal_that_image_loaded_successfully"),
1119           fromCache: false,
1120           error: "net::ERR_BLOCKED_BY_CLIENT",
1121         }
1122       },
1123     ],
1124     [  // event order
1125       ["onBeforeRequest-1", "onBeforeRedirect", "onBeforeRequest-2",
1126        "onBeforeSendHeaders", "onSendHeaders", "onHeadersReceived",
1127        "onResponseStarted", "onCompleted",
1128        "onBeforeRequest-3", "onErrorOccurred"],
1129     ],
1130     {urls: ["<all_urls>"], types: ['image']}, // filter
1131     ["blocking"]);
1132   navigateAndWait(frameUrl);
1133 }