michael@0: var Cc = Components.classes; michael@0: var Ci = Components.interfaces; michael@0: var Cu = Components.utils; michael@0: var Cr = Components.results; michael@0: michael@0: Cu.import("resource://gre/modules/Services.jsm"); michael@0: Cu.import("resource://gre/modules/FileUtils.jsm"); michael@0: michael@0: var seer = null; michael@0: var ios = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService); michael@0: var profile = null; michael@0: michael@0: function extract_origin(uri) { michael@0: var o = uri.scheme + "://" + uri.asciiHost; michael@0: if (uri.port !== -1) { michael@0: o = o + ":" + uri.port; michael@0: } michael@0: return o; michael@0: } michael@0: michael@0: var LoadContext = function _loadContext() { michael@0: }; michael@0: michael@0: LoadContext.prototype = { michael@0: usePrivateBrowsing: false, michael@0: michael@0: getInterface: function loadContext_getInterface(iid) { michael@0: return this.QueryInterface(iid); michael@0: }, michael@0: michael@0: QueryInterface: function loadContext_QueryInterface(iid) { michael@0: if (iid.equals(Ci.nsINetworkSeerVerifier) || michael@0: iid.equals(Ci.nsILoadContext)) { michael@0: return this; michael@0: } michael@0: michael@0: throw Cr.NS_ERROR_NO_INTERFACE; michael@0: } michael@0: }; michael@0: michael@0: var load_context = new LoadContext(); michael@0: michael@0: var Verifier = function _verifier(testing, expected_preconnects, expected_preresolves) { michael@0: this.verifying = testing; michael@0: this.expected_preconnects = expected_preconnects; michael@0: this.expected_preresolves = expected_preresolves; michael@0: }; michael@0: michael@0: Verifier.prototype = { michael@0: verifying: null, michael@0: expected_preconnects: null, michael@0: expected_preresolves: null, michael@0: michael@0: getInterface: function verifier_getInterface(iid) { michael@0: return this.QueryInterface(iid); michael@0: }, michael@0: michael@0: QueryInterface: function verifier_QueryInterface(iid) { michael@0: if (iid.equals(Ci.nsINetworkSeerVerifier) || michael@0: iid.equals(Ci.nsISupports)) { michael@0: return this; michael@0: } michael@0: michael@0: throw Cr.NS_ERROR_NO_INTERFACE; michael@0: }, michael@0: michael@0: maybe_run_next_test: function verifier_maybe_run_next_test() { michael@0: if (this.expected_preconnects.length === 0 && michael@0: this.expected_preresolves.length === 0) { michael@0: do_check_true(true, "Well this is unexpected..."); michael@0: run_next_test(); michael@0: } michael@0: }, michael@0: michael@0: onPredictPreconnect: function verifier_onPredictPreconnect(uri) { michael@0: var origin = extract_origin(uri); michael@0: var index = this.expected_preconnects.indexOf(origin); michael@0: if (index == -1) { michael@0: do_check_true(false, "Got preconnect for unexpected uri " + origin); michael@0: } else { michael@0: this.expected_preconnects.splice(index, 1); michael@0: } michael@0: this.maybe_run_next_test(); michael@0: }, michael@0: michael@0: onPredictDNS: function verifier_onPredictDNS(uri) { michael@0: var origin = extract_origin(uri); michael@0: var index = this.expected_preresolves.indexOf(origin); michael@0: if (index == -1) { michael@0: do_check_true(false, "Got preresolve for unexpected uri " + origin); michael@0: } else { michael@0: this.expected_preresolves.splice(index, 1); michael@0: } michael@0: this.maybe_run_next_test(); michael@0: } michael@0: }; michael@0: michael@0: function reset_seer() { michael@0: seer.reset(); michael@0: } michael@0: michael@0: function newURI(s) { michael@0: return ios.newURI(s, null, null); michael@0: } michael@0: michael@0: function test_link_hover() { michael@0: reset_seer(); michael@0: var uri = newURI("http://localhost:4444/foo/bar"); michael@0: var referrer = newURI("http://localhost:4444/foo"); michael@0: var preconns = ["http://localhost:4444"]; michael@0: michael@0: var verifier = new Verifier("hover", preconns, []); michael@0: seer.predict(uri, referrer, seer.PREDICT_LINK, load_context, verifier); michael@0: } michael@0: michael@0: function test_pageload() { michael@0: reset_seer(); michael@0: var toplevel = "http://localhost:4444/index.html"; michael@0: var subresources = [ michael@0: "http://localhost:4444/style.css", michael@0: "http://localhost:4443/jquery.js", michael@0: "http://localhost:4444/image.png" michael@0: ]; michael@0: michael@0: var tluri = newURI(toplevel); michael@0: seer.learn(tluri, null, seer.LEARN_LOAD_TOPLEVEL, load_context); michael@0: var preconns = []; michael@0: for (var i = 0; i < subresources.length; i++) { michael@0: var sruri = newURI(subresources[i]); michael@0: seer.learn(sruri, tluri, seer.LEARN_LOAD_SUBRESOURCE, load_context); michael@0: preconns.push(extract_origin(sruri)); michael@0: } michael@0: michael@0: var verifier = new Verifier("pageload", preconns, []); michael@0: seer.predict(tluri, null, seer.PREDICT_LOAD, load_context, verifier); michael@0: } michael@0: michael@0: function test_redirect() { michael@0: reset_seer(); michael@0: var initial = "http://localhost:4443/redirect"; michael@0: var target = "http://localhost:4444/index.html"; michael@0: var subresources = [ michael@0: "http://localhost:4444/style.css", michael@0: "http://localhost:4443/jquery.js", michael@0: "http://localhost:4444/image.png" michael@0: ]; michael@0: michael@0: var inituri = newURI(initial); michael@0: var targeturi = newURI(target); michael@0: seer.learn(inituri, null, seer.LEARN_LOAD_TOPLEVEL, load_context); michael@0: seer.learn(targeturi, inituri, seer.LEARN_LOAD_REDIRECT, load_context); michael@0: seer.learn(targeturi, null, seer.LEARN_LOAD_TOPLEVEL, load_context); michael@0: michael@0: var preconns = []; michael@0: preconns.push(extract_origin(targeturi)); michael@0: for (var i = 0; i < subresources.length; i++) { michael@0: var sruri = newURI(subresources[i]); michael@0: seer.learn(sruri, targeturi, seer.LEARN_LOAD_SUBRESOURCE, load_context); michael@0: preconns.push(extract_origin(sruri)); michael@0: } michael@0: michael@0: var verifier = new Verifier("redirect", preconns, []); michael@0: seer.predict(inituri, null, seer.PREDICT_LOAD, load_context, verifier); michael@0: } michael@0: michael@0: function test_startup() { michael@0: reset_seer(); michael@0: var uris = [ michael@0: "http://localhost:4444/startup", michael@0: "http://localhost:4443/startup" michael@0: ]; michael@0: var preconns = []; michael@0: for (var i = 0; i < uris.length; i++) { michael@0: var uri = newURI(uris[i]); michael@0: seer.learn(uri, null, seer.LEARN_STARTUP, load_context); michael@0: preconns.push(extract_origin(uri)); michael@0: } michael@0: michael@0: var verifier = new Verifier("startup", preconns, []); michael@0: seer.predict(null, null, seer.PREDICT_STARTUP, load_context, verifier); michael@0: } michael@0: michael@0: // A class used to guarantee serialization of SQL queries so we can properly michael@0: // update last hit times on subresources to ensure the seer tries to do DNS michael@0: // preresolve on them instead of preconnecting michael@0: var DnsContinueVerifier = function _dnsContinueVerifier(subresource, tluri, preresolves) { michael@0: this.subresource = subresource; michael@0: this.tluri = tluri; michael@0: this.preresolves = preresolves; michael@0: }; michael@0: michael@0: DnsContinueVerifier.prototype = { michael@0: subresource: null, michael@0: tluri: null, michael@0: preresolves: null, michael@0: michael@0: getInterface: function _dnsContinueVerifier_getInterface(iid) { michael@0: return this.QueryInterface(iid); michael@0: }, michael@0: michael@0: QueryInterface: function _dnsContinueVerifier_QueryInterface(iid) { michael@0: if (iid.equals(Ci.nsISupports) || michael@0: iid.equals(Ci.nsINetworkSeerVerifier)) { michael@0: return this; michael@0: } michael@0: michael@0: throw Cr.NS_ERROR_NO_INTERFACE; michael@0: }, michael@0: michael@0: onPredictPreconnect: function _dnsContinueVerifier_onPredictPreconnect() { michael@0: // This means that the seer has learned and done our "checkpoint" prediction michael@0: // Now we can get on with the prediction we actually want to test michael@0: michael@0: // tstamp is 10 days older than now - just over 1 week, which will ensure we michael@0: // hit our cutoff for dns vs. preconnect. This is all in usec, hence the michael@0: // x1000 on the Date object value. michael@0: var tstamp = (new Date().valueOf() * 1000) - (10 * 86400 * 1000000); michael@0: michael@0: seer.prepareForDnsTest(tstamp, this.subresource); michael@0: michael@0: var verifier = new Verifier("dns", [], this.preresolves); michael@0: seer.predict(this.tluri, null, seer.PREDICT_LOAD, load_context, verifier); michael@0: }, michael@0: michael@0: onPredictDNS: function _dnsContinueVerifier_onPredictDNS() { michael@0: do_check_true(false, "Shouldn't have gotten a preresolve prediction here!"); michael@0: } michael@0: }; michael@0: michael@0: function test_dns() { michael@0: reset_seer(); michael@0: var toplevel = "http://localhost:4444/index.html"; michael@0: var subresource = "http://localhost:4443/jquery.js"; michael@0: michael@0: var tluri = newURI(toplevel); michael@0: seer.learn(tluri, null, seer.LEARN_LOAD_TOPLEVEL, load_context); michael@0: var sruri = newURI(subresource); michael@0: seer.learn(sruri, tluri, seer.LEARN_LOAD_SUBRESOURCE, load_context); michael@0: michael@0: var preresolves = [extract_origin(sruri)]; michael@0: var continue_verifier = new DnsContinueVerifier(subresource, tluri, preresolves); michael@0: // Fire off a prediction that will do preconnects so we know when the seer michael@0: // thread has gotten to the point where we can update the database manually michael@0: seer.predict(tluri, null, seer.PREDICT_LOAD, load_context, continue_verifier); michael@0: } michael@0: michael@0: function test_origin() { michael@0: reset_seer(); michael@0: var toplevel = "http://localhost:4444/index.html"; michael@0: var subresources = [ michael@0: "http://localhost:4444/style.css", michael@0: "http://localhost:4443/jquery.js", michael@0: "http://localhost:4444/image.png" michael@0: ]; michael@0: michael@0: var tluri = newURI(toplevel); michael@0: seer.learn(tluri, null, seer.LEARN_LOAD_TOPLEVEL, load_context); michael@0: var preconns = []; michael@0: for (var i = 0; i < subresources.length; i++) { michael@0: var sruri = newURI(subresources[i]); michael@0: seer.learn(sruri, tluri, seer.LEARN_LOAD_SUBRESOURCE, load_context); michael@0: var origin = extract_origin(sruri); michael@0: if (preconns.indexOf(origin) === -1) { michael@0: preconns.push(origin); michael@0: } michael@0: } michael@0: michael@0: var loaduri = newURI("http://localhost:4444/anotherpage.html"); michael@0: var verifier = new Verifier("origin", preconns, []); michael@0: seer.predict(loaduri, null, seer.PREDICT_LOAD, load_context, verifier); michael@0: } michael@0: michael@0: var tests = [ michael@0: test_link_hover, michael@0: test_pageload, michael@0: test_redirect, michael@0: test_startup, michael@0: test_dns, michael@0: test_origin michael@0: ]; michael@0: michael@0: function run_test() { michael@0: tests.forEach(add_test); michael@0: profile = do_get_profile(); michael@0: seer = Cc["@mozilla.org/network/seer;1"].getService(Ci.nsINetworkSeer); michael@0: do_register_cleanup(reset_seer); michael@0: run_next_test(); michael@0: }