1 | // Copyright 2006 The Closure Library Authors. All Rights Reserved. |
2 | // |
3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
4 | // you may not use this file except in compliance with the License. |
5 | // You may obtain a copy of the License at |
6 | // |
7 | // http://www.apache.org/licenses/LICENSE-2.0 |
8 | // |
9 | // Unless required by applicable law or agreed to in writing, software |
10 | // distributed under the License is distributed on an "AS-IS" BASIS, |
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
12 | // See the License for the specific language governing permissions and |
13 | // limitations under the License. |
14 | |
15 | /** |
16 | * @fileoverview Low level handling of XMLHttpRequest. |
17 | * @author arv@google.com (Erik Arvidsson) |
18 | * @author dbk@google.com (David Barrett-Kahn) |
19 | */ |
20 | |
21 | goog.provide('goog.net.DefaultXmlHttpFactory'); |
22 | goog.provide('goog.net.XmlHttp'); |
23 | goog.provide('goog.net.XmlHttp.OptionType'); |
24 | goog.provide('goog.net.XmlHttp.ReadyState'); |
25 | |
26 | goog.require('goog.net.WrapperXmlHttpFactory'); |
27 | goog.require('goog.net.XmlHttpFactory'); |
28 | |
29 | |
30 | /** |
31 | * Static class for creating XMLHttpRequest objects. |
32 | * @return {!(XMLHttpRequest|GearsHttpRequest)} A new XMLHttpRequest object. |
33 | */ |
34 | goog.net.XmlHttp = function() { |
35 | return goog.net.XmlHttp.factory_.createInstance(); |
36 | }; |
37 | |
38 | |
39 | /** |
40 | * @define {boolean} Whether to assume XMLHttpRequest exists. Setting this to |
41 | * true strips the ActiveX probing code. |
42 | */ |
43 | goog.define('goog.net.XmlHttp.ASSUME_NATIVE_XHR', false); |
44 | |
45 | |
46 | /** |
47 | * Gets the options to use with the XMLHttpRequest objects obtained using |
48 | * the static methods. |
49 | * @return {Object} The options. |
50 | */ |
51 | goog.net.XmlHttp.getOptions = function() { |
52 | return goog.net.XmlHttp.factory_.getOptions(); |
53 | }; |
54 | |
55 | |
56 | /** |
57 | * Type of options that an XmlHttp object can have. |
58 | * @enum {number} |
59 | */ |
60 | goog.net.XmlHttp.OptionType = { |
61 | /** |
62 | * Whether a goog.nullFunction should be used to clear the onreadystatechange |
63 | * handler instead of null. |
64 | */ |
65 | USE_NULL_FUNCTION: 0, |
66 | |
67 | /** |
68 | * NOTE(user): In IE if send() errors on a *local* request the readystate |
69 | * is still changed to COMPLETE. We need to ignore it and allow the |
70 | * try/catch around send() to pick up the error. |
71 | */ |
72 | LOCAL_REQUEST_ERROR: 1 |
73 | }; |
74 | |
75 | |
76 | /** |
77 | * Status constants for XMLHTTP, matches: |
78 | * http://msdn.microsoft.com/library/default.asp?url=/library/ |
79 | * en-us/xmlsdk/html/0e6a34e4-f90c-489d-acff-cb44242fafc6.asp |
80 | * @enum {number} |
81 | */ |
82 | goog.net.XmlHttp.ReadyState = { |
83 | /** |
84 | * Constant for when xmlhttprequest.readyState is uninitialized |
85 | */ |
86 | UNINITIALIZED: 0, |
87 | |
88 | /** |
89 | * Constant for when xmlhttprequest.readyState is loading. |
90 | */ |
91 | LOADING: 1, |
92 | |
93 | /** |
94 | * Constant for when xmlhttprequest.readyState is loaded. |
95 | */ |
96 | LOADED: 2, |
97 | |
98 | /** |
99 | * Constant for when xmlhttprequest.readyState is in an interactive state. |
100 | */ |
101 | INTERACTIVE: 3, |
102 | |
103 | /** |
104 | * Constant for when xmlhttprequest.readyState is completed |
105 | */ |
106 | COMPLETE: 4 |
107 | }; |
108 | |
109 | |
110 | /** |
111 | * The global factory instance for creating XMLHttpRequest objects. |
112 | * @type {goog.net.XmlHttpFactory} |
113 | * @private |
114 | */ |
115 | goog.net.XmlHttp.factory_; |
116 | |
117 | |
118 | /** |
119 | * Sets the factories for creating XMLHttpRequest objects and their options. |
120 | * @param {Function} factory The factory for XMLHttpRequest objects. |
121 | * @param {Function} optionsFactory The factory for options. |
122 | * @deprecated Use setGlobalFactory instead. |
123 | */ |
124 | goog.net.XmlHttp.setFactory = function(factory, optionsFactory) { |
125 | goog.net.XmlHttp.setGlobalFactory(new goog.net.WrapperXmlHttpFactory( |
126 | /** @type {function() : !(XMLHttpRequest|GearsHttpRequest)} */ (factory), |
127 | /** @type {function() : !Object}*/ (optionsFactory))); |
128 | }; |
129 | |
130 | |
131 | /** |
132 | * Sets the global factory object. |
133 | * @param {!goog.net.XmlHttpFactory} factory New global factory object. |
134 | */ |
135 | goog.net.XmlHttp.setGlobalFactory = function(factory) { |
136 | goog.net.XmlHttp.factory_ = factory; |
137 | }; |
138 | |
139 | |
140 | |
141 | /** |
142 | * Default factory to use when creating xhr objects. You probably shouldn't be |
143 | * instantiating this directly, but rather using it via goog.net.XmlHttp. |
144 | * @extends {goog.net.XmlHttpFactory} |
145 | * @constructor |
146 | */ |
147 | goog.net.DefaultXmlHttpFactory = function() { |
148 | goog.net.XmlHttpFactory.call(this); |
149 | }; |
150 | goog.inherits(goog.net.DefaultXmlHttpFactory, goog.net.XmlHttpFactory); |
151 | |
152 | |
153 | /** @override */ |
154 | goog.net.DefaultXmlHttpFactory.prototype.createInstance = function() { |
155 | var progId = this.getProgId_(); |
156 | if (progId) { |
157 | return new ActiveXObject(progId); |
158 | } else { |
159 | return new XMLHttpRequest(); |
160 | } |
161 | }; |
162 | |
163 | |
164 | /** @override */ |
165 | goog.net.DefaultXmlHttpFactory.prototype.internalGetOptions = function() { |
166 | var progId = this.getProgId_(); |
167 | var options = {}; |
168 | if (progId) { |
169 | options[goog.net.XmlHttp.OptionType.USE_NULL_FUNCTION] = true; |
170 | options[goog.net.XmlHttp.OptionType.LOCAL_REQUEST_ERROR] = true; |
171 | } |
172 | return options; |
173 | }; |
174 | |
175 | |
176 | /** |
177 | * The ActiveX PROG ID string to use to create xhr's in IE. Lazily initialized. |
178 | * @type {string|undefined} |
179 | * @private |
180 | */ |
181 | goog.net.DefaultXmlHttpFactory.prototype.ieProgId_; |
182 | |
183 | |
184 | /** |
185 | * Initialize the private state used by other functions. |
186 | * @return {string} The ActiveX PROG ID string to use to create xhr's in IE. |
187 | * @private |
188 | */ |
189 | goog.net.DefaultXmlHttpFactory.prototype.getProgId_ = function() { |
190 | if (goog.net.XmlHttp.ASSUME_NATIVE_XHR) { |
191 | return ''; |
192 | } |
193 | |
194 | // The following blog post describes what PROG IDs to use to create the |
195 | // XMLHTTP object in Internet Explorer: |
196 | // http://blogs.msdn.com/xmlteam/archive/2006/10/23/using-the-right-version-of-msxml-in-internet-explorer.aspx |
197 | // However we do not (yet) fully trust that this will be OK for old versions |
198 | // of IE on Win9x so we therefore keep the last 2. |
199 | if (!this.ieProgId_ && typeof XMLHttpRequest == 'undefined' && |
200 | typeof ActiveXObject != 'undefined') { |
201 | // Candidate Active X types. |
202 | var ACTIVE_X_IDENTS = ['MSXML2.XMLHTTP.6.0', 'MSXML2.XMLHTTP.3.0', |
203 | 'MSXML2.XMLHTTP', 'Microsoft.XMLHTTP']; |
204 | for (var i = 0; i < ACTIVE_X_IDENTS.length; i++) { |
205 | var candidate = ACTIVE_X_IDENTS[i]; |
206 | /** @preserveTry */ |
207 | try { |
208 | new ActiveXObject(candidate); |
209 | // NOTE(user): cannot assign progid and return candidate in one line |
210 | // because JSCompiler complaings: BUG 658126 |
211 | this.ieProgId_ = candidate; |
212 | return candidate; |
213 | } catch (e) { |
214 | // do nothing; try next choice |
215 | } |
216 | } |
217 | |
218 | // couldn't find any matches |
219 | throw Error('Could not create ActiveXObject. ActiveX might be disabled,' + |
220 | ' or MSXML might not be installed'); |
221 | } |
222 | |
223 | return /** @type {string} */ (this.ieProgId_); |
224 | }; |
225 | |
226 | |
227 | //Set the global factory to an instance of the default factory. |
228 | goog.net.XmlHttp.setGlobalFactory(new goog.net.DefaultXmlHttpFactory()); |