|
1 # This Source Code Form is subject to the terms of the Mozilla Public |
|
2 # License, v. 2.0. If a copy of the MPL was not distributed with this |
|
3 # file, You can obtain one at http://mozilla.org/MPL/2.0/. |
|
4 |
|
5 // A simple class that encapsulates a request. You'll notice the |
|
6 // style here is different from the rest of the extension; that's |
|
7 // because this was re-used from really old code we had. At some |
|
8 // point it might be nice to replace this with something better |
|
9 // (e.g., something that has explicit onerror handler, ability |
|
10 // to set headers, and so on). |
|
11 |
|
12 /** |
|
13 * Because we might be in a component, we can't just assume that |
|
14 * XMLHttpRequest exists. So we use this tiny factory function to wrap the |
|
15 * XPCOM version. |
|
16 * |
|
17 * @return XMLHttpRequest object |
|
18 */ |
|
19 function PROT_NewXMLHttpRequest() { |
|
20 var Cc = Components.classes; |
|
21 var Ci = Components.interfaces; |
|
22 var request = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"] |
|
23 .createInstance(Ci.nsIXMLHttpRequest); |
|
24 // Need the following so we get onerror/load/progresschange |
|
25 request.QueryInterface(Ci.nsIJSXMLHttpRequest); |
|
26 return request; |
|
27 } |
|
28 |
|
29 /** |
|
30 * A helper class that does HTTP GETs and calls back a function with |
|
31 * the content it receives. Asynchronous, so uses a closure for the |
|
32 * callback. |
|
33 * |
|
34 * Note, that XMLFetcher is only used for SafeBrowsing, therefore |
|
35 * we inherit from nsILoadContext, so we can use the callbacks on the |
|
36 * channel to separate the safebrowsing cookie based on a reserved |
|
37 * appId. |
|
38 * @constructor |
|
39 */ |
|
40 function PROT_XMLFetcher() { |
|
41 this.debugZone = "xmlfetcher"; |
|
42 this._request = PROT_NewXMLHttpRequest(); |
|
43 // implements nsILoadContext |
|
44 this.appId = Ci.nsIScriptSecurityManager.SAFEBROWSING_APP_ID; |
|
45 this.isInBrowserElement = false; |
|
46 this.usePrivateBrowsing = false; |
|
47 this.isContent = false; |
|
48 } |
|
49 |
|
50 PROT_XMLFetcher.prototype = { |
|
51 /** |
|
52 * Function that will be called back upon fetch completion. |
|
53 */ |
|
54 _callback: null, |
|
55 |
|
56 |
|
57 /** |
|
58 * Fetches some content. |
|
59 * |
|
60 * @param page URL to fetch |
|
61 * @param callback Function to call back when complete. |
|
62 */ |
|
63 get: function(page, callback) { |
|
64 this._request.abort(); // abort() is asynchronous, so |
|
65 this._request = PROT_NewXMLHttpRequest(); |
|
66 this._callback = callback; |
|
67 var asynchronous = true; |
|
68 this._request.open("GET", page, asynchronous); |
|
69 this._request.channel.notificationCallbacks = this; |
|
70 |
|
71 // Create a closure |
|
72 var self = this; |
|
73 this._request.addEventListener("readystatechange", function() { |
|
74 self.readyStateChange(self); |
|
75 }, false); |
|
76 |
|
77 this._request.send(null); |
|
78 }, |
|
79 |
|
80 cancel: function() { |
|
81 this._request.abort(); |
|
82 this._request = null; |
|
83 }, |
|
84 |
|
85 /** |
|
86 * Called periodically by the request to indicate some state change. 4 |
|
87 * means content has been received. |
|
88 */ |
|
89 readyStateChange: function(fetcher) { |
|
90 if (fetcher._request.readyState != 4) |
|
91 return; |
|
92 |
|
93 // If the request fails, on trunk we get status set to |
|
94 // NS_ERROR_NOT_AVAILABLE. On 1.8.1 branch we get an exception |
|
95 // forwarded from nsIHttpChannel::GetResponseStatus. To be consistent |
|
96 // between branch and trunk, we send back NS_ERROR_NOT_AVAILABLE for |
|
97 // http failures. |
|
98 var responseText = null; |
|
99 var status = Components.results.NS_ERROR_NOT_AVAILABLE; |
|
100 try { |
|
101 G_Debug(this, "xml fetch status code: \"" + |
|
102 fetcher._request.status + "\""); |
|
103 status = fetcher._request.status; |
|
104 responseText = fetcher._request.responseText; |
|
105 } catch(e) { |
|
106 G_Debug(this, "Caught exception trying to read xmlhttprequest " + |
|
107 "status/response."); |
|
108 G_Debug(this, e); |
|
109 } |
|
110 if (fetcher._callback) |
|
111 fetcher._callback(responseText, status); |
|
112 }, |
|
113 |
|
114 // nsIInterfaceRequestor |
|
115 getInterface: function(iid) { |
|
116 return this.QueryInterface(iid); |
|
117 }, |
|
118 |
|
119 QueryInterface: XPCOMUtils.generateQI([Ci.nsIInterfaceRequestor, |
|
120 Ci.nsISupports, |
|
121 Ci.nsILoadContext]) |
|
122 }; |