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 |