1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/toolkit/components/url-classifier/content/xml-fetcher.js Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,122 @@ 1.4 +# This Source Code Form is subject to the terms of the Mozilla Public 1.5 +# License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 +# file, You can obtain one at http://mozilla.org/MPL/2.0/. 1.7 + 1.8 +// A simple class that encapsulates a request. You'll notice the 1.9 +// style here is different from the rest of the extension; that's 1.10 +// because this was re-used from really old code we had. At some 1.11 +// point it might be nice to replace this with something better 1.12 +// (e.g., something that has explicit onerror handler, ability 1.13 +// to set headers, and so on). 1.14 + 1.15 +/** 1.16 + * Because we might be in a component, we can't just assume that 1.17 + * XMLHttpRequest exists. So we use this tiny factory function to wrap the 1.18 + * XPCOM version. 1.19 + * 1.20 + * @return XMLHttpRequest object 1.21 + */ 1.22 +function PROT_NewXMLHttpRequest() { 1.23 + var Cc = Components.classes; 1.24 + var Ci = Components.interfaces; 1.25 + var request = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"] 1.26 + .createInstance(Ci.nsIXMLHttpRequest); 1.27 + // Need the following so we get onerror/load/progresschange 1.28 + request.QueryInterface(Ci.nsIJSXMLHttpRequest); 1.29 + return request; 1.30 +} 1.31 + 1.32 +/** 1.33 + * A helper class that does HTTP GETs and calls back a function with 1.34 + * the content it receives. Asynchronous, so uses a closure for the 1.35 + * callback. 1.36 + * 1.37 + * Note, that XMLFetcher is only used for SafeBrowsing, therefore 1.38 + * we inherit from nsILoadContext, so we can use the callbacks on the 1.39 + * channel to separate the safebrowsing cookie based on a reserved 1.40 + * appId. 1.41 + * @constructor 1.42 + */ 1.43 +function PROT_XMLFetcher() { 1.44 + this.debugZone = "xmlfetcher"; 1.45 + this._request = PROT_NewXMLHttpRequest(); 1.46 + // implements nsILoadContext 1.47 + this.appId = Ci.nsIScriptSecurityManager.SAFEBROWSING_APP_ID; 1.48 + this.isInBrowserElement = false; 1.49 + this.usePrivateBrowsing = false; 1.50 + this.isContent = false; 1.51 +} 1.52 + 1.53 +PROT_XMLFetcher.prototype = { 1.54 + /** 1.55 + * Function that will be called back upon fetch completion. 1.56 + */ 1.57 + _callback: null, 1.58 + 1.59 + 1.60 + /** 1.61 + * Fetches some content. 1.62 + * 1.63 + * @param page URL to fetch 1.64 + * @param callback Function to call back when complete. 1.65 + */ 1.66 + get: function(page, callback) { 1.67 + this._request.abort(); // abort() is asynchronous, so 1.68 + this._request = PROT_NewXMLHttpRequest(); 1.69 + this._callback = callback; 1.70 + var asynchronous = true; 1.71 + this._request.open("GET", page, asynchronous); 1.72 + this._request.channel.notificationCallbacks = this; 1.73 + 1.74 + // Create a closure 1.75 + var self = this; 1.76 + this._request.addEventListener("readystatechange", function() { 1.77 + self.readyStateChange(self); 1.78 + }, false); 1.79 + 1.80 + this._request.send(null); 1.81 + }, 1.82 + 1.83 + cancel: function() { 1.84 + this._request.abort(); 1.85 + this._request = null; 1.86 + }, 1.87 + 1.88 + /** 1.89 + * Called periodically by the request to indicate some state change. 4 1.90 + * means content has been received. 1.91 + */ 1.92 + readyStateChange: function(fetcher) { 1.93 + if (fetcher._request.readyState != 4) 1.94 + return; 1.95 + 1.96 + // If the request fails, on trunk we get status set to 1.97 + // NS_ERROR_NOT_AVAILABLE. On 1.8.1 branch we get an exception 1.98 + // forwarded from nsIHttpChannel::GetResponseStatus. To be consistent 1.99 + // between branch and trunk, we send back NS_ERROR_NOT_AVAILABLE for 1.100 + // http failures. 1.101 + var responseText = null; 1.102 + var status = Components.results.NS_ERROR_NOT_AVAILABLE; 1.103 + try { 1.104 + G_Debug(this, "xml fetch status code: \"" + 1.105 + fetcher._request.status + "\""); 1.106 + status = fetcher._request.status; 1.107 + responseText = fetcher._request.responseText; 1.108 + } catch(e) { 1.109 + G_Debug(this, "Caught exception trying to read xmlhttprequest " + 1.110 + "status/response."); 1.111 + G_Debug(this, e); 1.112 + } 1.113 + if (fetcher._callback) 1.114 + fetcher._callback(responseText, status); 1.115 + }, 1.116 + 1.117 + // nsIInterfaceRequestor 1.118 + getInterface: function(iid) { 1.119 + return this.QueryInterface(iid); 1.120 + }, 1.121 + 1.122 + QueryInterface: XPCOMUtils.generateQI([Ci.nsIInterfaceRequestor, 1.123 + Ci.nsISupports, 1.124 + Ci.nsILoadContext]) 1.125 +};