|
1 var Cc = Components.classes; |
|
2 var Ci = Components.interfaces; |
|
3 var Cu = Components.utils; |
|
4 var Cr = Components.results; |
|
5 |
|
6 Cu.import("resource://gre/modules/Services.jsm"); |
|
7 Cu.import("resource://gre/modules/FileUtils.jsm"); |
|
8 |
|
9 var seer = null; |
|
10 var ios = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService); |
|
11 var profile = null; |
|
12 |
|
13 function extract_origin(uri) { |
|
14 var o = uri.scheme + "://" + uri.asciiHost; |
|
15 if (uri.port !== -1) { |
|
16 o = o + ":" + uri.port; |
|
17 } |
|
18 return o; |
|
19 } |
|
20 |
|
21 var LoadContext = function _loadContext() { |
|
22 }; |
|
23 |
|
24 LoadContext.prototype = { |
|
25 usePrivateBrowsing: false, |
|
26 |
|
27 getInterface: function loadContext_getInterface(iid) { |
|
28 return this.QueryInterface(iid); |
|
29 }, |
|
30 |
|
31 QueryInterface: function loadContext_QueryInterface(iid) { |
|
32 if (iid.equals(Ci.nsINetworkSeerVerifier) || |
|
33 iid.equals(Ci.nsILoadContext)) { |
|
34 return this; |
|
35 } |
|
36 |
|
37 throw Cr.NS_ERROR_NO_INTERFACE; |
|
38 } |
|
39 }; |
|
40 |
|
41 var load_context = new LoadContext(); |
|
42 |
|
43 var Verifier = function _verifier(testing, expected_preconnects, expected_preresolves) { |
|
44 this.verifying = testing; |
|
45 this.expected_preconnects = expected_preconnects; |
|
46 this.expected_preresolves = expected_preresolves; |
|
47 }; |
|
48 |
|
49 Verifier.prototype = { |
|
50 verifying: null, |
|
51 expected_preconnects: null, |
|
52 expected_preresolves: null, |
|
53 |
|
54 getInterface: function verifier_getInterface(iid) { |
|
55 return this.QueryInterface(iid); |
|
56 }, |
|
57 |
|
58 QueryInterface: function verifier_QueryInterface(iid) { |
|
59 if (iid.equals(Ci.nsINetworkSeerVerifier) || |
|
60 iid.equals(Ci.nsISupports)) { |
|
61 return this; |
|
62 } |
|
63 |
|
64 throw Cr.NS_ERROR_NO_INTERFACE; |
|
65 }, |
|
66 |
|
67 maybe_run_next_test: function verifier_maybe_run_next_test() { |
|
68 if (this.expected_preconnects.length === 0 && |
|
69 this.expected_preresolves.length === 0) { |
|
70 do_check_true(true, "Well this is unexpected..."); |
|
71 run_next_test(); |
|
72 } |
|
73 }, |
|
74 |
|
75 onPredictPreconnect: function verifier_onPredictPreconnect(uri) { |
|
76 var origin = extract_origin(uri); |
|
77 var index = this.expected_preconnects.indexOf(origin); |
|
78 if (index == -1) { |
|
79 do_check_true(false, "Got preconnect for unexpected uri " + origin); |
|
80 } else { |
|
81 this.expected_preconnects.splice(index, 1); |
|
82 } |
|
83 this.maybe_run_next_test(); |
|
84 }, |
|
85 |
|
86 onPredictDNS: function verifier_onPredictDNS(uri) { |
|
87 var origin = extract_origin(uri); |
|
88 var index = this.expected_preresolves.indexOf(origin); |
|
89 if (index == -1) { |
|
90 do_check_true(false, "Got preresolve for unexpected uri " + origin); |
|
91 } else { |
|
92 this.expected_preresolves.splice(index, 1); |
|
93 } |
|
94 this.maybe_run_next_test(); |
|
95 } |
|
96 }; |
|
97 |
|
98 function reset_seer() { |
|
99 seer.reset(); |
|
100 } |
|
101 |
|
102 function newURI(s) { |
|
103 return ios.newURI(s, null, null); |
|
104 } |
|
105 |
|
106 function test_link_hover() { |
|
107 reset_seer(); |
|
108 var uri = newURI("http://localhost:4444/foo/bar"); |
|
109 var referrer = newURI("http://localhost:4444/foo"); |
|
110 var preconns = ["http://localhost:4444"]; |
|
111 |
|
112 var verifier = new Verifier("hover", preconns, []); |
|
113 seer.predict(uri, referrer, seer.PREDICT_LINK, load_context, verifier); |
|
114 } |
|
115 |
|
116 function test_pageload() { |
|
117 reset_seer(); |
|
118 var toplevel = "http://localhost:4444/index.html"; |
|
119 var subresources = [ |
|
120 "http://localhost:4444/style.css", |
|
121 "http://localhost:4443/jquery.js", |
|
122 "http://localhost:4444/image.png" |
|
123 ]; |
|
124 |
|
125 var tluri = newURI(toplevel); |
|
126 seer.learn(tluri, null, seer.LEARN_LOAD_TOPLEVEL, load_context); |
|
127 var preconns = []; |
|
128 for (var i = 0; i < subresources.length; i++) { |
|
129 var sruri = newURI(subresources[i]); |
|
130 seer.learn(sruri, tluri, seer.LEARN_LOAD_SUBRESOURCE, load_context); |
|
131 preconns.push(extract_origin(sruri)); |
|
132 } |
|
133 |
|
134 var verifier = new Verifier("pageload", preconns, []); |
|
135 seer.predict(tluri, null, seer.PREDICT_LOAD, load_context, verifier); |
|
136 } |
|
137 |
|
138 function test_redirect() { |
|
139 reset_seer(); |
|
140 var initial = "http://localhost:4443/redirect"; |
|
141 var target = "http://localhost:4444/index.html"; |
|
142 var subresources = [ |
|
143 "http://localhost:4444/style.css", |
|
144 "http://localhost:4443/jquery.js", |
|
145 "http://localhost:4444/image.png" |
|
146 ]; |
|
147 |
|
148 var inituri = newURI(initial); |
|
149 var targeturi = newURI(target); |
|
150 seer.learn(inituri, null, seer.LEARN_LOAD_TOPLEVEL, load_context); |
|
151 seer.learn(targeturi, inituri, seer.LEARN_LOAD_REDIRECT, load_context); |
|
152 seer.learn(targeturi, null, seer.LEARN_LOAD_TOPLEVEL, load_context); |
|
153 |
|
154 var preconns = []; |
|
155 preconns.push(extract_origin(targeturi)); |
|
156 for (var i = 0; i < subresources.length; i++) { |
|
157 var sruri = newURI(subresources[i]); |
|
158 seer.learn(sruri, targeturi, seer.LEARN_LOAD_SUBRESOURCE, load_context); |
|
159 preconns.push(extract_origin(sruri)); |
|
160 } |
|
161 |
|
162 var verifier = new Verifier("redirect", preconns, []); |
|
163 seer.predict(inituri, null, seer.PREDICT_LOAD, load_context, verifier); |
|
164 } |
|
165 |
|
166 function test_startup() { |
|
167 reset_seer(); |
|
168 var uris = [ |
|
169 "http://localhost:4444/startup", |
|
170 "http://localhost:4443/startup" |
|
171 ]; |
|
172 var preconns = []; |
|
173 for (var i = 0; i < uris.length; i++) { |
|
174 var uri = newURI(uris[i]); |
|
175 seer.learn(uri, null, seer.LEARN_STARTUP, load_context); |
|
176 preconns.push(extract_origin(uri)); |
|
177 } |
|
178 |
|
179 var verifier = new Verifier("startup", preconns, []); |
|
180 seer.predict(null, null, seer.PREDICT_STARTUP, load_context, verifier); |
|
181 } |
|
182 |
|
183 // A class used to guarantee serialization of SQL queries so we can properly |
|
184 // update last hit times on subresources to ensure the seer tries to do DNS |
|
185 // preresolve on them instead of preconnecting |
|
186 var DnsContinueVerifier = function _dnsContinueVerifier(subresource, tluri, preresolves) { |
|
187 this.subresource = subresource; |
|
188 this.tluri = tluri; |
|
189 this.preresolves = preresolves; |
|
190 }; |
|
191 |
|
192 DnsContinueVerifier.prototype = { |
|
193 subresource: null, |
|
194 tluri: null, |
|
195 preresolves: null, |
|
196 |
|
197 getInterface: function _dnsContinueVerifier_getInterface(iid) { |
|
198 return this.QueryInterface(iid); |
|
199 }, |
|
200 |
|
201 QueryInterface: function _dnsContinueVerifier_QueryInterface(iid) { |
|
202 if (iid.equals(Ci.nsISupports) || |
|
203 iid.equals(Ci.nsINetworkSeerVerifier)) { |
|
204 return this; |
|
205 } |
|
206 |
|
207 throw Cr.NS_ERROR_NO_INTERFACE; |
|
208 }, |
|
209 |
|
210 onPredictPreconnect: function _dnsContinueVerifier_onPredictPreconnect() { |
|
211 // This means that the seer has learned and done our "checkpoint" prediction |
|
212 // Now we can get on with the prediction we actually want to test |
|
213 |
|
214 // tstamp is 10 days older than now - just over 1 week, which will ensure we |
|
215 // hit our cutoff for dns vs. preconnect. This is all in usec, hence the |
|
216 // x1000 on the Date object value. |
|
217 var tstamp = (new Date().valueOf() * 1000) - (10 * 86400 * 1000000); |
|
218 |
|
219 seer.prepareForDnsTest(tstamp, this.subresource); |
|
220 |
|
221 var verifier = new Verifier("dns", [], this.preresolves); |
|
222 seer.predict(this.tluri, null, seer.PREDICT_LOAD, load_context, verifier); |
|
223 }, |
|
224 |
|
225 onPredictDNS: function _dnsContinueVerifier_onPredictDNS() { |
|
226 do_check_true(false, "Shouldn't have gotten a preresolve prediction here!"); |
|
227 } |
|
228 }; |
|
229 |
|
230 function test_dns() { |
|
231 reset_seer(); |
|
232 var toplevel = "http://localhost:4444/index.html"; |
|
233 var subresource = "http://localhost:4443/jquery.js"; |
|
234 |
|
235 var tluri = newURI(toplevel); |
|
236 seer.learn(tluri, null, seer.LEARN_LOAD_TOPLEVEL, load_context); |
|
237 var sruri = newURI(subresource); |
|
238 seer.learn(sruri, tluri, seer.LEARN_LOAD_SUBRESOURCE, load_context); |
|
239 |
|
240 var preresolves = [extract_origin(sruri)]; |
|
241 var continue_verifier = new DnsContinueVerifier(subresource, tluri, preresolves); |
|
242 // Fire off a prediction that will do preconnects so we know when the seer |
|
243 // thread has gotten to the point where we can update the database manually |
|
244 seer.predict(tluri, null, seer.PREDICT_LOAD, load_context, continue_verifier); |
|
245 } |
|
246 |
|
247 function test_origin() { |
|
248 reset_seer(); |
|
249 var toplevel = "http://localhost:4444/index.html"; |
|
250 var subresources = [ |
|
251 "http://localhost:4444/style.css", |
|
252 "http://localhost:4443/jquery.js", |
|
253 "http://localhost:4444/image.png" |
|
254 ]; |
|
255 |
|
256 var tluri = newURI(toplevel); |
|
257 seer.learn(tluri, null, seer.LEARN_LOAD_TOPLEVEL, load_context); |
|
258 var preconns = []; |
|
259 for (var i = 0; i < subresources.length; i++) { |
|
260 var sruri = newURI(subresources[i]); |
|
261 seer.learn(sruri, tluri, seer.LEARN_LOAD_SUBRESOURCE, load_context); |
|
262 var origin = extract_origin(sruri); |
|
263 if (preconns.indexOf(origin) === -1) { |
|
264 preconns.push(origin); |
|
265 } |
|
266 } |
|
267 |
|
268 var loaduri = newURI("http://localhost:4444/anotherpage.html"); |
|
269 var verifier = new Verifier("origin", preconns, []); |
|
270 seer.predict(loaduri, null, seer.PREDICT_LOAD, load_context, verifier); |
|
271 } |
|
272 |
|
273 var tests = [ |
|
274 test_link_hover, |
|
275 test_pageload, |
|
276 test_redirect, |
|
277 test_startup, |
|
278 test_dns, |
|
279 test_origin |
|
280 ]; |
|
281 |
|
282 function run_test() { |
|
283 tests.forEach(add_test); |
|
284 profile = do_get_profile(); |
|
285 seer = Cc["@mozilla.org/network/seer;1"].getService(Ci.nsINetworkSeer); |
|
286 do_register_cleanup(reset_seer); |
|
287 run_next_test(); |
|
288 } |