| Index: chrome/test/data/extensions/api_test/webrequest/events/test.html
|
| diff --git a/chrome/test/data/extensions/api_test/webrequest/events/test.html b/chrome/test/data/extensions/api_test/webrequest/events/test.html
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..c692844cfc4da5f29471d50229878f33c0a3ace0
|
| --- /dev/null
|
| +++ b/chrome/test/data/extensions/api_test/webrequest/events/test.html
|
| @@ -0,0 +1,928 @@
|
| +<script>
|
| +var getURL = chrome.extension.getURL;
|
| +var deepEq = chrome.test.checkDeepEq;
|
| +var expectedEventData;
|
| +var capturedEventData;
|
| +var expectedEventOrder;
|
| +var tabId;
|
| +var eventsCaptured;
|
| +
|
| +// PORT will be changed to the port of the test server.
|
| +var URL_HTTP_SIMPLE_LOAD =
|
| + 'http://www.a.com:PORT/files/extensions/api_test/webrequest/events/simpleLoad/a.html';
|
| +var URL_HTTP_SIMPLE_LOAD_REDIRECT =
|
| + 'http://www.a.com:PORT/server-redirect?'+URL_HTTP_SIMPLE_LOAD;
|
| +var URL_ECHO_USER_AGENT =
|
| + 'http://www.a.com:PORT/echoheader?User-Agent';
|
| +var URL_AUTH_REQUIRED =
|
| + 'http://www.a.com:PORT/auth-basic';
|
| +var URL_HTTP_XHR =
|
| + 'http://www.a.com:PORT/files/extensions/api_test/webrequest/events/xhr/a.html';
|
| +var URL_HTTP_XHR_DATA =
|
| + 'http://www.a.com:PORT/files/extensions/api_test/webrequest/events/xhr/data.json';
|
| +
|
| +function runTests(tests) {
|
| + chrome.tabs.getSelected(null, function(tab) {
|
| + tabId = tab.id;
|
| + chrome.test.getConfig(function(config) {
|
| + var fixPort = function(url) {
|
| + return url.replace(/PORT/g, config.testServer.port);
|
| + };
|
| + URL_HTTP_SIMPLE_LOAD = fixPort(URL_HTTP_SIMPLE_LOAD);
|
| + URL_HTTP_SIMPLE_LOAD_REDIRECT = fixPort(URL_HTTP_SIMPLE_LOAD_REDIRECT);
|
| + URL_ECHO_USER_AGENT = fixPort(URL_ECHO_USER_AGENT);
|
| + URL_AUTH_REQUIRED = fixPort(URL_AUTH_REQUIRED);
|
| + URL_HTTP_XHR = fixPort(URL_HTTP_XHR);
|
| + URL_HTTP_XHR_DATA = fixPort(URL_HTTP_XHR_DATA);
|
| +
|
| + chrome.test.runTests(tests);
|
| + });
|
| + });
|
| +}
|
| +
|
| +// Helper to advance to the next test only when the tab has finished loading.
|
| +// This is because tabs.update can sometimes fail if the tab is in the middle
|
| +// of a navigation (from the previous test), resulting in flakiness.
|
| +function navigateAndWait(url, callback) {
|
| + var done = chrome.test.listenForever(chrome.tabs.onUpdated,
|
| + function (_, info, tab) {
|
| + if (tab.id == tabId && info.status == "complete") {
|
| + if (callback) callback();
|
| + done();
|
| + }
|
| + });
|
| + chrome.tabs.update(tabId, {url: url});
|
| +}
|
| +
|
| +// data: array of extected events, each one is a dictionary:
|
| +// { label: "<unique identifier>",
|
| +// event: "<webrequest event type>",
|
| +// details: { <expected details of the webrequest event> },
|
| +// retval: { <dictionary that the event handler shall return> } (optional)
|
| +// }
|
| +// order: an array of sequences, e.g. [ ["a", "b", "c"], ["d", "e"] ] means that
|
| +// event with label "a" needs to occur before event with label "b". The
|
| +// relative order of "a" and "d" does not matter.
|
| +// filter: filter dictionary passed on to the event subscription of the
|
| +// webRequest API.
|
| +// extraInfoSpec: the union of all desired extraInfoSpecs for the events.
|
| +function expect(data, order, filter, extraInfoSpec) {
|
| + expectedEventData = data;
|
| + capturedEventData = [];
|
| + expectedEventOrder = order;
|
| + eventsCaptured = chrome.test.callbackAdded();
|
| + tabAndFrameUrls = {}; // Maps "{tabId}-{frameId}" to the URL of the frame.
|
| + removeListeners();
|
| + initListeners(filter || {}, extraInfoSpec || []);
|
| +}
|
| +
|
| +function checkExpectations() {
|
| + if (capturedEventData.length < expectedEventData.length) {
|
| + return;
|
| + }
|
| + if (capturedEventData.length > expectedEventData.length) {
|
| + chrome.test.fail("Recorded too many events. " +
|
| + JSON.stringify(capturedEventData));
|
| + return;
|
| + }
|
| + // We have ensured that capturedEventData contains exactly the same elements
|
| + // as expectedEventData. Now we need to verify the ordering.
|
| + // Step 1: build positions such that
|
| + // positions[<event-label>]=<position of this event in capturedEventData>
|
| + var curPos = 0;
|
| + var positions = {}
|
| + capturedEventData.forEach(function (event) {
|
| + chrome.test.assertTrue(event.hasOwnProperty("label"));
|
| + positions[event.label] = curPos;
|
| + curPos++;
|
| + });
|
| + // Step 2: check that elements arrived in correct order
|
| + expectedEventOrder.forEach(function (order) {
|
| + var previousLabel = undefined;
|
| + order.forEach(function(label) {
|
| + if (previousLabel === undefined) {
|
| + previousLabel = label;
|
| + return;
|
| + }
|
| + chrome.test.assertTrue(positions[previousLabel] < positions[label],
|
| + "Event " + previousLabel + " is supposed to arrive before " +
|
| + label + ".");
|
| + previousLabel = label;
|
| + });
|
| + });
|
| +
|
| + eventsCaptured();
|
| +}
|
| +
|
| +// Simple check to see that we have a User-Agent header, and that it contains
|
| +// an expected value. This is a basic check that the request headers are valid.
|
| +function checkUserAgent(headers) {
|
| + for (var i in headers) {
|
| + if (headers[i].name.toLowerCase() == "user-agent")
|
| + return headers[i].value.toLowerCase().indexOf("chrome") != -1;
|
| + }
|
| + return false;
|
| +}
|
| +
|
| +function captureEvent(name, details) {
|
| + // Ignore system-level requests like safebrowsing updates and favicon fetches
|
| + // since they are unpredictable.
|
| + if (details.tabId == -1 || details.type == "other" ||
|
| + details.url.match(/\/favicon.ico$/) ||
|
| + details.url.match(/https:\/\/dl.google.com/))
|
| + return;
|
| +
|
| + // Pull the extra per-event options out of the expected data. These let
|
| + // us specify special return values per event.
|
| + var currentIndex = capturedEventData.length;
|
| + var extraOptions;
|
| + if (expectedEventData.length > currentIndex) {
|
| + retval = expectedEventData[currentIndex].retval;
|
| + }
|
| +
|
| + // Check that the frameId can be used to reliably determine the URL of the
|
| + // frame that caused requests.
|
| + if (name == "onBeforeRequest") {
|
| + chrome.test.assertTrue('frameId' in details &&
|
| + typeof details.frameId === 'number');
|
| + chrome.test.assertTrue('tabId' in details &&
|
| + typeof details.tabId === 'number');
|
| + var key = details.tabId + "-" + details.frameId;
|
| + if (details.type == "main_frame" || details.type == "sub_frame") {
|
| + tabAndFrameUrls[key] = details.url;
|
| + }
|
| + details.frameUrl = tabAndFrameUrls[key] || "unknown frame URL";
|
| + }
|
| + delete details.frameId;
|
| +
|
| + delete details.requestId;
|
| + delete details.timeStamp;
|
| + if (details.requestHeaders) {
|
| + details.requestHeadersValid = checkUserAgent(details.requestHeaders);
|
| + delete details.requestHeaders;
|
| + }
|
| + if (details.responseHeaders) {
|
| + details.responseHeadersExist = true;
|
| + delete details.responseHeaders;
|
| + }
|
| +
|
| + // find |details| in expectedEventData
|
| + var found = false;
|
| + var label = undefined;
|
| + expectedEventData.forEach(function (exp) {
|
| + if (deepEq(exp.event, name) && deepEq(exp.details, details)) {
|
| + if (found) {
|
| + chrome.test.fail("Received event twice '" + name + "':" +
|
| + JSON.stringify(details));
|
| + } else {
|
| + found = true;
|
| + label = exp.label;
|
| + }
|
| + }
|
| + });
|
| + if (!found) {
|
| + chrome.test.fail("Received unexpected event '" + name + "':" +
|
| + JSON.stringify(details));
|
| + }
|
| +
|
| + capturedEventData.push({label: label, event: name, details: details});
|
| + checkExpectations();
|
| + return retval;
|
| +}
|
| +
|
| +// Simple array intersection. We use this to filter extraInfoSpec so
|
| +// that only the allowed specs are sent to each listener.
|
| +function intersect(array1, array2) {
|
| + return array1.filter(function(x) { return array2.indexOf(x) != -1; });
|
| +}
|
| +
|
| +function initListeners(filter, extraInfoSpec) {
|
| + chrome.experimental.webRequest.onBeforeRequest.addListener(
|
| + function(details) {
|
| + return captureEvent("onBeforeRequest", details);
|
| + }, filter, intersect(extraInfoSpec, ["blocking"]));
|
| + chrome.experimental.webRequest.onBeforeSendHeaders.addListener(
|
| + function(details) {
|
| + return captureEvent("onBeforeSendHeaders", details);
|
| + }, filter, intersect(extraInfoSpec, ["blocking", "requestHeaders"]));
|
| + chrome.experimental.webRequest.onSendHeaders.addListener(
|
| + function(details) {
|
| + return captureEvent("onSendHeaders", details);
|
| + }, filter, intersect(extraInfoSpec, ["requestHeaders"]));
|
| + chrome.experimental.webRequest.onAuthRequired.addListener(
|
| + function(details) {
|
| + return captureEvent("onAuthRequired", details);
|
| + }, filter, intersect(extraInfoSpec, ["responseHeaders", "statusLine"]));
|
| + chrome.experimental.webRequest.onResponseStarted.addListener(
|
| + function(details) {
|
| + return captureEvent("onResponseStarted", details);
|
| + }, filter, intersect(extraInfoSpec, ["responseHeaders", "statusLine"]));
|
| + chrome.experimental.webRequest.onBeforeRedirect.addListener(
|
| + function(details) {
|
| + return captureEvent("onBeforeRedirect", details);
|
| + }, filter, intersect(extraInfoSpec, ["responseHeaders", "statusLine"]));
|
| + chrome.experimental.webRequest.onCompleted.addListener(
|
| + function(details) {
|
| + return captureEvent("onCompleted", details);
|
| + }, filter, intersect(extraInfoSpec, ["responseHeaders", "statusLine"]));
|
| + chrome.experimental.webRequest.onErrorOccurred.addListener(
|
| + function(details) {
|
| + return captureEvent("onErrorOccurred", details);
|
| + }, filter);
|
| +}
|
| +
|
| +function removeListeners() {
|
| + function helper(event) {
|
| + // Note: We're poking at the internal event data, but it's easier than
|
| + // the alternative. If this starts failing, we just need to update this
|
| + // helper.
|
| + for (var cb in event.callbackMap_) {
|
| + event.removeListener(cb);
|
| + }
|
| + chrome.test.assertFalse(event.hasListeners());
|
| + }
|
| + helper(chrome.experimental.webRequest.onBeforeRequest);
|
| + helper(chrome.experimental.webRequest.onBeforeSendHeaders);
|
| + helper(chrome.experimental.webRequest.onAuthRequired);
|
| + helper(chrome.experimental.webRequest.onSendHeaders);
|
| + helper(chrome.experimental.webRequest.onResponseStarted);
|
| + helper(chrome.experimental.webRequest.onBeforeRedirect);
|
| + helper(chrome.experimental.webRequest.onCompleted);
|
| + helper(chrome.experimental.webRequest.onErrorOccurred);
|
| +}
|
| +
|
| +runTests([
|
| + // Navigates to a blank page.
|
| + function simpleLoad() {
|
| + expect(
|
| + [ // events
|
| + { label: "a-onBeforeRequest",
|
| + event: "onBeforeRequest",
|
| + details: {
|
| + method: "GET",
|
| + tabId: tabId,
|
| + type: "main_frame",
|
| + url: getURL("simpleLoad/a.html"),
|
| + frameUrl: getURL("simpleLoad/a.html")
|
| + }
|
| + },
|
| + { label: "a-onResponseStarted",
|
| + event: "onResponseStarted",
|
| + details: {
|
| + url: getURL("simpleLoad/a.html"),
|
| + statusCode: 200,
|
| + fromCache: false
|
| + // Request to chrome-extension:// url has no IP.
|
| + }
|
| + },
|
| + { label: "a-onCompleted",
|
| + event: "onCompleted",
|
| + details: {
|
| + url: getURL("simpleLoad/a.html"),
|
| + statusCode: 200,
|
| + fromCache: false
|
| + // Request to chrome-extension:// url has no IP.
|
| + }
|
| + },
|
| + ],
|
| + [ // event order
|
| + ["a-onBeforeRequest", "a-onResponseStarted", "a-onCompleted"] ]);
|
| + navigateAndWait(getURL("simpleLoad/a.html"));
|
| + },
|
| +
|
| + // Navigates to a blank page via HTTP. Only HTTP requests get the
|
| + // onBeforeSendHeaders event.
|
| + function simpleLoadHttp() {
|
| + expect(
|
| + [ // events
|
| + { label: "onBeforeRequest-1",
|
| + event: "onBeforeRequest",
|
| + details: {
|
| + method: "GET",
|
| + tabId: tabId,
|
| + type: "main_frame",
|
| + url: URL_HTTP_SIMPLE_LOAD_REDIRECT,
|
| + frameUrl: URL_HTTP_SIMPLE_LOAD_REDIRECT
|
| + }
|
| + },
|
| + { label: "onBeforeSendHeaders-1",
|
| + event: "onBeforeSendHeaders",
|
| + details: {
|
| + url: URL_HTTP_SIMPLE_LOAD_REDIRECT,
|
| + requestHeadersValid: true
|
| + }
|
| + },
|
| + { label: "onSendHeaders-1",
|
| + event: "onSendHeaders",
|
| + details: {
|
| + url: URL_HTTP_SIMPLE_LOAD_REDIRECT,
|
| + requestHeadersValid: true
|
| + }
|
| + },
|
| + { label: "onBeforeRedirect",
|
| + event: "onBeforeRedirect",
|
| + details: {
|
| + url: URL_HTTP_SIMPLE_LOAD_REDIRECT,
|
| + redirectUrl: URL_HTTP_SIMPLE_LOAD,
|
| + statusCode: 301,
|
| + responseHeadersExist: true,
|
| + ip: "127.0.0.1",
|
| + fromCache: false,
|
| + statusLine: "HTTP/1.0 301 Moved Permanently"
|
| + }
|
| + },
|
| + { label: "onBeforeRequest-2",
|
| + event: "onBeforeRequest",
|
| + details: {
|
| + method: "GET",
|
| + tabId: tabId,
|
| + type: "main_frame",
|
| + url: URL_HTTP_SIMPLE_LOAD,
|
| + frameUrl: URL_HTTP_SIMPLE_LOAD
|
| + }
|
| + },
|
| + { label: "onBeforeSendHeaders-2",
|
| + event: "onBeforeSendHeaders",
|
| + details: {
|
| + url: URL_HTTP_SIMPLE_LOAD,
|
| + requestHeadersValid: true
|
| + }
|
| + },
|
| + { label: "onSendHeaders-2",
|
| + event: "onSendHeaders",
|
| + details: {
|
| + url: URL_HTTP_SIMPLE_LOAD,
|
| + requestHeadersValid: true
|
| + }
|
| + },
|
| + { label: "onResponseStarted",
|
| + event: "onResponseStarted",
|
| + details: {
|
| + url: URL_HTTP_SIMPLE_LOAD,
|
| + statusCode: 200,
|
| + responseHeadersExist: true,
|
| + ip: "127.0.0.1",
|
| + fromCache: false,
|
| + statusLine: "HTTP/1.0 200 OK",
|
| + }
|
| + },
|
| + { label: "onCompleted",
|
| + event: "onCompleted",
|
| + details: {
|
| + url: URL_HTTP_SIMPLE_LOAD,
|
| + statusCode: 200,
|
| + ip: "127.0.0.1",
|
| + fromCache: false,
|
| + responseHeadersExist: true,
|
| + statusLine: "HTTP/1.0 200 OK"
|
| + }
|
| + }
|
| + ],
|
| + [ // event order
|
| + ["onBeforeRequest-1", "onBeforeSendHeaders-1", "onSendHeaders-1",
|
| + "onBeforeRedirect",
|
| + "onBeforeRequest-2", "onBeforeSendHeaders-2", "onSendHeaders-2",
|
| + "onResponseStarted", "onCompleted"] ],
|
| + {}, // filter
|
| + ["requestHeaders", "responseHeaders", "statusLine"]);
|
| + navigateAndWait(URL_HTTP_SIMPLE_LOAD_REDIRECT);
|
| + },
|
| +
|
| + // Navigates to a page to generates an XHR.
|
| + function xhrLoad() {
|
| + expect(
|
| + [ // events
|
| + { label: "onBeforeRequest-1",
|
| + event: "onBeforeRequest",
|
| + details: {
|
| + method: "GET",
|
| + tabId: tabId,
|
| + type: "main_frame",
|
| + url: URL_HTTP_XHR,
|
| + frameUrl: URL_HTTP_XHR
|
| + }
|
| + },
|
| + { label: "onBeforeSendHeaders-1",
|
| + event: "onBeforeSendHeaders",
|
| + details: {
|
| + url: URL_HTTP_XHR,
|
| + }
|
| + },
|
| + { label: "onSendHeaders-1",
|
| + event: "onSendHeaders",
|
| + details: {
|
| + url: URL_HTTP_XHR,
|
| + }
|
| + },
|
| + { label: "onResponseStarted-1",
|
| + event: "onResponseStarted",
|
| + details: {
|
| + url: URL_HTTP_XHR,
|
| + statusCode: 200,
|
| + ip: "127.0.0.1",
|
| + fromCache: false,
|
| + }
|
| + },
|
| + { label: "onCompleted-1",
|
| + event: "onCompleted",
|
| + details: {
|
| + url: URL_HTTP_XHR,
|
| + statusCode: 200,
|
| + ip: "127.0.0.1",
|
| + fromCache: false,
|
| + }
|
| + },
|
| + { label: "onBeforeRequest-2",
|
| + event: "onBeforeRequest",
|
| + details: {
|
| + method: "GET",
|
| + tabId: tabId,
|
| + type: "xmlhttprequest",
|
| + url: URL_HTTP_XHR_DATA,
|
| + frameUrl: URL_HTTP_XHR
|
| + }
|
| + },
|
| + { label: "onBeforeSendHeaders-2",
|
| + event: "onBeforeSendHeaders",
|
| + details: {
|
| + url: URL_HTTP_XHR_DATA,
|
| + }
|
| + },
|
| + { label: "onSendHeaders-2",
|
| + event: "onSendHeaders",
|
| + details: {
|
| + url: URL_HTTP_XHR_DATA,
|
| + }
|
| + },
|
| + { label: "onResponseStarted-2",
|
| + event: "onResponseStarted",
|
| + details: {
|
| + url: URL_HTTP_XHR_DATA,
|
| + statusCode: 200,
|
| + ip: "127.0.0.1",
|
| + fromCache: false,
|
| + }
|
| + },
|
| + { label: "onCompleted-2",
|
| + event: "onCompleted",
|
| + details: {
|
| + url: URL_HTTP_XHR_DATA,
|
| + statusCode: 200,
|
| + ip: "127.0.0.1",
|
| + fromCache: false,
|
| + }
|
| + }
|
| + ],
|
| + [ // event order
|
| + ["onBeforeRequest-1", "onBeforeSendHeaders-1", "onSendHeaders-1",
|
| + "onResponseStarted-1", "onCompleted-1",
|
| + "onBeforeRequest-2", "onBeforeSendHeaders-2", "onSendHeaders-2",
|
| + "onResponseStarted-2", "onCompleted-2"] ],
|
| + {}, []);
|
| + navigateAndWait(URL_HTTP_XHR);
|
| + },
|
| +
|
| + // Navigates to a page with subresources.
|
| + // TODO(mpcomplete): add multiple subresources; requires support for
|
| + // recognizing partial ordering.
|
| + function complexLoad() {
|
| + expect(
|
| + [ // events
|
| + { label: "a.html-onBeforeRequest",
|
| + event: "onBeforeRequest",
|
| + details: {
|
| + method: "GET",
|
| + tabId: tabId,
|
| + type: "main_frame",
|
| + url: getURL("complexLoad/a.html"),
|
| + frameUrl: getURL("complexLoad/a.html")
|
| + }
|
| + },
|
| + { label: "b.html-onBeforeRequest",
|
| + event: "onBeforeRequest",
|
| + details: {
|
| + method: "GET",
|
| + tabId: tabId,
|
| + type: "sub_frame",
|
| + url: getURL("complexLoad/b.html"),
|
| + frameUrl: getURL("complexLoad/b.html")
|
| + }
|
| + },
|
| + { label: "b.jpg-onBeforeRequest",
|
| + event: "onBeforeRequest",
|
| + details: {
|
| + method: "GET",
|
| + tabId: tabId,
|
| + type: "image",
|
| + url: getURL("complexLoad/b.jpg"),
|
| + frameUrl: getURL("complexLoad/b.html")
|
| + }
|
| + },
|
| + { label: "a.html-onResponseStarted",
|
| + event: "onResponseStarted",
|
| + details: {
|
| + url: getURL("complexLoad/a.html"),
|
| + fromCache: false,
|
| + statusCode: 200
|
| + // Request to chrome-extension:// url has no IP.
|
| + }
|
| + },
|
| + { label: "b.html-onResponseStarted",
|
| + event: "onResponseStarted",
|
| + details: {
|
| + url: getURL("complexLoad/b.html"),
|
| + fromCache: false,
|
| + statusCode: 200
|
| + // Request to chrome-extension:// url has no IP.
|
| + }
|
| + },
|
| + { label: "b.jpg-onResponseStarted",
|
| + event: "onResponseStarted",
|
| + details: {
|
| + url: getURL("complexLoad/b.jpg"),
|
| + fromCache: false,
|
| + statusCode: 200
|
| + // Request to chrome-extension:// url has no IP.
|
| + }
|
| + },
|
| + { label: "a.html-onCompleted",
|
| + event: "onCompleted",
|
| + details: {
|
| + url: getURL("complexLoad/a.html"),
|
| + fromCache: false,
|
| + statusCode: 200
|
| + // Request to chrome-extension:// url has no IP.
|
| + }
|
| + },
|
| + { label: "b.html-onCompleted",
|
| + event: "onCompleted",
|
| + details: {
|
| + url: getURL("complexLoad/b.html"),
|
| + fromCache: false,
|
| + statusCode: 200
|
| + // Request to chrome-extension:// url has no IP.
|
| + }
|
| + },
|
| + { label: "b.jpg-onCompleted",
|
| + event: "onCompleted",
|
| + details: {
|
| + url: getURL("complexLoad/b.jpg"),
|
| + fromCache: false,
|
| + statusCode: 200
|
| + // Request to chrome-extension:// url has no IP.
|
| + }
|
| + },
|
| + ],
|
| + [ // event order
|
| + ["a.html-onBeforeRequest", "a.html-onResponseStarted",
|
| + "b.html-onBeforeRequest", "b.html-onResponseStarted",
|
| + "b.jpg-onBeforeRequest", "b.jpg-onResponseStarted" ],
|
| + ["a.html-onResponseStarted", "a.html-onCompleted"],
|
| + ["b.html-onResponseStarted", "b.html-onCompleted"],
|
| + ["b.jpg-onResponseStarted", "b.jpg-onCompleted"] ]
|
| + );
|
| + navigateAndWait(getURL("complexLoad/a.html"));
|
| + },
|
| +
|
| + // Navigates to a page with subresources, with a blocking handler that
|
| + // cancels the page request. The page will not load, and we should not
|
| + // see the subresources.
|
| + function complexLoadCancelled() {
|
| + expect(
|
| + [ // events
|
| + { label: "onBeforeRequest",
|
| + event: "onBeforeRequest",
|
| + details: {
|
| + method: "GET",
|
| + tabId: tabId,
|
| + type: "main_frame",
|
| + url: getURL("complexLoad/a.html"),
|
| + frameUrl: getURL("complexLoad/a.html")
|
| + },
|
| + retval: {cancel: true}
|
| + },
|
| + // Cancelling is considered an error.
|
| + { label: "onErrorOccurred",
|
| + event: "onErrorOccurred",
|
| + details: {
|
| + url: getURL("complexLoad/a.html"),
|
| + fromCache: false,
|
| + error: "net::ERR_EMPTY_RESPONSE"
|
| + // Request to chrome-extension:// url has no IP.
|
| + }
|
| + },
|
| + ],
|
| + [ // event order
|
| + ["onBeforeRequest"]
|
| + ],
|
| + {}, // filter
|
| + ["blocking"]);
|
| + navigateAndWait(getURL("complexLoad/a.html"));
|
| + },
|
| +
|
| + // Navigates to a page with a blocking handler that redirects to a different
|
| + // page.
|
| + // TODO(mpcomplete): We should see an onBeforeRedirect as well, but our
|
| + // process switching logic cancels the original redirect request and
|
| + // starts a new one instead. See http://crbug.com/79520.
|
| + function complexLoadRedirected() {
|
| + expect(
|
| + [ // events
|
| + { label: "onBeforeRequest-1",
|
| + event: "onBeforeRequest",
|
| + details: {
|
| + method: "GET",
|
| + tabId: tabId,
|
| + type: "main_frame",
|
| + url: getURL("complexLoad/a.html"),
|
| + frameUrl: getURL("complexLoad/a.html")
|
| + },
|
| + retval: {redirectUrl: getURL("simpleLoad/a.html")}
|
| + },
|
| + { label: "onErrorOccurred-1",
|
| + event: "onErrorOccurred",
|
| + details: {
|
| + url: getURL("complexLoad/a.html"),
|
| + fromCache: false,
|
| + error: "net::ERR_ABORTED"
|
| + // Request to chrome-extension:// url has no IP.
|
| + }
|
| + },
|
| + { label: "onBeforeRequest-2",
|
| + event: "onBeforeRequest",
|
| + details: {
|
| + method: "GET",
|
| + tabId: tabId,
|
| + type: "main_frame",
|
| + url: getURL("simpleLoad/a.html"),
|
| + frameUrl: getURL("simpleLoad/a.html"),
|
| + },
|
| + },
|
| + { label: "onResponseStarted",
|
| + event: "onResponseStarted",
|
| + details: {
|
| + url: getURL("simpleLoad/a.html"),
|
| + fromCache: false,
|
| + statusCode: 200
|
| + // Request to chrome-extension:// url has no IP.
|
| + }
|
| + },
|
| + { label: "onCompleted",
|
| + event: "onCompleted",
|
| + details: {
|
| + url: getURL("simpleLoad/a.html"),
|
| + fromCache: false,
|
| + statusCode: 200
|
| + // Request to chrome-extension:// url has no IP.
|
| + }
|
| + },
|
| + ],
|
| + [ // event order
|
| + ["onBeforeRequest-1", "onErrorOccurred-1", "onBeforeRequest-2",
|
| + "onResponseStarted", "onCompleted"],
|
| + ],
|
| + {}, // filter
|
| + ["blocking"]);
|
| + navigateAndWait(getURL("complexLoad/a.html"));
|
| + },
|
| +
|
| + // Loads several resources, but should only see the complexLoad main_frame
|
| + // and image due to the filter.
|
| + function complexLoadFiltered() {
|
| + expect(
|
| + [ // events
|
| + { label: "a-onBeforeRequest",
|
| + event: "onBeforeRequest",
|
| + details: {
|
| + method: "GET",
|
| + tabId: tabId,
|
| + type: "main_frame",
|
| + url: getURL("complexLoad/a.html"),
|
| + frameUrl: getURL("complexLoad/a.html")
|
| + }
|
| + },
|
| + { label: "b-onBeforeRequest",
|
| + event: "onBeforeRequest",
|
| + details: {
|
| + method: "GET",
|
| + tabId: tabId,
|
| + type: "image",
|
| + url: getURL("complexLoad/b.jpg"),
|
| + // As we do not listed to sub-frames we do not know the frameUrl.
|
| + frameUrl: "unknown frame URL"
|
| + }
|
| + },
|
| + { label: "a-onResponseStarted",
|
| + event: "onResponseStarted",
|
| + details: {
|
| + url: getURL("complexLoad/a.html"),
|
| + fromCache: false,
|
| + statusCode: 200
|
| + // Request to chrome-extension:// url has no IP.
|
| + }
|
| + },
|
| + { label: "b-onResponseStarted",
|
| + event: "onResponseStarted",
|
| + details: {
|
| + url: getURL("complexLoad/b.jpg"),
|
| + fromCache: false,
|
| + statusCode: 200
|
| + // Request to chrome-extension:// url has no IP.
|
| + }
|
| + },
|
| + { label: "a-onCompleted",
|
| + event: "onCompleted",
|
| + details: {
|
| + url: getURL("complexLoad/a.html"),
|
| + fromCache: false,
|
| + statusCode: 200
|
| + // Request to chrome-extension:// url has no IP.
|
| + }
|
| + },
|
| + { label: "b-onCompleted",
|
| + event: "onCompleted",
|
| + details: {
|
| + url: getURL("complexLoad/b.jpg"),
|
| + fromCache: false,
|
| + statusCode: 200
|
| + // Request to chrome-extension:// url has no IP.
|
| + }
|
| + },
|
| + ],
|
| + [ // event order
|
| + ["a-onBeforeRequest", "a-onResponseStarted",
|
| + "b-onBeforeRequest", "b-onResponseStarted"],
|
| + ["a-onResponseStarted", "a-onCompleted"],
|
| + ["b-onResponseStarted", "b-onCompleted"] ],
|
| + { // filters
|
| + urls: [getURL("complexLoad/*")],
|
| + types: ["main_frame", "image"],
|
| + tabId: tabId
|
| + });
|
| + chrome.tabs.create({ url: getURL("simpleLoad/a.html") },
|
| + function(newTab) {
|
| + chrome.tabs.remove(newTab.id);
|
| + navigateAndWait(getURL("complexLoad/a.html"));
|
| + });
|
| + },
|
| +
|
| + // Navigates to a non-existing page.
|
| + function nonExistingLoad() {
|
| + expect(
|
| + [ // events
|
| + { label: "onBeforeRequest",
|
| + event: "onBeforeRequest",
|
| + details: {
|
| + method: "GET",
|
| + tabId: tabId,
|
| + type: "main_frame",
|
| + url: getURL("does_not_exist.html"),
|
| + frameUrl: getURL("does_not_exist.html")
|
| + }
|
| + },
|
| + { label: "onErrorOccurred",
|
| + event: "onErrorOccurred",
|
| + details: {
|
| + url: getURL("does_not_exist.html"),
|
| + fromCache: false,
|
| + error: "net::ERR_FILE_NOT_FOUND",
|
| + // Request to chrome-extension:// url has no IP.
|
| + }
|
| + },
|
| + ],
|
| + [ // event order
|
| + ["onBeforeRequest", "onErrorOccurred"] ]);
|
| + navigateAndWait(getURL("does_not_exist.html"));
|
| + },
|
| +
|
| + // Loads a testserver page that echoes the User-Agent header that was
|
| + // sent to fetch it. We modify the outgoing User-Agent in
|
| + // onBeforeSendHeaders, so we should see that modified version.
|
| + function modifyRequestHeaders() {
|
| + expect(
|
| + [ // events
|
| + { label: "onBeforeRequest",
|
| + event: "onBeforeRequest",
|
| + details: {
|
| + method: "GET",
|
| + tabId: tabId,
|
| + type: "main_frame",
|
| + url: URL_ECHO_USER_AGENT,
|
| + frameUrl: URL_ECHO_USER_AGENT
|
| + }
|
| + },
|
| + { label: "onBeforeSendHeaders",
|
| + event: "onBeforeSendHeaders",
|
| + details: {
|
| + url: URL_ECHO_USER_AGENT,
|
| + // Note: no requestHeaders because we don't ask for them.
|
| + },
|
| + retval: {requestHeaders: [{name: "User-Agent", value: "FoobarUA"}]}
|
| + },
|
| + { label: "onSendHeaders",
|
| + event: "onSendHeaders",
|
| + details: {
|
| + url: URL_ECHO_USER_AGENT
|
| + }
|
| + },
|
| + { label: "onResponseStarted",
|
| + event: "onResponseStarted",
|
| + details: {
|
| + url: URL_ECHO_USER_AGENT,
|
| + fromCache: false,
|
| + statusCode: 200,
|
| + ip: "127.0.0.1"
|
| + }
|
| + },
|
| + { label: "onCompleted",
|
| + event: "onCompleted",
|
| + details: {
|
| + url: URL_ECHO_USER_AGENT,
|
| + fromCache: false,
|
| + statusCode: 200,
|
| + ip: "127.0.0.1"
|
| + }
|
| + },
|
| + ],
|
| + [ // event order
|
| + ["onBeforeRequest", "onBeforeSendHeaders", "onSendHeaders",
|
| + "onResponseStarted", "onCompleted"]
|
| + ],
|
| + {}, ["blocking"]);
|
| + // Check the page content for our modified User-Agent string.
|
| + navigateAndWait(URL_ECHO_USER_AGENT, function() {
|
| + chrome.test.listenOnce(chrome.extension.onRequest, function(request) {
|
| + chrome.test.assertTrue(request.pass, "Request header was not set.");
|
| + });
|
| + chrome.tabs.executeScript(tabId,
|
| + {
|
| + code: "chrome.extension.sendRequest(" +
|
| + "{pass: document.body.innerText.indexOf('FoobarUA') >= 0});"
|
| + });
|
| + });
|
| + },
|
| +
|
| + // Loads a testserver page that requires authentication.
|
| + function authRequired() {
|
| + expect(
|
| + [ // events
|
| + { label: "onBeforeRequest",
|
| + event: "onBeforeRequest",
|
| + details: {
|
| + method: "GET",
|
| + tabId: tabId,
|
| + type: "main_frame",
|
| + url: URL_AUTH_REQUIRED,
|
| + frameUrl: URL_AUTH_REQUIRED
|
| + }
|
| + },
|
| + { label: "onBeforeSendHeaders",
|
| + event: "onBeforeSendHeaders",
|
| + details: {
|
| + url: URL_AUTH_REQUIRED,
|
| + // Note: no requestHeaders because we don't ask for them.
|
| + },
|
| + },
|
| + { label: "onSendHeaders",
|
| + event: "onSendHeaders",
|
| + details: {
|
| + url: URL_AUTH_REQUIRED,
|
| + }
|
| + },
|
| + { label: "onAuthRequired",
|
| + event: "onAuthRequired",
|
| + details: {
|
| + url: URL_AUTH_REQUIRED,
|
| + isProxy: false,
|
| + scheme: "basic",
|
| + realm: "testrealm",
|
| + }
|
| + },
|
| + { label: "onResponseStarted",
|
| + event: "onResponseStarted",
|
| + details: {
|
| + url: URL_AUTH_REQUIRED,
|
| + fromCache: false,
|
| + statusCode: 401,
|
| + ip: "127.0.0.1"
|
| + }
|
| + },
|
| + { label: "onCompleted",
|
| + event: "onCompleted",
|
| + details: {
|
| + url: URL_AUTH_REQUIRED,
|
| + fromCache: false,
|
| + statusCode: 401,
|
| + ip: "127.0.0.1"
|
| + }
|
| + },
|
| + ],
|
| + [ // event order
|
| + ["onBeforeRequest", "onBeforeSendHeaders", "onSendHeaders",
|
| + "onAuthRequired", "onResponseStarted", "onCompleted"]
|
| + ],
|
| + {}, []);
|
| + navigateAndWait(URL_AUTH_REQUIRED);
|
| + },
|
| +]);
|
| +</script>
|
|
|