Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(128)

Side by Side Diff: chrome/test/data/extensions/api_test/webrequest/framework.js

Issue 7606033: Unrevert r96075: Split ExtensionWebRequestApiTest.WebRequestEvents into (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 9 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 var getURL = chrome.extension.getURL;
2 var deepEq = chrome.test.checkDeepEq;
3 var expectedEventData;
4 var capturedEventData;
5 var expectedEventOrder;
6 var tabId;
7 var testServerPort;
8 var eventsCaptured;
9
10 function runTests(tests) {
11 chrome.tabs.create({url: "about:blank"}, function(tab) {
12 tabId = tab.id;
13 chrome.test.getConfig(function(config) {
14 testServerPort = config.testServer.port;
15 chrome.test.runTests(tests);
16 });
17 });
18 }
19
20 // Returns an URL from the test server, fixing up the port. Must be called
21 // from within a test case passed to runTests.
22 function getServerURL(path) {
23 if (!testServerPort)
24 throw new Error("Called getServerURL outside of runTests.");
25 return "http://www.a.com:" + testServerPort + "/" + path;
26 }
27
28 // Helper to advance to the next test only when the tab has finished loading.
29 // This is because tabs.update can sometimes fail if the tab is in the middle
30 // of a navigation (from the previous test), resulting in flakiness.
31 function navigateAndWait(url, callback) {
32 var done = chrome.test.listenForever(chrome.tabs.onUpdated,
33 function (_, info, tab) {
34 console.log("tabUpdated: " + info.status + ": " + tab.url);
35 if (tab.id == tabId && info.status == "complete") {
36 if (callback) callback();
37 done();
38 }
39 });
40 chrome.tabs.update(tabId, {url: url});
41 }
42
43 // data: array of extected events, each one is a dictionary:
44 // { label: "<unique identifier>",
45 // event: "<webrequest event type>",
46 // details: { <expected details of the webrequest event> },
47 // retval: { <dictionary that the event handler shall return> } (optional)
48 // }
49 // order: an array of sequences, e.g. [ ["a", "b", "c"], ["d", "e"] ] means that
50 // event with label "a" needs to occur before event with label "b". The
51 // relative order of "a" and "d" does not matter.
52 // filter: filter dictionary passed on to the event subscription of the
53 // webRequest API.
54 // extraInfoSpec: the union of all desired extraInfoSpecs for the events.
55 function expect(data, order, filter, extraInfoSpec) {
56 expectedEventData = data;
57 capturedEventData = [];
58 expectedEventOrder = order;
59 eventsCaptured = chrome.test.callbackAdded();
60 tabAndFrameUrls = {}; // Maps "{tabId}-{frameId}" to the URL of the frame.
61 removeListeners();
62 initListeners(filter || {}, extraInfoSpec || []);
63 }
64
65 function checkExpectations() {
66 if (capturedEventData.length < expectedEventData.length) {
67 return;
68 }
69 if (capturedEventData.length > expectedEventData.length) {
70 chrome.test.fail("Recorded too many events. " +
71 JSON.stringify(capturedEventData));
72 return;
73 }
74 // We have ensured that capturedEventData contains exactly the same elements
75 // as expectedEventData. Now we need to verify the ordering.
76 // Step 1: build positions such that
77 // positions[<event-label>]=<position of this event in capturedEventData>
78 var curPos = 0;
79 var positions = {}
80 capturedEventData.forEach(function (event) {
81 chrome.test.assertTrue(event.hasOwnProperty("label"));
82 positions[event.label] = curPos;
83 curPos++;
84 });
85 // Step 2: check that elements arrived in correct order
86 expectedEventOrder.forEach(function (order) {
87 var previousLabel = undefined;
88 order.forEach(function(label) {
89 if (previousLabel === undefined) {
90 previousLabel = label;
91 return;
92 }
93 chrome.test.assertTrue(positions[previousLabel] < positions[label],
94 "Event " + previousLabel + " is supposed to arrive before " +
95 label + ".");
96 previousLabel = label;
97 });
98 });
99
100 eventsCaptured();
101 }
102
103 // Simple check to see that we have a User-Agent header, and that it contains
104 // an expected value. This is a basic check that the request headers are valid.
105 function checkUserAgent(headers) {
106 for (var i in headers) {
107 if (headers[i].name.toLowerCase() == "user-agent")
108 return headers[i].value.toLowerCase().indexOf("chrome") != -1;
109 }
110 return false;
111 }
112
113 function captureEvent(name, details) {
114 // Ignore system-level requests like safebrowsing updates and favicon fetches
115 // since they are unpredictable.
116 if (details.tabId == -1 || details.type == "other" ||
117 details.url.match(/\/favicon.ico$/) ||
118 details.url.match(/https:\/\/dl.google.com/))
119 return;
120
121 // Pull the extra per-event options out of the expected data. These let
122 // us specify special return values per event.
123 var currentIndex = capturedEventData.length;
124 var extraOptions;
125 if (expectedEventData.length > currentIndex) {
126 retval = expectedEventData[currentIndex].retval;
127 }
128
129 // Check that the frameId can be used to reliably determine the URL of the
130 // frame that caused requests.
131 if (name == "onBeforeRequest") {
132 chrome.test.assertTrue('frameId' in details &&
133 typeof details.frameId === 'number');
134 chrome.test.assertTrue('tabId' in details &&
135 typeof details.tabId === 'number');
136 var key = details.tabId + "-" + details.frameId;
137 if (details.type == "main_frame" || details.type == "sub_frame") {
138 tabAndFrameUrls[key] = details.url;
139 }
140 details.frameUrl = tabAndFrameUrls[key] || "unknown frame URL";
141 }
142 delete details.frameId;
143
144 delete details.requestId;
145 delete details.timeStamp;
146 if (details.requestHeaders) {
147 details.requestHeadersValid = checkUserAgent(details.requestHeaders);
148 delete details.requestHeaders;
149 }
150 if (details.responseHeaders) {
151 details.responseHeadersExist = true;
152 delete details.responseHeaders;
153 }
154
155 // find |details| in expectedEventData
156 var found = false;
157 var label = undefined;
158 expectedEventData.forEach(function (exp) {
159 if (deepEq(exp.event, name) && deepEq(exp.details, details)) {
160 if (found) {
161 chrome.test.fail("Received event twice '" + name + "':" +
162 JSON.stringify(details));
163 } else {
164 found = true;
165 label = exp.label;
166 }
167 }
168 });
169 if (!found) {
170 chrome.test.fail("Received unexpected event '" + name + "':" +
171 JSON.stringify(details));
172 }
173
174 capturedEventData.push({label: label, event: name, details: details});
175 checkExpectations();
176 return retval;
177 }
178
179 // Simple array intersection. We use this to filter extraInfoSpec so
180 // that only the allowed specs are sent to each listener.
181 function intersect(array1, array2) {
182 return array1.filter(function(x) { return array2.indexOf(x) != -1; });
183 }
184
185 function initListeners(filter, extraInfoSpec) {
186 chrome.experimental.webRequest.onBeforeRequest.addListener(
187 function(details) {
188 return captureEvent("onBeforeRequest", details);
189 }, filter, intersect(extraInfoSpec, ["blocking"]));
190 chrome.experimental.webRequest.onBeforeSendHeaders.addListener(
191 function(details) {
192 return captureEvent("onBeforeSendHeaders", details);
193 }, filter, intersect(extraInfoSpec, ["blocking", "requestHeaders"]));
194 chrome.experimental.webRequest.onSendHeaders.addListener(
195 function(details) {
196 return captureEvent("onSendHeaders", details);
197 }, filter, intersect(extraInfoSpec, ["requestHeaders"]));
198 chrome.experimental.webRequest.onAuthRequired.addListener(
199 function(details) {
200 return captureEvent("onAuthRequired", details);
201 }, filter, intersect(extraInfoSpec, ["responseHeaders", "statusLine"]));
202 chrome.experimental.webRequest.onResponseStarted.addListener(
203 function(details) {
204 return captureEvent("onResponseStarted", details);
205 }, filter, intersect(extraInfoSpec, ["responseHeaders", "statusLine"]));
206 chrome.experimental.webRequest.onBeforeRedirect.addListener(
207 function(details) {
208 return captureEvent("onBeforeRedirect", details);
209 }, filter, intersect(extraInfoSpec, ["responseHeaders", "statusLine"]));
210 chrome.experimental.webRequest.onCompleted.addListener(
211 function(details) {
212 return captureEvent("onCompleted", details);
213 }, filter, intersect(extraInfoSpec, ["responseHeaders", "statusLine"]));
214 chrome.experimental.webRequest.onErrorOccurred.addListener(
215 function(details) {
216 return captureEvent("onErrorOccurred", details);
217 }, filter);
218 }
219
220 function removeListeners() {
221 function helper(event) {
222 // Note: We're poking at the internal event data, but it's easier than
223 // the alternative. If this starts failing, we just need to update this
224 // helper.
225 for (var cb in event.callbackMap_) {
226 event.removeListener(cb);
227 }
228 chrome.test.assertFalse(event.hasListeners());
229 }
230 helper(chrome.experimental.webRequest.onBeforeRequest);
231 helper(chrome.experimental.webRequest.onBeforeSendHeaders);
232 helper(chrome.experimental.webRequest.onAuthRequired);
233 helper(chrome.experimental.webRequest.onSendHeaders);
234 helper(chrome.experimental.webRequest.onResponseStarted);
235 helper(chrome.experimental.webRequest.onBeforeRedirect);
236 helper(chrome.experimental.webRequest.onCompleted);
237 helper(chrome.experimental.webRequest.onErrorOccurred);
238 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698