Upstream version 7.36.149.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             statusLine: "",
284             statusCode: -1,
285             fromCache: false,
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   // Loads a testserver page that echoes the User-Agent header that was
326   // sent to fetch it. We modify the outgoing User-Agent in
327   // onBeforeSendHeaders, so we should see that modified version.
328   function modifyRequestHeaders() {
329     expect(
330       [  // events
331         { label: "onBeforeRequest",
332           event: "onBeforeRequest",
333           details: {
334             url: getURLEchoUserAgent(),
335             frameUrl: getURLEchoUserAgent()
336           }
337         },
338         { label: "onBeforeSendHeaders",
339           event: "onBeforeSendHeaders",
340           details: {
341             url: getURLEchoUserAgent(),
342             // Note: no requestHeaders because we don't ask for them.
343           },
344           retval: {requestHeaders: [{name: "User-Agent", value: "FoobarUA"}]}
345         },
346         { label: "onSendHeaders",
347           event: "onSendHeaders",
348           details: {
349             url: getURLEchoUserAgent()
350           }
351         },
352         { label: "onHeadersReceived",
353           event: "onHeadersReceived",
354           details: {
355             url: getURLEchoUserAgent(),
356             statusLine: "HTTP/1.1 200 OK",
357           }
358         },
359         { label: "onResponseStarted",
360           event: "onResponseStarted",
361           details: {
362             url: getURLEchoUserAgent(),
363             fromCache: false,
364             statusCode: 200,
365             ip: "127.0.0.1",
366             statusLine: "HTTP/1.1 200 OK",
367           }
368         },
369         { label: "onCompleted",
370           event: "onCompleted",
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       ],
380       [  // event order
381         ["onBeforeRequest", "onBeforeSendHeaders", "onSendHeaders",
382          "onHeadersReceived", "onResponseStarted", "onCompleted"]
383       ],
384       {urls: ["<all_urls>"]}, ["blocking"]);
385     // Check the page content for our modified User-Agent string.
386     navigateAndWait(getURLEchoUserAgent(), function() {
387       chrome.test.listenOnce(chrome.extension.onRequest, function(request) {
388         chrome.test.assertTrue(request.pass, "Request header was not set.");
389       });
390       chrome.tabs.executeScript(tabId,
391         {
392           code: "chrome.extension.sendRequest(" +
393               "{pass: document.body.innerText.indexOf('FoobarUA') >= 0});"
394         });
395     });
396   },
397
398   // Loads a testserver page that echoes the User-Agent header that was
399   // sent to fetch it. We modify the outgoing User-Agent in
400   // onBeforeSendHeaders, so we should see that modified version.
401   // In this version we check whether we can set binary header values.
402   function modifyBinaryRequestHeaders() {
403     expect(
404       [  // events
405         { label: "onBeforeRequest",
406           event: "onBeforeRequest",
407           details: {
408             url: getURLEchoUserAgent(),
409             frameUrl: getURLEchoUserAgent()
410           }
411         },
412         { label: "onBeforeSendHeaders",
413           event: "onBeforeSendHeaders",
414           details: {
415             url: getURLEchoUserAgent(),
416             // Note: no requestHeaders because we don't ask for them.
417           },
418           retval: {requestHeaders: [{name: "User-Agent",
419                                      binaryValue: toCharCodes("FoobarUA")}]}
420         },
421         { label: "onSendHeaders",
422           event: "onSendHeaders",
423           details: {
424             url: getURLEchoUserAgent()
425           }
426         },
427         { label: "onHeadersReceived",
428           event: "onHeadersReceived",
429           details: {
430             url: getURLEchoUserAgent(),
431             statusLine: "HTTP/1.1 200 OK",
432           }
433         },
434         { label: "onResponseStarted",
435           event: "onResponseStarted",
436           details: {
437             url: getURLEchoUserAgent(),
438             fromCache: false,
439             statusCode: 200,
440             ip: "127.0.0.1",
441             statusLine: "HTTP/1.1 200 OK",
442           }
443         },
444         { label: "onCompleted",
445           event: "onCompleted",
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       ],
455       [  // event order
456         ["onBeforeRequest", "onBeforeSendHeaders", "onSendHeaders",
457          "onHeadersReceived", "onResponseStarted", "onCompleted"]
458       ],
459       {urls: ["<all_urls>"]}, ["blocking"]);
460     // Check the page content for our modified User-Agent string.
461     navigateAndWait(getURLEchoUserAgent(), function() {
462       chrome.test.listenOnce(chrome.extension.onRequest, function(request) {
463         chrome.test.assertTrue(request.pass, "Request header was not set.");
464       });
465       chrome.tabs.executeScript(tabId,
466         {
467           code: "chrome.extension.sendRequest(" +
468               "{pass: document.body.innerText.indexOf('FoobarUA') >= 0});"
469         });
470     });
471   },
472
473   // Loads a testserver page that sets a cookie "Foo=Bar" but removes
474   // the cookies from the response headers so that they are not set.
475   function modifyResponseHeaders() {
476     expect(
477       [  // events
478         { label: "onBeforeRequest",
479           event: "onBeforeRequest",
480           details: {
481             method: "GET",
482             type: "main_frame",
483             url: getURLSetCookie(),
484             frameUrl: getURLSetCookie()
485           }
486         },
487         { label: "onBeforeSendHeaders",
488           event: "onBeforeSendHeaders",
489           details: {
490             url: getURLSetCookie(),
491             // Note: no requestHeaders because we don't ask for them.
492           },
493         },
494         { label: "onSendHeaders",
495           event: "onSendHeaders",
496           details: {
497             url: getURLSetCookie(),
498           }
499         },
500         { label: "onHeadersReceived",
501           event: "onHeadersReceived",
502           details: {
503             url: getURLSetCookie(),
504             statusLine: "HTTP/1.1 200 OK",
505             responseHeadersExist: true,
506           },
507           retval_function: function(name, details) {
508             responseHeaders = details.responseHeaders;
509             var found = false;
510             for (var i = 0; i < responseHeaders.length; ++i) {
511               if (responseHeaders[i].name === "Set-Cookie" &&
512                   responseHeaders[i].value.indexOf("Foo") != -1) {
513                 found = true;
514                 responseHeaders.splice(i);
515                 break;
516               }
517             }
518             chrome.test.assertTrue(found);
519             return {responseHeaders: responseHeaders};
520           }
521         },
522         { label: "onResponseStarted",
523           event: "onResponseStarted",
524           details: {
525             url: getURLSetCookie(),
526             fromCache: false,
527             statusCode: 200,
528             statusLine: "HTTP/1.1 200 OK",
529             ip: "127.0.0.1",
530             responseHeadersExist: true,
531           }
532         },
533         { label: "onCompleted",
534           event: "onCompleted",
535           details: {
536             url: getURLSetCookie(),
537             fromCache: false,
538             statusCode: 200,
539             statusLine: "HTTP/1.1 200 OK",
540             ip: "127.0.0.1",
541             responseHeadersExist: true,
542           }
543         },
544       ],
545       [  // event order
546         ["onBeforeRequest", "onBeforeSendHeaders", "onSendHeaders",
547          "onHeadersReceived", "onResponseStarted", "onCompleted"]
548       ],
549       {urls: ["<all_urls>"]}, ["blocking", "responseHeaders"]);
550     // Check that the cookie was really removed.
551     navigateAndWait(getURLSetCookie(), function() {
552       chrome.test.listenOnce(chrome.extension.onRequest, function(request) {
553         chrome.test.assertTrue(request.pass, "Cookie was not removed.");
554       });
555       chrome.tabs.executeScript(tabId,
556       { code: "chrome.extension.sendRequest(" +
557             "{pass: document.cookie.indexOf('Foo') == -1});"
558         });
559     });
560   },
561
562   // Loads a testserver page that sets a cookie "Foo=U+FDD1" which is not a
563   // valid UTF-8 code point. Therefore, it cannot be passed to JavaScript
564   // as a normal string.
565   function handleNonUTF8InModifyResponseHeaders() {
566     expect(
567       [  // events
568         { label: "onBeforeRequest",
569           event: "onBeforeRequest",
570           details: {
571             method: "GET",
572             type: "main_frame",
573             url: getURLNonUTF8SetCookie(),
574             frameUrl: getURLNonUTF8SetCookie()
575           }
576         },
577         { label: "onBeforeSendHeaders",
578           event: "onBeforeSendHeaders",
579           details: {
580             url: getURLNonUTF8SetCookie(),
581             // Note: no requestHeaders because we don't ask for them.
582           },
583         },
584         { label: "onSendHeaders",
585           event: "onSendHeaders",
586           details: {
587             url: getURLNonUTF8SetCookie(),
588           }
589         },
590         { label: "onHeadersReceived",
591           event: "onHeadersReceived",
592           details: {
593             url: getURLNonUTF8SetCookie(),
594             statusLine: "HTTP/1.1 200 OK",
595             responseHeadersExist: true,
596           },
597           retval_function: function(name, details) {
598             responseHeaders = details.responseHeaders;
599             var found = false;
600             var expectedValue = [
601               "F".charCodeAt(0),
602               "o".charCodeAt(0),
603               "o".charCodeAt(0),
604               0x3D, 0xFE, 0xD1
605               ];
606
607             for (var i = 0; i < responseHeaders.length; ++i) {
608               if (responseHeaders[i].name === "Set-Cookie" &&
609                   deepEq(responseHeaders[i].binaryValue, expectedValue)) {
610                 found = true;
611                 responseHeaders.splice(i);
612                 break;
613               }
614             }
615             chrome.test.assertTrue(found);
616             return {responseHeaders: responseHeaders};
617           }
618         },
619         { label: "onResponseStarted",
620           event: "onResponseStarted",
621           details: {
622             url: getURLNonUTF8SetCookie(),
623             fromCache: false,
624             statusCode: 200,
625             statusLine: "HTTP/1.1 200 OK",
626             ip: "127.0.0.1",
627             responseHeadersExist: true,
628           }
629         },
630         { label: "onCompleted",
631           event: "onCompleted",
632           details: {
633             url: getURLNonUTF8SetCookie(),
634             fromCache: false,
635             statusCode: 200,
636             statusLine: "HTTP/1.1 200 OK",
637             ip: "127.0.0.1",
638             responseHeadersExist: true,
639           }
640         },
641       ],
642       [  // event order
643         ["onBeforeRequest", "onBeforeSendHeaders", "onSendHeaders",
644          "onHeadersReceived", "onResponseStarted", "onCompleted"]
645       ],
646       {urls: ["<all_urls>"]}, ["blocking", "responseHeaders"]);
647     // Check that the cookie was really removed.
648     navigateAndWait(getURLNonUTF8SetCookie(), function() {
649       chrome.test.listenOnce(chrome.extension.onRequest, function(request) {
650         chrome.test.assertTrue(request.pass, "Cookie was not removed.");
651       });
652       chrome.tabs.executeScript(tabId,
653       { code: "chrome.extension.sendRequest(" +
654             "{pass: document.cookie.indexOf('Foo') == -1});"
655         });
656     });
657   },
658
659   // Navigates to a page with a blocking handler that redirects to a different
660   // non-http page during onHeadersReceived. The requested page should not be
661   // loaded, and the redirect should succeed.
662   function simpleLoadRedirectOnReceiveHeaders() {
663     expect(
664       [  // events
665         { label: "onBeforeRequest-1",
666           event: "onBeforeRequest",
667           details: {
668             method: "GET",
669             type: "main_frame",
670             url: getURLHttpSimpleLoad(),
671             frameUrl: getURLHttpSimpleLoad()
672           },
673         },
674         { label: "onBeforeSendHeaders",
675           event: "onBeforeSendHeaders",
676           details: {
677             url: getURLHttpSimpleLoad(),
678             // Note: no requestHeaders because we don't ask for them.
679           },
680         },
681         { label: "onSendHeaders",
682           event: "onSendHeaders",
683           details: {
684             url: getURLHttpSimpleLoad()
685           }
686         },
687         { label: "onHeadersReceived",
688           event: "onHeadersReceived",
689           details: {
690             url: getURLHttpSimpleLoad(),
691             statusLine: "HTTP/1.1 200 OK",
692           },
693           retval: {redirectUrl: getURL("simpleLoad/a.html")}
694         },
695         { label: "onBeforeRedirect",
696           event: "onBeforeRedirect",
697           details: {
698             url: getURLHttpSimpleLoad(),
699             redirectUrl: getURL("simpleLoad/a.html"),
700             statusLine: "HTTP/1.1 302 Found",
701             statusCode: 302,
702             fromCache: false,
703             ip: "127.0.0.1",
704           }
705         },
706         { label: "onBeforeRequest-2",
707           event: "onBeforeRequest",
708           details: {
709             url: getURL("simpleLoad/a.html"),
710             frameUrl: getURL("simpleLoad/a.html"),
711           },
712         },
713         { label: "onResponseStarted",
714           event: "onResponseStarted",
715           details: {
716             url: getURL("simpleLoad/a.html"),
717             fromCache: false,
718             statusCode: 200,
719             statusLine: "HTTP/1.1 200 OK",
720             // Request to chrome-extension:// url has no IP.
721           }
722         },
723         { label: "onCompleted",
724           event: "onCompleted",
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       ],
734       [  // event order
735         ["onBeforeRequest-1", "onBeforeSendHeaders", "onSendHeaders",
736          "onHeadersReceived", "onBeforeRedirect", "onBeforeRequest-2",
737          "onResponseStarted", "onCompleted"]
738       ],
739       {urls: ["<all_urls>"]},  // filter
740       ["blocking"]);
741     navigateAndWait(getURLHttpSimpleLoad());
742   },
743
744   // Checks that synchronous XHR requests from ourself are invisible to blocking
745   // handlers.
746   function syncXhrsFromOurselfAreInvisible() {
747     expect(
748       [  // events
749         { label: "a-onBeforeRequest",
750           event: "onBeforeRequest",
751           details: {
752             url: getURL("simpleLoad/a.html"),
753             frameUrl: getURL("simpleLoad/a.html")
754           }
755         },
756         { label: "a-onResponseStarted",
757           event: "onResponseStarted",
758           details: {
759             url: getURL("simpleLoad/a.html"),
760             statusCode: 200,
761             fromCache: false,
762             statusLine: "HTTP/1.1 200 OK",
763             // Request to chrome-extension:// url has no IP.
764           }
765         },
766         { label: "a-onCompleted",
767           event: "onCompleted",
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         // We do not see onBeforeRequest for the XHR request here because it is
777         // handled by a blocking handler.
778         { label: "x-onSendHeaders",
779           event: "onSendHeaders",
780           details: {
781             url: getURLHttpXHRData(),
782             tabId: 1,
783             type: "xmlhttprequest",
784           }
785         },
786         { label: "x-onResponseStarted",
787           event: "onResponseStarted",
788           details: {
789             url: getURLHttpXHRData(),
790             statusCode: 200,
791             fromCache: false,
792             statusLine: "HTTP/1.1 200 OK",
793             tabId: 1,
794             type: "xmlhttprequest",
795             ip: "127.0.0.1",
796             // Request to chrome-extension:// url has no IP.
797           }
798         },
799         { label: "x-onCompleted",
800           event: "onCompleted",
801           details: {
802             url: getURLHttpXHRData(),
803             statusCode: 200,
804             fromCache: false,
805             statusLine: "HTTP/1.1 200 OK",
806             tabId: 1,
807             type: "xmlhttprequest",
808             ip: "127.0.0.1",
809             // Request to chrome-extension:// url has no IP.
810           }
811         },
812         { label: "b-onBeforeRequest",
813           event: "onBeforeRequest",
814           details: {
815             url: getURL("complexLoad/b.jpg"),
816             frameUrl: getURL("complexLoad/b.jpg")
817           }
818         },
819         { label: "b-onResponseStarted",
820           event: "onResponseStarted",
821           details: {
822             url: getURL("complexLoad/b.jpg"),
823             statusCode: 200,
824             fromCache: false,
825             statusLine: "HTTP/1.1 200 OK",
826             // Request to chrome-extension:// url has no IP.
827           }
828         },
829         { label: "b-onCompleted",
830           event: "onCompleted",
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       ],
840       [  // event order
841         ["a-onBeforeRequest", "a-onResponseStarted", "a-onCompleted",
842          "x-onSendHeaders", "x-onResponseStarted", "x-onCompleted",
843          "b-onBeforeRequest", "b-onResponseStarted", "b-onCompleted"]
844       ],
845       {urls: ["<all_urls>"]}, ["blocking"]);
846     // Check the page content for our modified User-Agent string.
847     navigateAndWait(getURL("simpleLoad/a.html"), function() {
848         var req = new XMLHttpRequest();
849         var asynchronous = false;
850         req.open("GET", getURLHttpXHRData(), asynchronous);
851         req.send(null);
852         navigateAndWait(getURL("complexLoad/b.jpg"));
853     });
854   },
855
856   // Checks that asynchronous XHR requests from ourself are visible to blocking
857   // handlers.
858   function asyncXhrsFromOurselfAreVisible() {
859     expect(
860       [  // events
861         { label: "a-onBeforeRequest",
862           event: "onBeforeRequest",
863           details: {
864             url: getURL("simpleLoad/a.html"),
865             frameUrl: getURL("simpleLoad/a.html")
866           }
867         },
868         { label: "a-onResponseStarted",
869           event: "onResponseStarted",
870           details: {
871             url: getURL("simpleLoad/a.html"),
872             statusCode: 200,
873             fromCache: false,
874             statusLine: "HTTP/1.1 200 OK",
875             // Request to chrome-extension:// url has no IP.
876           }
877         },
878         { label: "a-onCompleted",
879           event: "onCompleted",
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         {
889           label: "x-onBeforeRequest",
890           event: "onBeforeRequest",
891           details: {
892             url: getURLHttpXHRData(),
893             tabId: 1,
894             type: "xmlhttprequest",
895             frameUrl: "unknown frame URL",
896           }
897         },
898         {
899           label: "x-onBeforeSendHeaders",
900           event: "onBeforeSendHeaders",
901           details: {
902             url: getURLHttpXHRData(),
903             tabId: 1,
904             type: "xmlhttprequest",
905           }
906         },
907         { label: "x-onSendHeaders",
908           event: "onSendHeaders",
909           details: {
910             url: getURLHttpXHRData(),
911             tabId: 1,
912             type: "xmlhttprequest",
913           }
914         },
915         { label: "x-onResponseStarted",
916           event: "onResponseStarted",
917           details: {
918             url: getURLHttpXHRData(),
919             statusCode: 200,
920             fromCache: false,
921             statusLine: "HTTP/1.1 200 OK",
922             tabId: 1,
923             type: "xmlhttprequest",
924             ip: "127.0.0.1",
925             // Request to chrome-extension:// url has no IP.
926           }
927         },
928         {
929           label: "x-onHeadersReceived",
930           event: "onHeadersReceived",
931           details: {
932             url: getURLHttpXHRData(),
933             tabId: 1,
934             type: "xmlhttprequest",
935             statusLine: "HTTP/1.1 200 OK",
936           }
937         },
938         { label: "x-onCompleted",
939           event: "onCompleted",
940           details: {
941             url: getURLHttpXHRData(),
942             statusCode: 200,
943             fromCache: false,
944             statusLine: "HTTP/1.1 200 OK",
945             tabId: 1,
946             type: "xmlhttprequest",
947             ip: "127.0.0.1",
948             // Request to chrome-extension:// url has no IP.
949           }
950         },
951         { label: "b-onBeforeRequest",
952           event: "onBeforeRequest",
953           details: {
954             url: getURL("complexLoad/b.jpg"),
955             frameUrl: getURL("complexLoad/b.jpg")
956           }
957         },
958         { label: "b-onResponseStarted",
959           event: "onResponseStarted",
960           details: {
961             url: getURL("complexLoad/b.jpg"),
962             statusCode: 200,
963             fromCache: false,
964             statusLine: "HTTP/1.1 200 OK",
965             // Request to chrome-extension:// url has no IP.
966           }
967         },
968         { label: "b-onCompleted",
969           event: "onCompleted",
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       ],
979       [  // event order
980         ["a-onBeforeRequest", "a-onResponseStarted", "a-onCompleted",
981          "x-onBeforeRequest", "x-onBeforeSendHeaders", "x-onSendHeaders",
982          "x-onHeadersReceived", "x-onResponseStarted", "x-onCompleted"],
983         ["a-onCompleted", "x-onBeforeRequest",
984          "b-onBeforeRequest", "b-onResponseStarted", "b-onCompleted"]
985       ],
986       {urls: ["<all_urls>"]}, ["blocking"]);
987     // Check the page content for our modified User-Agent string.
988     navigateAndWait(getURL("simpleLoad/a.html"), function() {
989         var req = new XMLHttpRequest();
990         var asynchronous = true;
991         req.open("GET", getURLHttpXHRData(), asynchronous);
992         req.send(null);
993         navigateAndWait(getURL("complexLoad/b.jpg"));
994     });
995   },
996 ]);