// Copyright 2006 The Closure Library Authors. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS-IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. /** * @fileoverview Low level handling of XMLHttpRequest. * @author arv@google.com (Erik Arvidsson) * @author dbk@google.com (David Barrett-Kahn) */ goog.provide('goog.net.DefaultXmlHttpFactory'); goog.provide('goog.net.XmlHttp'); goog.provide('goog.net.XmlHttp.OptionType'); goog.provide('goog.net.XmlHttp.ReadyState'); goog.provide('goog.net.XmlHttpDefines'); goog.require('goog.asserts'); goog.require('goog.net.WrapperXmlHttpFactory'); goog.require('goog.net.XmlHttpFactory'); /** * Static class for creating XMLHttpRequest objects. * @return {!goog.net.XhrLike.OrNative} A new XMLHttpRequest object. */ goog.net.XmlHttp = function() { return goog.net.XmlHttp.factory_.createInstance(); }; /** * @define {boolean} Whether to assume XMLHttpRequest exists. Setting this to * true bypasses the ActiveX probing code. * NOTE(ruilopes): Due to the way JSCompiler works, this define *will not* strip * out the ActiveX probing code from binaries. To achieve this, use * {@code goog.net.XmlHttpDefines.ASSUME_NATIVE_XHR} instead. * TODO(ruilopes): Collapse both defines. */ goog.define('goog.net.XmlHttp.ASSUME_NATIVE_XHR', false); /** @const */ goog.net.XmlHttpDefines = {}; /** * @define {boolean} Whether to assume XMLHttpRequest exists. Setting this to * true eliminates the ActiveX probing code. */ goog.define('goog.net.XmlHttpDefines.ASSUME_NATIVE_XHR', false); /** * Gets the options to use with the XMLHttpRequest objects obtained using * the static methods. * @return {Object} The options. */ goog.net.XmlHttp.getOptions = function() { return goog.net.XmlHttp.factory_.getOptions(); }; /** * Type of options that an XmlHttp object can have. * @enum {number} */ goog.net.XmlHttp.OptionType = { /** * Whether a goog.nullFunction should be used to clear the onreadystatechange * handler instead of null. */ USE_NULL_FUNCTION: 0, /** * NOTE(user): In IE if send() errors on a *local* request the readystate * is still changed to COMPLETE. We need to ignore it and allow the * try/catch around send() to pick up the error. */ LOCAL_REQUEST_ERROR: 1 }; /** * Status constants for XMLHTTP, matches: * https://msdn.microsoft.com/en-us/library/ms534361(v=vs.85).aspx * @enum {number} */ goog.net.XmlHttp.ReadyState = { /** * Constant for when xmlhttprequest.readyState is uninitialized */ UNINITIALIZED: 0, /** * Constant for when xmlhttprequest.readyState is loading. */ LOADING: 1, /** * Constant for when xmlhttprequest.readyState is loaded. */ LOADED: 2, /** * Constant for when xmlhttprequest.readyState is in an interactive state. */ INTERACTIVE: 3, /** * Constant for when xmlhttprequest.readyState is completed */ COMPLETE: 4 }; /** * The global factory instance for creating XMLHttpRequest objects. * @type {goog.net.XmlHttpFactory} * @private */ goog.net.XmlHttp.factory_; /** * Sets the factories for creating XMLHttpRequest objects and their options. * @param {Function} factory The factory for XMLHttpRequest objects. * @param {Function} optionsFactory The factory for options. * @deprecated Use setGlobalFactory instead. */ goog.net.XmlHttp.setFactory = function(factory, optionsFactory) { goog.net.XmlHttp.setGlobalFactory( new goog.net.WrapperXmlHttpFactory( goog.asserts.assert(factory), goog.asserts.assert(optionsFactory))); }; /** * Sets the global factory object. * @param {!goog.net.XmlHttpFactory} factory New global factory object. */ goog.net.XmlHttp.setGlobalFactory = function(factory) { goog.net.XmlHttp.factory_ = factory; }; /** * Default factory to use when creating xhr objects. You probably shouldn't be * instantiating this directly, but rather using it via goog.net.XmlHttp. * @extends {goog.net.XmlHttpFactory} * @constructor */ goog.net.DefaultXmlHttpFactory = function() { goog.net.XmlHttpFactory.call(this); }; goog.inherits(goog.net.DefaultXmlHttpFactory, goog.net.XmlHttpFactory); /** @override */ goog.net.DefaultXmlHttpFactory.prototype.createInstance = function() { var progId = this.getProgId_(); if (progId) { return new ActiveXObject(progId); } else { return new XMLHttpRequest(); } }; /** @override */ goog.net.DefaultXmlHttpFactory.prototype.internalGetOptions = function() { var progId = this.getProgId_(); var options = {}; if (progId) { options[goog.net.XmlHttp.OptionType.USE_NULL_FUNCTION] = true; options[goog.net.XmlHttp.OptionType.LOCAL_REQUEST_ERROR] = true; } return options; }; /** * The ActiveX PROG ID string to use to create xhr's in IE. Lazily initialized. * @type {string|undefined} * @private */ goog.net.DefaultXmlHttpFactory.prototype.ieProgId_; /** * Initialize the private state used by other functions. * @return {string} The ActiveX PROG ID string to use to create xhr's in IE. * @private */ goog.net.DefaultXmlHttpFactory.prototype.getProgId_ = function() { if (goog.net.XmlHttp.ASSUME_NATIVE_XHR || goog.net.XmlHttpDefines.ASSUME_NATIVE_XHR) { return ''; } // The following blog post describes what PROG IDs to use to create the // XMLHTTP object in Internet Explorer: // http://blogs.msdn.com/xmlteam/archive/2006/10/23/using-the-right-version-of-msxml-in-internet-explorer.aspx // However we do not (yet) fully trust that this will be OK for old versions // of IE on Win9x so we therefore keep the last 2. if (!this.ieProgId_ && typeof XMLHttpRequest == 'undefined' && typeof ActiveXObject != 'undefined') { // Candidate Active X types. var ACTIVE_X_IDENTS = [ 'MSXML2.XMLHTTP.6.0', 'MSXML2.XMLHTTP.3.0', 'MSXML2.XMLHTTP', 'Microsoft.XMLHTTP' ]; for (var i = 0; i < ACTIVE_X_IDENTS.length; i++) { var candidate = ACTIVE_X_IDENTS[i]; try { new ActiveXObject(candidate); // NOTE(user): cannot assign progid and return candidate in one line // because JSCompiler complaings: BUG 658126 this.ieProgId_ = candidate; return candidate; } catch (e) { // do nothing; try next choice } } // couldn't find any matches throw Error( 'Could not create ActiveXObject. ActiveX might be disabled,' + ' or MSXML might not be installed'); } return /** @type {string} */ (this.ieProgId_); }; // Set the global factory to an instance of the default factory. goog.net.XmlHttp.setGlobalFactory(new goog.net.DefaultXmlHttpFactory());