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 | goog.provide('goog.net.XmlHttpDefines'); |
26 | |
27 | goog.require('goog.asserts'); |
28 | goog.require('goog.net.WrapperXmlHttpFactory'); |
29 | goog.require('goog.net.XmlHttpFactory'); |
30 | |
31 | |
32 | /** |
33 | * Static class for creating XMLHttpRequest objects. |
34 | * @return {!goog.net.XhrLike.OrNative} A new XMLHttpRequest object. |
35 | */ |
36 | goog.net.XmlHttp = function() { |
37 | return goog.net.XmlHttp.factory_.createInstance(); |
38 | }; |
39 | |
40 | |
41 | /** |
42 | * @define {boolean} Whether to assume XMLHttpRequest exists. Setting this to |
43 | * true bypasses the ActiveX probing code. |
44 | * NOTE(user): Due to the way JSCompiler works, this define *will not* strip |
45 | * out the ActiveX probing code from binaries. To achieve this, use |
46 | * {@code goog.net.XmlHttpDefines.ASSUME_NATIVE_XHR} instead. |
47 | * TODO(user): Collapse both defines. |
48 | */ |
49 | goog.define('goog.net.XmlHttp.ASSUME_NATIVE_XHR', false); |
50 | |
51 | |
52 | /** @const */ |
53 | goog.net.XmlHttpDefines = {}; |
54 | |
55 | |
56 | /** |
57 | * @define {boolean} Whether to assume XMLHttpRequest exists. Setting this to |
58 | * true eliminates the ActiveX probing code. |
59 | */ |
60 | goog.define('goog.net.XmlHttpDefines.ASSUME_NATIVE_XHR', false); |
61 | |
62 | |
63 | /** |
64 | * Gets the options to use with the XMLHttpRequest objects obtained using |
65 | * the static methods. |
66 | * @return {Object} The options. |
67 | */ |
68 | goog.net.XmlHttp.getOptions = function() { |
69 | return goog.net.XmlHttp.factory_.getOptions(); |
70 | }; |
71 | |
72 | |
73 | /** |
74 | * Type of options that an XmlHttp object can have. |
75 | * @enum {number} |
76 | */ |
77 | goog.net.XmlHttp.OptionType = { |
78 | /** |
79 | * Whether a goog.nullFunction should be used to clear the onreadystatechange |
80 | * handler instead of null. |
81 | */ |
82 | USE_NULL_FUNCTION: 0, |
83 | |
84 | /** |
85 | * NOTE(user): In IE if send() errors on a *local* request the readystate |
86 | * is still changed to COMPLETE. We need to ignore it and allow the |
87 | * try/catch around send() to pick up the error. |
88 | */ |
89 | LOCAL_REQUEST_ERROR: 1 |
90 | }; |
91 | |
92 | |
93 | /** |
94 | * Status constants for XMLHTTP, matches: |
95 | * http://msdn.microsoft.com/library/default.asp?url=/library/ |
96 | * en-us/xmlsdk/html/0e6a34e4-f90c-489d-acff-cb44242fafc6.asp |
97 | * @enum {number} |
98 | */ |
99 | goog.net.XmlHttp.ReadyState = { |
100 | /** |
101 | * Constant for when xmlhttprequest.readyState is uninitialized |
102 | */ |
103 | UNINITIALIZED: 0, |
104 | |
105 | /** |
106 | * Constant for when xmlhttprequest.readyState is loading. |
107 | */ |
108 | LOADING: 1, |
109 | |
110 | /** |
111 | * Constant for when xmlhttprequest.readyState is loaded. |
112 | */ |
113 | LOADED: 2, |
114 | |
115 | /** |
116 | * Constant for when xmlhttprequest.readyState is in an interactive state. |
117 | */ |
118 | INTERACTIVE: 3, |
119 | |
120 | /** |
121 | * Constant for when xmlhttprequest.readyState is completed |
122 | */ |
123 | COMPLETE: 4 |
124 | }; |
125 | |
126 | |
127 | /** |
128 | * The global factory instance for creating XMLHttpRequest objects. |
129 | * @type {goog.net.XmlHttpFactory} |
130 | * @private |
131 | */ |
132 | goog.net.XmlHttp.factory_; |
133 | |
134 | |
135 | /** |
136 | * Sets the factories for creating XMLHttpRequest objects and their options. |
137 | * @param {Function} factory The factory for XMLHttpRequest objects. |
138 | * @param {Function} optionsFactory The factory for options. |
139 | * @deprecated Use setGlobalFactory instead. |
140 | */ |
141 | goog.net.XmlHttp.setFactory = function(factory, optionsFactory) { |
142 | goog.net.XmlHttp.setGlobalFactory(new goog.net.WrapperXmlHttpFactory( |
143 | goog.asserts.assert(factory), |
144 | goog.asserts.assert(optionsFactory))); |
145 | }; |
146 | |
147 | |
148 | /** |
149 | * Sets the global factory object. |
150 | * @param {!goog.net.XmlHttpFactory} factory New global factory object. |
151 | */ |
152 | goog.net.XmlHttp.setGlobalFactory = function(factory) { |
153 | goog.net.XmlHttp.factory_ = factory; |
154 | }; |
155 | |
156 | |
157 | |
158 | /** |
159 | * Default factory to use when creating xhr objects. You probably shouldn't be |
160 | * instantiating this directly, but rather using it via goog.net.XmlHttp. |
161 | * @extends {goog.net.XmlHttpFactory} |
162 | * @constructor |
163 | */ |
164 | goog.net.DefaultXmlHttpFactory = function() { |
165 | goog.net.XmlHttpFactory.call(this); |
166 | }; |
167 | goog.inherits(goog.net.DefaultXmlHttpFactory, goog.net.XmlHttpFactory); |
168 | |
169 | |
170 | /** @override */ |
171 | goog.net.DefaultXmlHttpFactory.prototype.createInstance = function() { |
172 | var progId = this.getProgId_(); |
173 | if (progId) { |
174 | return new ActiveXObject(progId); |
175 | } else { |
176 | return new XMLHttpRequest(); |
177 | } |
178 | }; |
179 | |
180 | |
181 | /** @override */ |
182 | goog.net.DefaultXmlHttpFactory.prototype.internalGetOptions = function() { |
183 | var progId = this.getProgId_(); |
184 | var options = {}; |
185 | if (progId) { |
186 | options[goog.net.XmlHttp.OptionType.USE_NULL_FUNCTION] = true; |
187 | options[goog.net.XmlHttp.OptionType.LOCAL_REQUEST_ERROR] = true; |
188 | } |
189 | return options; |
190 | }; |
191 | |
192 | |
193 | /** |
194 | * The ActiveX PROG ID string to use to create xhr's in IE. Lazily initialized. |
195 | * @type {string|undefined} |
196 | * @private |
197 | */ |
198 | goog.net.DefaultXmlHttpFactory.prototype.ieProgId_; |
199 | |
200 | |
201 | /** |
202 | * Initialize the private state used by other functions. |
203 | * @return {string} The ActiveX PROG ID string to use to create xhr's in IE. |
204 | * @private |
205 | */ |
206 | goog.net.DefaultXmlHttpFactory.prototype.getProgId_ = function() { |
207 | if (goog.net.XmlHttp.ASSUME_NATIVE_XHR || |
208 | goog.net.XmlHttpDefines.ASSUME_NATIVE_XHR) { |
209 | return ''; |
210 | } |
211 | |
212 | // The following blog post describes what PROG IDs to use to create the |
213 | // XMLHTTP object in Internet Explorer: |
214 | // http://blogs.msdn.com/xmlteam/archive/2006/10/23/using-the-right-version-of-msxml-in-internet-explorer.aspx |
215 | // However we do not (yet) fully trust that this will be OK for old versions |
216 | // of IE on Win9x so we therefore keep the last 2. |
217 | if (!this.ieProgId_ && typeof XMLHttpRequest == 'undefined' && |
218 | typeof ActiveXObject != 'undefined') { |
219 | // Candidate Active X types. |
220 | var ACTIVE_X_IDENTS = ['MSXML2.XMLHTTP.6.0', 'MSXML2.XMLHTTP.3.0', |
221 | 'MSXML2.XMLHTTP', 'Microsoft.XMLHTTP']; |
222 | for (var i = 0; i < ACTIVE_X_IDENTS.length; i++) { |
223 | var candidate = ACTIVE_X_IDENTS[i]; |
224 | /** @preserveTry */ |
225 | try { |
226 | new ActiveXObject(candidate); |
227 | // NOTE(user): cannot assign progid and return candidate in one line |
228 | // because JSCompiler complaings: BUG 658126 |
229 | this.ieProgId_ = candidate; |
230 | return candidate; |
231 | } catch (e) { |
232 | // do nothing; try next choice |
233 | } |
234 | } |
235 | |
236 | // couldn't find any matches |
237 | throw Error('Could not create ActiveXObject. ActiveX might be disabled,' + |
238 | ' or MSXML might not be installed'); |
239 | } |
240 | |
241 | return /** @type {string} */ (this.ieProgId_); |
242 | }; |
243 | |
244 | |
245 | //Set the global factory to an instance of the default factory. |
246 | goog.net.XmlHttp.setGlobalFactory(new goog.net.DefaultXmlHttpFactory()); |