initial commit
This commit is contained in:
Executable
+506
@@ -0,0 +1,506 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright The Closure Library Authors.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @fileoverview Functions for setting, getting and deleting cookies.
|
||||
*/
|
||||
|
||||
|
||||
goog.provide('goog.net.Cookies');
|
||||
|
||||
goog.require('goog.string');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* A class for handling browser cookies.
|
||||
* @param {?Document} context The context document to get/set cookies on.
|
||||
* @constructor
|
||||
* @final
|
||||
*/
|
||||
goog.net.Cookies = function(context) {
|
||||
'use strict';
|
||||
/**
|
||||
* The context document to get/set cookies on. If no document context is
|
||||
* passed, use a fake one with only the "cookie" attribute. This allows
|
||||
* this class to be instantiated safely in web worker environments.
|
||||
* @private {{cookie: string}}
|
||||
*/
|
||||
this.document_ = context || {cookie: ''};
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Static constant for the size of cookies. Per the spec, there's a 4K limit
|
||||
* to the size of a cookie. To make sure users can't break this limit, we
|
||||
* should truncate long cookies at 3950 bytes, to be extra careful with dumb
|
||||
* browsers/proxies that interpret 4K as 4000 rather than 4096.
|
||||
* @const {number}
|
||||
*/
|
||||
goog.net.Cookies.MAX_COOKIE_LENGTH = 3950;
|
||||
|
||||
|
||||
/**
|
||||
* The name of the test cookie to set.
|
||||
*
|
||||
*
|
||||
* @private @const {string}
|
||||
*/
|
||||
goog.net.Cookies.TEST_COOKIE_NAME_ = 'TESTCOOKIESENABLED';
|
||||
|
||||
|
||||
/**
|
||||
* The value of the test cookie to set.
|
||||
* @private @const {string}
|
||||
*/
|
||||
goog.net.Cookies.TEST_COOKIE_VALUE_ = '1';
|
||||
|
||||
|
||||
/**
|
||||
* Max age of the test cookie in seconds.
|
||||
* @private @const {number}
|
||||
*/
|
||||
goog.net.Cookies.TEST_COOKIE_MAX_AGE_ = 60;
|
||||
|
||||
|
||||
/**
|
||||
* Returns true if cookies are enabled.
|
||||
*
|
||||
* navigator.cookieEnabled is an unreliable API in some browsers such as
|
||||
* Internet Explorer. It will return true even when cookies are actually
|
||||
* blocked. To work around this, check for the presence of cookies, or attempt
|
||||
* to manually set and retrieve a cookie, which is the ultimate test of whether
|
||||
* or not a browser supports cookies.
|
||||
*
|
||||
* @return {boolean} True if cookies are enabled.
|
||||
*/
|
||||
goog.net.Cookies.prototype.isEnabled = function() {
|
||||
'use strict';
|
||||
if (!goog.global.navigator.cookieEnabled) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!this.isEmpty()) {
|
||||
// There are some cookies already set for the current domain, so cookies
|
||||
// can't be totally blocked.
|
||||
return true;
|
||||
}
|
||||
|
||||
// Try setting and reading back a cookie to see if cookies are enabled.
|
||||
this.set(
|
||||
goog.net.Cookies.TEST_COOKIE_NAME_, goog.net.Cookies.TEST_COOKIE_VALUE_,
|
||||
{maxAge: goog.net.Cookies.TEST_COOKIE_MAX_AGE_});
|
||||
if (this.get(goog.net.Cookies.TEST_COOKIE_NAME_) !==
|
||||
goog.net.Cookies.TEST_COOKIE_VALUE_) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Clean up the test cookie.
|
||||
this.remove(goog.net.Cookies.TEST_COOKIE_NAME_);
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* We do not allow '=', ';', or white space in the name.
|
||||
*
|
||||
* NOTE: The following are allowed by this method, but should be avoided for
|
||||
* cookies handled by the server.
|
||||
* - any name starting with '$'
|
||||
* - 'Comment'
|
||||
* - 'Domain'
|
||||
* - 'Expires'
|
||||
* - 'Max-Age'
|
||||
* - 'Path'
|
||||
* - 'Secure'
|
||||
* - 'Version'
|
||||
*
|
||||
* @param {string} name Cookie name.
|
||||
* @return {boolean} Whether name is valid.
|
||||
*
|
||||
* @see <a href="http://tools.ietf.org/html/rfc2109">RFC 2109</a>
|
||||
* @see <a href="http://tools.ietf.org/html/rfc2965">RFC 2965</a>
|
||||
*/
|
||||
goog.net.Cookies.prototype.isValidName = function(name) {
|
||||
'use strict';
|
||||
return !(/[;=\s]/.test(name));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* We do not allow ';' or line break in the value.
|
||||
*
|
||||
* Spec does not mention any illegal characters, but in practice semi-colons
|
||||
* break parsing and line breaks truncate the name.
|
||||
*
|
||||
* @param {string} value Cookie value.
|
||||
* @return {boolean} Whether value is valid.
|
||||
*
|
||||
* @see <a href="http://tools.ietf.org/html/rfc2109">RFC 2109</a>
|
||||
* @see <a href="http://tools.ietf.org/html/rfc2965">RFC 2965</a>
|
||||
*/
|
||||
goog.net.Cookies.prototype.isValidValue = function(value) {
|
||||
'use strict';
|
||||
return !(/[;\r\n]/.test(value));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Sets a cookie. The max_age can be -1 to set a session cookie. To remove and
|
||||
* expire cookies, use remove() instead.
|
||||
*
|
||||
* Neither the `name` nor the `value` are encoded in any way. It is
|
||||
* up to the callers of `get` and `set` (as well as all the other
|
||||
* methods) to handle any possible encoding and decoding.
|
||||
*
|
||||
* @throws {!Error} If the `name` fails #goog.net.cookies.isValidName.
|
||||
* @throws {!Error} If the `value` fails #goog.net.cookies.isValidValue.
|
||||
*
|
||||
* @param {string} name The cookie name.
|
||||
* @param {string} value The cookie value.
|
||||
* @param {!goog.net.Cookies.SetOptions=} options The options object.
|
||||
*/
|
||||
goog.net.Cookies.prototype.set = function(name, value, options) {
|
||||
'use strict';
|
||||
/** @type {number|undefined} */
|
||||
let maxAge;
|
||||
/** @type {string|undefined} */
|
||||
let path;
|
||||
/** @type {string|undefined} */
|
||||
let domain;
|
||||
/** @type {boolean} */
|
||||
let secure = false;
|
||||
/** @type {!goog.net.Cookies.SameSite|undefined} */
|
||||
let sameSite;
|
||||
|
||||
if (typeof options === 'object') {
|
||||
sameSite = options.sameSite;
|
||||
secure = options.secure || false;
|
||||
domain = options.domain || undefined;
|
||||
path = options.path || undefined;
|
||||
maxAge = options.maxAge;
|
||||
}
|
||||
if (!this.isValidName(name)) {
|
||||
throw new Error('Invalid cookie name "' + name + '"');
|
||||
}
|
||||
if (!this.isValidValue(value)) {
|
||||
throw new Error('Invalid cookie value "' + value + '"');
|
||||
}
|
||||
|
||||
if (maxAge === undefined) {
|
||||
maxAge = -1;
|
||||
}
|
||||
|
||||
const domainStr = domain ? ';domain=' + domain : '';
|
||||
const pathStr = path ? ';path=' + path : '';
|
||||
const secureStr = secure ? ';secure' : '';
|
||||
|
||||
let expiresStr;
|
||||
|
||||
// Case 1: Set a session cookie.
|
||||
if (maxAge < 0) {
|
||||
expiresStr = '';
|
||||
|
||||
// Case 2: Remove the cookie.
|
||||
// Note: We don't tell people about this option in the function doc because
|
||||
// we prefer people to use remove() to remove cookies.
|
||||
} else if (maxAge == 0) {
|
||||
// Note: Don't use Jan 1, 1970 for date because NS 4.76 will try to convert
|
||||
// it to local time, and if the local time is before Jan 1, 1970, then the
|
||||
// browser will ignore the Expires attribute altogether.
|
||||
const pastDate = new Date(1970, 1 /*Feb*/, 1); // Feb 1, 1970
|
||||
expiresStr = ';expires=' + pastDate.toUTCString();
|
||||
|
||||
// Case 3: Set a persistent cookie.
|
||||
} else {
|
||||
const futureDate = new Date(Date.now() + maxAge * 1000);
|
||||
expiresStr = ';expires=' + futureDate.toUTCString();
|
||||
}
|
||||
|
||||
const sameSiteStr = sameSite != null ? ';samesite=' + sameSite : '';
|
||||
|
||||
this.setCookie_(
|
||||
name + '=' + value + domainStr + pathStr + expiresStr + secureStr +
|
||||
sameSiteStr);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the value for the first cookie with the given name.
|
||||
* @param {string} name The name of the cookie to get.
|
||||
* @param {string=} opt_default If not found this is returned instead.
|
||||
* @return {string|undefined} The value of the cookie. If no cookie is set this
|
||||
* returns opt_default or undefined if opt_default is not provided.
|
||||
*/
|
||||
goog.net.Cookies.prototype.get = function(name, opt_default) {
|
||||
'use strict';
|
||||
const nameEq = name + '=';
|
||||
const parts = this.getParts_();
|
||||
for (let i = 0, part; i < parts.length; i++) {
|
||||
part = goog.string.trim(parts[i]);
|
||||
// startsWith
|
||||
if (part.lastIndexOf(nameEq, 0) == 0) {
|
||||
return part.substr(nameEq.length);
|
||||
}
|
||||
if (part == name) {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
return opt_default;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Removes and expires a cookie.
|
||||
* @param {string} name The cookie name.
|
||||
* @param {?string=} opt_path The path of the cookie. If null or not present,
|
||||
* expires the cookie set at the full request path.
|
||||
* @param {?string=} opt_domain The domain of the cookie, or null to expire a
|
||||
* cookie set at the full request host name. If not provided, the default is
|
||||
* null (i.e. cookie at full request host name).
|
||||
* @return {boolean} Whether the cookie existed before it was removed.
|
||||
*/
|
||||
goog.net.Cookies.prototype.remove = function(name, opt_path, opt_domain) {
|
||||
'use strict';
|
||||
const rv = this.containsKey(name);
|
||||
this.set(name, '', {maxAge: 0, path: opt_path, domain: opt_domain});
|
||||
return rv;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Gets the names for all the cookies.
|
||||
* @return {!Array<string>} An array with the names of the cookies.
|
||||
*/
|
||||
goog.net.Cookies.prototype.getKeys = function() {
|
||||
'use strict';
|
||||
return this.getKeyValues_().keys;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Gets the values for all the cookies.
|
||||
* @return {!Array<string>} An array with the values of the cookies.
|
||||
*/
|
||||
goog.net.Cookies.prototype.getValues = function() {
|
||||
'use strict';
|
||||
return this.getKeyValues_().values;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {boolean} Whether there are any cookies for this document.
|
||||
*/
|
||||
goog.net.Cookies.prototype.isEmpty = function() {
|
||||
'use strict';
|
||||
return !this.getCookie_();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {number} The number of cookies for this document.
|
||||
*/
|
||||
goog.net.Cookies.prototype.getCount = function() {
|
||||
'use strict';
|
||||
const cookie = this.getCookie_();
|
||||
if (!cookie) {
|
||||
return 0;
|
||||
}
|
||||
return this.getParts_().length;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns whether there is a cookie with the given name.
|
||||
* @param {string} key The name of the cookie to test for.
|
||||
* @return {boolean} Whether there is a cookie by that name.
|
||||
*/
|
||||
goog.net.Cookies.prototype.containsKey = function(key) {
|
||||
'use strict';
|
||||
// substring will return empty string if the key is not found, so the get
|
||||
// function will only return undefined
|
||||
return this.get(key) !== undefined;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns whether there is a cookie with the given value. (This is an O(n)
|
||||
* operation.)
|
||||
* @param {string} value The value to check for.
|
||||
* @return {boolean} Whether there is a cookie with that value.
|
||||
*/
|
||||
goog.net.Cookies.prototype.containsValue = function(value) {
|
||||
'use strict';
|
||||
// this O(n) in any case so lets do the trivial thing.
|
||||
const values = this.getKeyValues_().values;
|
||||
for (let i = 0; i < values.length; i++) {
|
||||
if (values[i] == value) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Removes all cookies for this document. Note that this will only remove
|
||||
* cookies from the current path and domain. If there are cookies set using a
|
||||
* subpath and/or another domain these will still be there.
|
||||
*/
|
||||
goog.net.Cookies.prototype.clear = function() {
|
||||
'use strict';
|
||||
const keys = this.getKeyValues_().keys;
|
||||
for (let i = keys.length - 1; i >= 0; i--) {
|
||||
this.remove(keys[i]);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Private helper function to allow testing cookies without depending on the
|
||||
* browser.
|
||||
* @param {string} s The cookie string to set.
|
||||
* @private
|
||||
*/
|
||||
goog.net.Cookies.prototype.setCookie_ = function(s) {
|
||||
'use strict';
|
||||
this.document_.cookie = s;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Private helper function to allow testing cookies without depending on the
|
||||
* browser. IE6 can return null here.
|
||||
* @return {string} Returns the `document.cookie`.
|
||||
* @private
|
||||
*/
|
||||
goog.net.Cookies.prototype.getCookie_ = function() {
|
||||
'use strict';
|
||||
return this.document_.cookie;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {!Array<string>} The cookie split on semi colons.
|
||||
* @private
|
||||
*/
|
||||
goog.net.Cookies.prototype.getParts_ = function() {
|
||||
'use strict';
|
||||
return (this.getCookie_() || '').split(';');
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Gets the names and values for all the cookies.
|
||||
* @return {{keys:!Array<string>, values:!Array<string>}} An object with keys
|
||||
* and values.
|
||||
* @private
|
||||
*/
|
||||
goog.net.Cookies.prototype.getKeyValues_ = function() {
|
||||
'use strict';
|
||||
const parts = this.getParts_();
|
||||
const keys = [];
|
||||
const values = [];
|
||||
let index;
|
||||
let part;
|
||||
for (let i = 0; i < parts.length; i++) {
|
||||
part = goog.string.trim(parts[i]);
|
||||
index = part.indexOf('=');
|
||||
|
||||
if (index == -1) { // empty name
|
||||
keys.push('');
|
||||
values.push(part);
|
||||
} else {
|
||||
keys.push(part.substring(0, index));
|
||||
values.push(part.substring(index + 1));
|
||||
}
|
||||
}
|
||||
return {keys: keys, values: values};
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Options object for calls to Cookies.prototype.set.
|
||||
* @record
|
||||
*/
|
||||
goog.net.Cookies.SetOptions = function() {
|
||||
'use strict';
|
||||
/**
|
||||
* The max age in seconds (from now). Use -1 to set a session cookie. If not
|
||||
* provided, the default is -1 (i.e. set a session cookie).
|
||||
* @type {number|undefined}
|
||||
*/
|
||||
this.maxAge;
|
||||
/**
|
||||
* The path of the cookie. If not present then this uses the full request
|
||||
* path.
|
||||
* @type {?string|undefined}
|
||||
*/
|
||||
this.path;
|
||||
/**
|
||||
* The domain of the cookie, or null to not specify a domain attribute
|
||||
* (browser will use the full request host name). If not provided, the default
|
||||
* is null (i.e. let browser use full request host name).
|
||||
* @type {?string|undefined}
|
||||
*/
|
||||
this.domain;
|
||||
/**
|
||||
* Whether the cookie should only be sent over a secure channel.
|
||||
* @type {boolean|undefined}
|
||||
*/
|
||||
this.secure;
|
||||
/**
|
||||
* The SameSite attribute for the cookie (default is NONE).
|
||||
* @type {!goog.net.Cookies.SameSite|undefined}
|
||||
*/
|
||||
this.sameSite;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Valid values for the SameSite cookie attribute. In 2019, browsers began the
|
||||
* process of changing the default from NONE to LAX.
|
||||
*
|
||||
* @see https://web.dev/samesite-cookies-explained
|
||||
* @see https://tools.ietf.org/html/draft-ietf-httpbis-rfc6265bis-03#section-5.3.7
|
||||
* @enum {string}
|
||||
*/
|
||||
goog.net.Cookies.SameSite = {
|
||||
/**
|
||||
* The cookie will be sent in first-party contexts, including initial
|
||||
* navigation from external referrers.
|
||||
*/
|
||||
LAX: 'lax',
|
||||
/**
|
||||
* The cookie will be sent in all first-party or third-party contexts. This
|
||||
* was the original default behavior of the web, but will need to be set
|
||||
* explicitly starting in 2020.
|
||||
*/
|
||||
NONE: 'none',
|
||||
/**
|
||||
* The cookie will only be sent in first-party contexts. It will not be sent
|
||||
* on initial navigation from external referrers.
|
||||
*/
|
||||
STRICT: 'strict',
|
||||
};
|
||||
|
||||
/**
|
||||
* A static default instance.
|
||||
* @const {!goog.net.Cookies}
|
||||
* @private
|
||||
*/
|
||||
goog.net.Cookies.instance_ =
|
||||
new goog.net.Cookies(typeof document == 'undefined' ? null : document);
|
||||
|
||||
/**
|
||||
* Getter for the static instance of goog.net.Cookies.
|
||||
* @return {!goog.net.Cookies}
|
||||
*/
|
||||
goog.net.Cookies.getInstance = function() {
|
||||
'use strict';
|
||||
return goog.net.Cookies.instance_;
|
||||
};
|
||||
Executable
+23
@@ -0,0 +1,23 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright The Closure Library Authors.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @fileoverview A static instance of goog.net.Cookies that uses the default
|
||||
* window document.
|
||||
* @deprecated use `goog.net.Cookies.getInstance()` instead.
|
||||
*/
|
||||
|
||||
goog.provide('goog.net.cookies');
|
||||
|
||||
goog.require('goog.net.Cookies');
|
||||
|
||||
// TODO(closure-team): This should be a singleton getter instead of a static
|
||||
// instance.
|
||||
/**
|
||||
* A static default instance.
|
||||
* @const {!goog.net.Cookies}
|
||||
*/
|
||||
goog.net.cookies = goog.net.Cookies.getInstance();
|
||||
Executable
+123
@@ -0,0 +1,123 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright The Closure Library Authors.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @fileoverview Error codes shared between goog.net.IframeIo and
|
||||
* goog.net.XhrIo.
|
||||
*/
|
||||
|
||||
goog.provide('goog.net.ErrorCode');
|
||||
|
||||
|
||||
/**
|
||||
* Error codes
|
||||
* @enum {number}
|
||||
*/
|
||||
goog.net.ErrorCode = {
|
||||
|
||||
/**
|
||||
* There is no error condition.
|
||||
*/
|
||||
NO_ERROR: 0,
|
||||
|
||||
/**
|
||||
* The most common error from iframeio, unfortunately, is that the browser
|
||||
* responded with an error page that is classed as a different domain. The
|
||||
* situations, are when a browser error page is shown -- 404, access denied,
|
||||
* DNS failure, connection reset etc.)
|
||||
*
|
||||
*/
|
||||
ACCESS_DENIED: 1,
|
||||
|
||||
/**
|
||||
* Currently the only case where file not found will be caused is when the
|
||||
* code is running on the local file system and a non-IE browser makes a
|
||||
* request to a file that doesn't exist.
|
||||
*/
|
||||
FILE_NOT_FOUND: 2,
|
||||
|
||||
/**
|
||||
* If Firefox shows a browser error page, such as a connection reset by
|
||||
* server or access denied, then it will fail silently without the error or
|
||||
* load handlers firing.
|
||||
*/
|
||||
FF_SILENT_ERROR: 3,
|
||||
|
||||
/**
|
||||
* Custom error provided by the client through the error check hook.
|
||||
*/
|
||||
CUSTOM_ERROR: 4,
|
||||
|
||||
/**
|
||||
* Exception was thrown while processing the request.
|
||||
*/
|
||||
EXCEPTION: 5,
|
||||
|
||||
/**
|
||||
* The Http response returned a non-successful http status code.
|
||||
*/
|
||||
HTTP_ERROR: 6,
|
||||
|
||||
/**
|
||||
* The request was aborted.
|
||||
*/
|
||||
ABORT: 7,
|
||||
|
||||
/**
|
||||
* The request timed out.
|
||||
*/
|
||||
TIMEOUT: 8,
|
||||
|
||||
/**
|
||||
* The resource is not available offline.
|
||||
*/
|
||||
OFFLINE: 9,
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns a friendly error message for an error code. These messages are for
|
||||
* debugging and are not localized.
|
||||
* @param {goog.net.ErrorCode} errorCode An error code.
|
||||
* @return {string} A message for debugging.
|
||||
*/
|
||||
goog.net.ErrorCode.getDebugMessage = function(errorCode) {
|
||||
'use strict';
|
||||
switch (errorCode) {
|
||||
case goog.net.ErrorCode.NO_ERROR:
|
||||
return 'No Error';
|
||||
|
||||
case goog.net.ErrorCode.ACCESS_DENIED:
|
||||
return 'Access denied to content document';
|
||||
|
||||
case goog.net.ErrorCode.FILE_NOT_FOUND:
|
||||
return 'File not found';
|
||||
|
||||
case goog.net.ErrorCode.FF_SILENT_ERROR:
|
||||
return 'Firefox silently errored';
|
||||
|
||||
case goog.net.ErrorCode.CUSTOM_ERROR:
|
||||
return 'Application custom error';
|
||||
|
||||
case goog.net.ErrorCode.EXCEPTION:
|
||||
return 'An exception occurred';
|
||||
|
||||
case goog.net.ErrorCode.HTTP_ERROR:
|
||||
return 'Http response at 400 or 500 level';
|
||||
|
||||
case goog.net.ErrorCode.ABORT:
|
||||
return 'Request was aborted';
|
||||
|
||||
case goog.net.ErrorCode.TIMEOUT:
|
||||
return 'Request timed out';
|
||||
|
||||
case goog.net.ErrorCode.OFFLINE:
|
||||
return 'The resource is not available offline';
|
||||
|
||||
default:
|
||||
return 'Unrecognized error code';
|
||||
}
|
||||
};
|
||||
Executable
+34
@@ -0,0 +1,34 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright The Closure Library Authors.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @fileoverview Common events for the network classes.
|
||||
*/
|
||||
|
||||
|
||||
goog.provide('goog.net.EventType');
|
||||
|
||||
|
||||
/**
|
||||
* Event names for network events
|
||||
* @enum {string}
|
||||
*/
|
||||
goog.net.EventType = {
|
||||
COMPLETE: 'complete',
|
||||
SUCCESS: 'success',
|
||||
ERROR: 'error',
|
||||
ABORT: 'abort',
|
||||
READY: 'ready',
|
||||
READY_STATE_CHANGE: 'readystatechange',
|
||||
TIMEOUT: 'timeout',
|
||||
INCREMENTAL_DATA: 'incrementaldata',
|
||||
PROGRESS: 'progress',
|
||||
// DOWNLOAD_PROGRESS and UPLOAD_PROGRESS are special events dispatched by
|
||||
// goog.net.XhrIo to allow binding listeners specific to each type of
|
||||
// progress.
|
||||
DOWNLOAD_PROGRESS: 'downloadprogress',
|
||||
UPLOAD_PROGRESS: 'uploadprogress',
|
||||
};
|
||||
Executable
+118
@@ -0,0 +1,118 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright The Closure Library Authors.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @fileoverview Constants for HTTP status codes.
|
||||
*/
|
||||
|
||||
goog.provide('goog.net.HttpStatus');
|
||||
|
||||
|
||||
/**
|
||||
* HTTP Status Codes defined in RFC 2616, RFC 6585, RFC 4918 and RFC 7538.
|
||||
* @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
|
||||
* @see http://tools.ietf.org/html/rfc6585
|
||||
* @see https://tools.ietf.org/html/rfc4918
|
||||
* @see https://tools.ietf.org/html/rfc7538
|
||||
* @enum {number}
|
||||
*/
|
||||
goog.net.HttpStatus = {
|
||||
// Informational 1xx
|
||||
CONTINUE: 100,
|
||||
SWITCHING_PROTOCOLS: 101,
|
||||
|
||||
// Successful 2xx
|
||||
OK: 200,
|
||||
CREATED: 201,
|
||||
ACCEPTED: 202,
|
||||
NON_AUTHORITATIVE_INFORMATION: 203,
|
||||
NO_CONTENT: 204,
|
||||
RESET_CONTENT: 205,
|
||||
PARTIAL_CONTENT: 206,
|
||||
MULTI_STATUS: 207,
|
||||
|
||||
// Redirection 3xx
|
||||
MULTIPLE_CHOICES: 300,
|
||||
MOVED_PERMANENTLY: 301,
|
||||
FOUND: 302,
|
||||
SEE_OTHER: 303,
|
||||
NOT_MODIFIED: 304,
|
||||
USE_PROXY: 305,
|
||||
TEMPORARY_REDIRECT: 307,
|
||||
PERMANENT_REDIRECT: 308,
|
||||
|
||||
// Client Error 4xx
|
||||
BAD_REQUEST: 400,
|
||||
UNAUTHORIZED: 401,
|
||||
PAYMENT_REQUIRED: 402,
|
||||
FORBIDDEN: 403,
|
||||
NOT_FOUND: 404,
|
||||
METHOD_NOT_ALLOWED: 405,
|
||||
NOT_ACCEPTABLE: 406,
|
||||
PROXY_AUTHENTICATION_REQUIRED: 407,
|
||||
REQUEST_TIMEOUT: 408,
|
||||
CONFLICT: 409,
|
||||
GONE: 410,
|
||||
LENGTH_REQUIRED: 411,
|
||||
PRECONDITION_FAILED: 412,
|
||||
REQUEST_ENTITY_TOO_LARGE: 413,
|
||||
REQUEST_URI_TOO_LONG: 414,
|
||||
UNSUPPORTED_MEDIA_TYPE: 415,
|
||||
REQUEST_RANGE_NOT_SATISFIABLE: 416,
|
||||
EXPECTATION_FAILED: 417,
|
||||
UNPROCESSABLE_ENTITY: 422,
|
||||
LOCKED: 423,
|
||||
FAILED_DEPENDENCY: 424,
|
||||
PRECONDITION_REQUIRED: 428,
|
||||
TOO_MANY_REQUESTS: 429,
|
||||
REQUEST_HEADER_FIELDS_TOO_LARGE: 431,
|
||||
CLIENT_CLOSED_REQUEST: 499, // Nonstandard, used by GRPC
|
||||
|
||||
// Server Error 5xx
|
||||
INTERNAL_SERVER_ERROR: 500,
|
||||
NOT_IMPLEMENTED: 501,
|
||||
BAD_GATEWAY: 502,
|
||||
SERVICE_UNAVAILABLE: 503,
|
||||
GATEWAY_TIMEOUT: 504,
|
||||
HTTP_VERSION_NOT_SUPPORTED: 505,
|
||||
INSUFFICIENT_STORAGE: 507,
|
||||
NETWORK_AUTHENTICATION_REQUIRED: 511,
|
||||
|
||||
/*
|
||||
* IE returns this code for 204 due to its use of URLMon, which returns this
|
||||
* code for 'Operation Aborted'. The status text is 'Unknown', the response
|
||||
* headers are ''. Known to occur on IE 6 on XP through IE9 on Win7.
|
||||
*/
|
||||
QUIRK_IE_NO_CONTENT: 1223,
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns whether the given status should be considered successful.
|
||||
*
|
||||
* Successful codes are OK (200), CREATED (201), ACCEPTED (202),
|
||||
* NO CONTENT (204), PARTIAL CONTENT (206), NOT MODIFIED (304),
|
||||
* and IE's no content code (1223).
|
||||
*
|
||||
* @param {number} status The status code to test.
|
||||
* @return {boolean} Whether the status code should be considered successful.
|
||||
*/
|
||||
goog.net.HttpStatus.isSuccess = function(status) {
|
||||
'use strict';
|
||||
switch (status) {
|
||||
case goog.net.HttpStatus.OK:
|
||||
case goog.net.HttpStatus.CREATED:
|
||||
case goog.net.HttpStatus.ACCEPTED:
|
||||
case goog.net.HttpStatus.NO_CONTENT:
|
||||
case goog.net.HttpStatus.PARTIAL_CONTENT:
|
||||
case goog.net.HttpStatus.NOT_MODIFIED:
|
||||
case goog.net.HttpStatus.QUIRK_IE_NO_CONTENT:
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
};
|
||||
Executable
+64
@@ -0,0 +1,64 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright The Closure Library Authors.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @fileoverview Implementation of XmlHttpFactory which allows construction from
|
||||
* simple factory methods.
|
||||
*/
|
||||
|
||||
goog.provide('goog.net.WrapperXmlHttpFactory');
|
||||
|
||||
/** @suppress {extraRequire} Typedef. */
|
||||
goog.require('goog.net.XhrLike');
|
||||
goog.require('goog.net.XmlHttpFactory');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* An xhr factory subclass which can be constructed using two factory methods.
|
||||
* This exists partly to allow the preservation of goog.net.XmlHttp.setFactory()
|
||||
* with an unchanged signature.
|
||||
* @param {function():!goog.net.XhrLike.OrNative} xhrFactory
|
||||
* A function which returns a new XHR object.
|
||||
* @param {function():!Object} optionsFactory A function which returns the
|
||||
* options associated with xhr objects from this factory.
|
||||
* @extends {goog.net.XmlHttpFactory}
|
||||
* @constructor
|
||||
* @final
|
||||
*/
|
||||
goog.net.WrapperXmlHttpFactory = function(xhrFactory, optionsFactory) {
|
||||
'use strict';
|
||||
goog.net.XmlHttpFactory.call(this);
|
||||
|
||||
/**
|
||||
* XHR factory method.
|
||||
* @type {function() : !goog.net.XhrLike.OrNative}
|
||||
* @private
|
||||
*/
|
||||
this.xhrFactory_ = xhrFactory;
|
||||
|
||||
/**
|
||||
* Options factory method.
|
||||
* @type {function() : !Object}
|
||||
* @private
|
||||
*/
|
||||
this.optionsFactory_ = optionsFactory;
|
||||
};
|
||||
goog.inherits(goog.net.WrapperXmlHttpFactory, goog.net.XmlHttpFactory);
|
||||
|
||||
|
||||
/** @override */
|
||||
goog.net.WrapperXmlHttpFactory.prototype.createInstance = function() {
|
||||
'use strict';
|
||||
return this.xhrFactory_();
|
||||
};
|
||||
|
||||
|
||||
/** @override */
|
||||
goog.net.WrapperXmlHttpFactory.prototype.getOptions = function() {
|
||||
'use strict';
|
||||
return this.optionsFactory_();
|
||||
};
|
||||
Executable
+1461
File diff suppressed because it is too large
Load Diff
Executable
+97
@@ -0,0 +1,97 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright The Closure Library Authors.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @fileoverview Creates a pool of XhrIo objects to use. This allows multiple
|
||||
* XhrIo objects to be grouped together and requests will use next available
|
||||
* XhrIo object.
|
||||
*/
|
||||
|
||||
goog.provide('goog.net.XhrIoPool');
|
||||
|
||||
goog.require('goog.net.XhrIo');
|
||||
goog.require('goog.structs.PriorityPool');
|
||||
goog.requireType('goog.structs.Map');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* A pool of XhrIo objects.
|
||||
* @param {goog.structs.Map=} opt_headers Map of default headers to add to every
|
||||
* request.
|
||||
* @param {number=} opt_minCount Minimum number of objects (Default: 0).
|
||||
* @param {number=} opt_maxCount Maximum number of objects (Default: 10).
|
||||
* @param {boolean=} opt_withCredentials Add credentials to every request
|
||||
* (Default: false).
|
||||
* @constructor
|
||||
* @extends {goog.structs.PriorityPool}
|
||||
*/
|
||||
goog.net.XhrIoPool = function(
|
||||
opt_headers, opt_minCount, opt_maxCount, opt_withCredentials) {
|
||||
'use strict';
|
||||
/**
|
||||
* Map of default headers to add to every request.
|
||||
* @type {goog.structs.Map|undefined}
|
||||
* @private
|
||||
*/
|
||||
this.headers_ = opt_headers;
|
||||
|
||||
/**
|
||||
* Whether a "credentialed" requests are to be sent (ones that is aware of
|
||||
* cookies and authentication). This is applicable only for cross-domain
|
||||
* requests and more recent browsers that support this part of the HTTP Access
|
||||
* Control standard.
|
||||
*
|
||||
* @see http://www.w3.org/TR/XMLHttpRequest/#the-withcredentials-attribute
|
||||
*
|
||||
* @private {boolean}
|
||||
*/
|
||||
this.withCredentials_ = !!opt_withCredentials;
|
||||
|
||||
// Must break convention of putting the super-class's constructor first. This
|
||||
// is because the super-class constructor calls adjustForMinMax, which calls
|
||||
// this class' createObject. In this class's implementation, it assumes that
|
||||
// there is a headers_, and will lack those if not yet present.
|
||||
goog.structs.PriorityPool.call(this, opt_minCount, opt_maxCount);
|
||||
};
|
||||
goog.inherits(goog.net.XhrIoPool, goog.structs.PriorityPool);
|
||||
|
||||
|
||||
/**
|
||||
* Creates an instance of an XhrIo object to use in the pool.
|
||||
* @return {!goog.net.XhrIo} The created object.
|
||||
* @override
|
||||
*/
|
||||
goog.net.XhrIoPool.prototype.createObject = function() {
|
||||
'use strict';
|
||||
const xhrIo = new goog.net.XhrIo();
|
||||
const headers = this.headers_;
|
||||
if (headers) {
|
||||
headers.forEach(function(value, key) {
|
||||
'use strict';
|
||||
xhrIo.headers.set(key, value);
|
||||
});
|
||||
}
|
||||
if (this.withCredentials_) {
|
||||
xhrIo.setWithCredentials(true);
|
||||
}
|
||||
return xhrIo;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Determine if an object has become unusable and should not be used.
|
||||
* @param {Object} obj The object to test.
|
||||
* @return {boolean} Whether the object can be reused, which is true if the
|
||||
* object is not disposed and not active.
|
||||
* @override
|
||||
*/
|
||||
goog.net.XhrIoPool.prototype.objectCanBeReused = function(obj) {
|
||||
'use strict';
|
||||
// An active XhrIo object should never be used.
|
||||
const xhr = /** @type {goog.net.XhrIo} */ (obj);
|
||||
return !xhr.isDisposed() && !xhr.isActive();
|
||||
};
|
||||
Executable
+136
@@ -0,0 +1,136 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright The Closure Library Authors.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
goog.provide('goog.net.XhrLike');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Interface for the common parts of XMLHttpRequest.
|
||||
*
|
||||
* Mostly copied from externs/w3c_xml.js.
|
||||
*
|
||||
* @interface
|
||||
* @see http://www.w3.org/TR/XMLHttpRequest/
|
||||
*/
|
||||
goog.net.XhrLike = function() {};
|
||||
|
||||
|
||||
/**
|
||||
* Typedef that refers to either native or custom-implemented XHR objects.
|
||||
* @typedef {!goog.net.XhrLike|!XMLHttpRequest}
|
||||
*/
|
||||
goog.net.XhrLike.OrNative;
|
||||
|
||||
|
||||
/**
|
||||
* @type {function()|null|undefined}
|
||||
* @see http://www.w3.org/TR/XMLHttpRequest/#handler-xhr-onreadystatechange
|
||||
*/
|
||||
goog.net.XhrLike.prototype.onreadystatechange;
|
||||
|
||||
|
||||
/**
|
||||
* @type {?ArrayBuffer|?Blob|?Document|?Object|?string}
|
||||
* @see https://xhr.spec.whatwg.org/#response-object
|
||||
*/
|
||||
goog.net.XhrLike.prototype.response;
|
||||
|
||||
|
||||
/**
|
||||
* @type {string}
|
||||
* @see http://www.w3.org/TR/XMLHttpRequest/#the-responsetext-attribute
|
||||
*/
|
||||
goog.net.XhrLike.prototype.responseText;
|
||||
|
||||
|
||||
/**
|
||||
* @type {string}
|
||||
* @see https://xhr.spec.whatwg.org/#the-responsetype-attribute
|
||||
*/
|
||||
goog.net.XhrLike.prototype.responseType;
|
||||
|
||||
|
||||
/**
|
||||
* @type {Document}
|
||||
* @see http://www.w3.org/TR/XMLHttpRequest/#the-responsexml-attribute
|
||||
*/
|
||||
goog.net.XhrLike.prototype.responseXML;
|
||||
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
* @see http://www.w3.org/TR/XMLHttpRequest/#readystate
|
||||
*/
|
||||
goog.net.XhrLike.prototype.readyState;
|
||||
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
* @see http://www.w3.org/TR/XMLHttpRequest/#status
|
||||
*/
|
||||
goog.net.XhrLike.prototype.status;
|
||||
|
||||
|
||||
/**
|
||||
* @type {string}
|
||||
* @see http://www.w3.org/TR/XMLHttpRequest/#statustext
|
||||
*/
|
||||
goog.net.XhrLike.prototype.statusText;
|
||||
|
||||
|
||||
/**
|
||||
* @param {string} method
|
||||
* @param {string} url
|
||||
* @param {?boolean=} opt_async
|
||||
* @param {?string=} opt_user
|
||||
* @param {?string=} opt_password
|
||||
* @see http://www.w3.org/TR/XMLHttpRequest/#the-open()-method
|
||||
*/
|
||||
goog.net.XhrLike.prototype.open = function(
|
||||
method, url, opt_async, opt_user, opt_password) {};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ArrayBuffer|ArrayBufferView|Blob|Document|FormData|string=} opt_data
|
||||
* @see http://www.w3.org/TR/XMLHttpRequest/#the-send()-method
|
||||
*/
|
||||
goog.net.XhrLike.prototype.send = function(opt_data) {};
|
||||
|
||||
|
||||
/**
|
||||
* @see http://www.w3.org/TR/XMLHttpRequest/#the-abort()-method
|
||||
*/
|
||||
goog.net.XhrLike.prototype.abort = function() {};
|
||||
|
||||
|
||||
/**
|
||||
* @param {string} header
|
||||
* @param {string} value
|
||||
* @see http://www.w3.org/TR/XMLHttpRequest/#the-setrequestheader()-method
|
||||
*/
|
||||
goog.net.XhrLike.prototype.setRequestHeader = function(header, value) {};
|
||||
|
||||
|
||||
/**
|
||||
* @param {string} header
|
||||
* @return {?string}
|
||||
* @see http://www.w3.org/TR/XMLHttpRequest/#the-getresponseheader()-method
|
||||
*/
|
||||
goog.net.XhrLike.prototype.getResponseHeader = function(header) {};
|
||||
|
||||
|
||||
/**
|
||||
* @return {string}
|
||||
* @see http://www.w3.org/TR/XMLHttpRequest/#the-getallresponseheaders()-method
|
||||
*/
|
||||
goog.net.XhrLike.prototype.getAllResponseHeaders = function() {};
|
||||
|
||||
/**
|
||||
* @type {?function(!TrustTokenAttributeType): void | undefined}
|
||||
* @see https://docs.google.com/document/d/1qUjtKgA7nMv9YGMhi0xWKEojkSITKzGLdIcZgoz6ZkI.
|
||||
*/
|
||||
goog.net.XhrLike.prototype.setTrustToken = function(trustTokenAttribute) {};
|
||||
Executable
+818
@@ -0,0 +1,818 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright The Closure Library Authors.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @fileoverview Manages a pool of XhrIo's. This handles all the details of
|
||||
* dealing with the XhrPool and provides a simple interface for sending requests
|
||||
* and managing events.
|
||||
*
|
||||
* This class supports queueing & prioritization of requests (XhrIoPool
|
||||
* handles this) and retrying of requests.
|
||||
*
|
||||
* The events fired by the XhrManager are an aggregation of the events of
|
||||
* each of its XhrIo objects (with some filtering, i.e., ERROR only called
|
||||
* when there are no more retries left). For this reason, all send requests have
|
||||
* to have an id, so that the user of this object can know which event is for
|
||||
* which request.
|
||||
*/
|
||||
|
||||
goog.provide('goog.net.XhrManager');
|
||||
goog.provide('goog.net.XhrManager.Event');
|
||||
goog.provide('goog.net.XhrManager.Request');
|
||||
|
||||
goog.require('goog.events');
|
||||
goog.require('goog.events.Event');
|
||||
goog.require('goog.events.EventHandler');
|
||||
goog.require('goog.events.EventTarget');
|
||||
goog.require('goog.net.ErrorCode');
|
||||
goog.require('goog.net.EventType');
|
||||
goog.require('goog.net.XhrIo');
|
||||
goog.require('goog.net.XhrIoPool');
|
||||
goog.require('goog.structs.Map');
|
||||
|
||||
// TODO(user): Add some time in between retries.
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* A manager of an XhrIoPool.
|
||||
* @param {number=} opt_maxRetries Max. number of retries (Default: 1).
|
||||
* @param {goog.structs.Map=} opt_headers Map of default headers to add to every
|
||||
* request.
|
||||
* @param {number=} opt_minCount Min. number of objects (Default: 0).
|
||||
* @param {number=} opt_maxCount Max. number of objects (Default: 10).
|
||||
* @param {number=} opt_timeoutInterval Timeout (in ms) before aborting an
|
||||
* attempt (Default: 0ms).
|
||||
* @param {boolean=} opt_withCredentials Add credentials to every request
|
||||
* (Default: false).
|
||||
* @constructor
|
||||
* @extends {goog.events.EventTarget}
|
||||
*/
|
||||
goog.net.XhrManager = function(
|
||||
opt_maxRetries, opt_headers, opt_minCount, opt_maxCount,
|
||||
opt_timeoutInterval, opt_withCredentials) {
|
||||
'use strict';
|
||||
goog.net.XhrManager.base(this, 'constructor');
|
||||
|
||||
/**
|
||||
* Maximum number of retries for a given request
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
this.maxRetries_ = (opt_maxRetries !== undefined) ? opt_maxRetries : 1;
|
||||
|
||||
/**
|
||||
* Timeout interval for an attempt of a given request.
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
this.timeoutInterval_ = (opt_timeoutInterval !== undefined) ?
|
||||
Math.max(0, opt_timeoutInterval) :
|
||||
0;
|
||||
|
||||
/**
|
||||
* Add credentials to every request.
|
||||
* @private {boolean}
|
||||
*/
|
||||
this.withCredentials_ = !!opt_withCredentials;
|
||||
|
||||
/**
|
||||
* The pool of XhrIo's to use.
|
||||
* @type {goog.net.XhrIoPool}
|
||||
* @private
|
||||
*/
|
||||
this.xhrPool_ = new goog.net.XhrIoPool(
|
||||
opt_headers, opt_minCount, opt_maxCount, opt_withCredentials);
|
||||
|
||||
/**
|
||||
* Map of ID's to requests.
|
||||
* @type {goog.structs.Map<string, !goog.net.XhrManager.Request>}
|
||||
* @private
|
||||
*/
|
||||
this.requests_ = new goog.structs.Map();
|
||||
|
||||
/**
|
||||
* The event handler.
|
||||
* @type {goog.events.EventHandler<!goog.net.XhrManager>}
|
||||
* @private
|
||||
*/
|
||||
this.eventHandler_ = new goog.events.EventHandler(this);
|
||||
};
|
||||
goog.inherits(goog.net.XhrManager, goog.events.EventTarget);
|
||||
|
||||
|
||||
/**
|
||||
* Error to throw when a send is attempted with an ID that the manager already
|
||||
* has registered for another request.
|
||||
* @type {string}
|
||||
* @private
|
||||
*/
|
||||
goog.net.XhrManager.ERROR_ID_IN_USE_ = '[goog.net.XhrManager] ID in use';
|
||||
|
||||
|
||||
/**
|
||||
* The goog.net.EventType's to listen/unlisten for on the XhrIo object.
|
||||
* @type {Array<goog.net.EventType>}
|
||||
* @private
|
||||
*/
|
||||
goog.net.XhrManager.XHR_EVENT_TYPES_ = [
|
||||
goog.net.EventType.READY,
|
||||
goog.net.EventType.COMPLETE,
|
||||
goog.net.EventType.SUCCESS,
|
||||
goog.net.EventType.ERROR,
|
||||
goog.net.EventType.ABORT,
|
||||
goog.net.EventType.TIMEOUT,
|
||||
];
|
||||
|
||||
|
||||
/**
|
||||
* Sets the number of milliseconds after which an incomplete request will be
|
||||
* aborted. Zero means no timeout is set.
|
||||
* @param {number} ms Timeout interval in milliseconds; 0 means none.
|
||||
*/
|
||||
goog.net.XhrManager.prototype.setTimeoutInterval = function(ms) {
|
||||
'use strict';
|
||||
this.timeoutInterval_ = Math.max(0, ms);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the number of requests either in flight, or waiting to be sent.
|
||||
* The count will include the current request if used within a COMPLETE event
|
||||
* handler or callback.
|
||||
* @return {number} The number of requests in flight or pending send.
|
||||
*/
|
||||
goog.net.XhrManager.prototype.getOutstandingCount = function() {
|
||||
'use strict';
|
||||
return this.requests_.getCount();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns an array of request ids that are either in flight, or waiting to
|
||||
* be sent. The id of the current request will be included if used within a
|
||||
* COMPLETE event handler or callback.
|
||||
* @return {!Array<string>} Request ids in flight or pending send.
|
||||
*/
|
||||
goog.net.XhrManager.prototype.getOutstandingRequestIds = function() {
|
||||
'use strict';
|
||||
return this.requests_.getKeys();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Registers the given request to be sent. Throws an error if a request
|
||||
* already exists with the given ID.
|
||||
* NOTE: It is not sent immediately. It is buffered and will be sent when an
|
||||
* XhrIo object becomes available, taking into account the request's
|
||||
* priority. Note also that requests of equal priority are sent in an
|
||||
* implementation specific order - to get FIFO queue semantics use a
|
||||
* monotonically increasing priority for successive requests.
|
||||
* @param {string} id The id of the request.
|
||||
* @param {string} url Uri to make the request to.
|
||||
* @param {string=} opt_method Send method, default: GET.
|
||||
* @param {ArrayBuffer|ArrayBufferView|Blob|Document|FormData|string=}
|
||||
* opt_content Post data.
|
||||
* @param {Object|goog.structs.Map=} opt_headers Map of headers to add to the
|
||||
* request.
|
||||
* @param {number=} opt_priority The priority of the request. A smaller value
|
||||
* means a higher priority.
|
||||
* @param {Function=} opt_callback Callback function for when request is
|
||||
* complete. The only param is the event object from the COMPLETE event.
|
||||
* @param {number=} opt_maxRetries The maximum number of times the request
|
||||
* should be retried.
|
||||
* @param {goog.net.XhrIo.ResponseType=} opt_responseType The response type of
|
||||
* this request; defaults to goog.net.XhrIo.ResponseType.DEFAULT.
|
||||
* @param {boolean=} opt_withCredentials Add credentials to this request,
|
||||
* default: false.
|
||||
* @return {!goog.net.XhrManager.Request} The queued request object.
|
||||
*/
|
||||
goog.net.XhrManager.prototype.send = function(
|
||||
id, url, opt_method, opt_content, opt_headers, opt_priority, opt_callback,
|
||||
opt_maxRetries, opt_responseType, opt_withCredentials) {
|
||||
'use strict';
|
||||
const requests = this.requests_;
|
||||
// Check if there is already a request with the given id.
|
||||
if (requests.get(id)) {
|
||||
throw new Error(goog.net.XhrManager.ERROR_ID_IN_USE_);
|
||||
}
|
||||
|
||||
// Make the Request object.
|
||||
const request = new goog.net.XhrManager.Request(
|
||||
url, goog.bind(this.handleEvent_, this, id), opt_method, opt_content,
|
||||
opt_headers, opt_callback,
|
||||
opt_maxRetries !== undefined ? opt_maxRetries : this.maxRetries_,
|
||||
opt_responseType,
|
||||
opt_withCredentials !== undefined ? opt_withCredentials :
|
||||
this.withCredentials_);
|
||||
this.requests_.set(id, request);
|
||||
|
||||
// Setup the callback for the pool.
|
||||
const callback = goog.bind(this.handleAvailableXhr_, this, id);
|
||||
this.xhrPool_.getObject(callback, opt_priority);
|
||||
|
||||
return request;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Aborts the request associated with id.
|
||||
* @param {string} id The id of the request to abort.
|
||||
* @param {boolean=} opt_force If true, remove the id now so it can be reused.
|
||||
* No events are fired and the callback is not called when forced.
|
||||
*/
|
||||
goog.net.XhrManager.prototype.abort = function(id, opt_force) {
|
||||
'use strict';
|
||||
const request = this.requests_.get(id);
|
||||
if (request) {
|
||||
const xhrIo = request.xhrIo;
|
||||
request.setAborted(true);
|
||||
if (opt_force) {
|
||||
if (xhrIo) {
|
||||
// We remove listeners to make sure nothing gets called if a new request
|
||||
// with the same id is made.
|
||||
this.removeXhrListener_(xhrIo, request.getXhrEventCallback());
|
||||
goog.events.listenOnce(xhrIo, goog.net.EventType.READY, function() {
|
||||
'use strict';
|
||||
this.xhrPool_.releaseObject(xhrIo);
|
||||
}, false, this);
|
||||
}
|
||||
this.requests_.remove(id);
|
||||
}
|
||||
if (xhrIo) {
|
||||
xhrIo.abort();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handles when an XhrIo object becomes available. Sets up the events, fires
|
||||
* the READY event, and starts the process to send the request.
|
||||
* @param {string} id The id of the request the XhrIo is for.
|
||||
* @param {goog.net.XhrIo} xhrIo The available XhrIo object.
|
||||
* @private
|
||||
*/
|
||||
goog.net.XhrManager.prototype.handleAvailableXhr_ = function(id, xhrIo) {
|
||||
'use strict';
|
||||
const request = this.requests_.get(id);
|
||||
// Make sure the request doesn't already have an XhrIo attached. This can
|
||||
// happen if a forced abort occurs before an XhrIo is available, and a new
|
||||
// request with the same id is made.
|
||||
if (request && !request.xhrIo) {
|
||||
this.addXhrListener_(xhrIo, request.getXhrEventCallback());
|
||||
|
||||
// Set properties for the XhrIo.
|
||||
xhrIo.setTimeoutInterval(this.timeoutInterval_);
|
||||
xhrIo.setResponseType(request.getResponseType());
|
||||
xhrIo.setWithCredentials(request.getWithCredentials());
|
||||
|
||||
// Add a reference to the XhrIo object to the request.
|
||||
request.xhrIo = xhrIo;
|
||||
|
||||
// Notify the listeners.
|
||||
this.dispatchEvent(
|
||||
new goog.net.XhrManager.Event(
|
||||
goog.net.EventType.READY, this, id, xhrIo));
|
||||
|
||||
// Send the request.
|
||||
this.retry_(id, xhrIo);
|
||||
|
||||
// If the request was aborted before it got an XhrIo object, abort it now.
|
||||
if (request.getAborted()) {
|
||||
xhrIo.abort();
|
||||
}
|
||||
} else {
|
||||
// If the request has an XhrIo object already, or no request exists, just
|
||||
// return the XhrIo back to the pool.
|
||||
this.xhrPool_.releaseObject(xhrIo);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handles all events fired by the XhrIo object for a given request.
|
||||
* @param {string} id The id of the request.
|
||||
* @param {goog.events.Event} e The event.
|
||||
* @return {Object} The return value from the handler, if any.
|
||||
* @private
|
||||
*/
|
||||
goog.net.XhrManager.prototype.handleEvent_ = function(id, e) {
|
||||
'use strict';
|
||||
const xhrIo = /** @type {goog.net.XhrIo} */ (e.target);
|
||||
switch (e.type) {
|
||||
case goog.net.EventType.READY:
|
||||
this.retry_(id, xhrIo);
|
||||
break;
|
||||
|
||||
case goog.net.EventType.COMPLETE:
|
||||
return this.handleComplete_(id, xhrIo, e);
|
||||
|
||||
case goog.net.EventType.SUCCESS:
|
||||
this.handleSuccess_(id, xhrIo);
|
||||
break;
|
||||
|
||||
// A timeout is handled like an error.
|
||||
case goog.net.EventType.TIMEOUT:
|
||||
case goog.net.EventType.ERROR:
|
||||
this.handleError_(id, xhrIo);
|
||||
break;
|
||||
|
||||
case goog.net.EventType.ABORT:
|
||||
this.handleAbort_(id, xhrIo);
|
||||
break;
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Attempts to retry the given request. If the request has already attempted
|
||||
* the maximum number of retries, then it removes the request and releases
|
||||
* the XhrIo object back into the pool.
|
||||
* @param {string} id The id of the request.
|
||||
* @param {goog.net.XhrIo} xhrIo The XhrIo object.
|
||||
* @private
|
||||
*/
|
||||
goog.net.XhrManager.prototype.retry_ = function(id, xhrIo) {
|
||||
'use strict';
|
||||
const request = this.requests_.get(id);
|
||||
|
||||
// If the request has not completed and it is below its max. retries.
|
||||
if (request && !request.getCompleted() && !request.hasReachedMaxRetries()) {
|
||||
request.increaseAttemptCount();
|
||||
xhrIo.send(
|
||||
request.getUrl(), request.getMethod(), request.getContent(),
|
||||
request.getHeaders());
|
||||
} else {
|
||||
if (request) {
|
||||
// Remove the events on the XhrIo objects.
|
||||
this.removeXhrListener_(xhrIo, request.getXhrEventCallback());
|
||||
|
||||
// Remove the request.
|
||||
this.requests_.remove(id);
|
||||
}
|
||||
// Release the XhrIo object back into the pool.
|
||||
this.xhrPool_.releaseObject(xhrIo);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handles the complete of a request. Dispatches the COMPLETE event and sets the
|
||||
* the request as completed if the request has succeeded, or is done retrying.
|
||||
* @param {string} id The id of the request.
|
||||
* @param {goog.net.XhrIo} xhrIo The XhrIo object.
|
||||
* @param {goog.events.Event} e The original event.
|
||||
* @return {Object} The return value from the callback, if any.
|
||||
* @private
|
||||
*/
|
||||
goog.net.XhrManager.prototype.handleComplete_ = function(id, xhrIo, e) {
|
||||
'use strict';
|
||||
// Only if the request is done processing should a COMPLETE event be fired.
|
||||
const request = this.requests_.get(id);
|
||||
if (xhrIo.getLastErrorCode() == goog.net.ErrorCode.ABORT ||
|
||||
xhrIo.isSuccess() || request.hasReachedMaxRetries()) {
|
||||
this.dispatchEvent(
|
||||
new goog.net.XhrManager.Event(
|
||||
goog.net.EventType.COMPLETE, this, id, xhrIo));
|
||||
|
||||
// If the request exists, we mark it as completed and call the callback
|
||||
if (request) {
|
||||
request.setCompleted(true);
|
||||
// Call the complete callback as if it was set as a COMPLETE event on the
|
||||
// XhrIo directly.
|
||||
if (request.getCompleteCallback()) {
|
||||
return request.getCompleteCallback().call(xhrIo, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handles the abort of an underlying XhrIo object.
|
||||
* @param {string} id The id of the request.
|
||||
* @param {goog.net.XhrIo} xhrIo The XhrIo object.
|
||||
* @private
|
||||
*/
|
||||
goog.net.XhrManager.prototype.handleAbort_ = function(id, xhrIo) {
|
||||
'use strict';
|
||||
// Fire event.
|
||||
// NOTE: The complete event should always be fired before the abort event, so
|
||||
// the bulk of the work is done in handleComplete.
|
||||
this.dispatchEvent(
|
||||
new goog.net.XhrManager.Event(goog.net.EventType.ABORT, this, id, xhrIo));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handles the success of a request. Dispatches the SUCCESS event and sets the
|
||||
* the request as completed.
|
||||
* @param {string} id The id of the request.
|
||||
* @param {goog.net.XhrIo} xhrIo The XhrIo object.
|
||||
* @private
|
||||
*/
|
||||
goog.net.XhrManager.prototype.handleSuccess_ = function(id, xhrIo) {
|
||||
'use strict';
|
||||
// Fire event.
|
||||
// NOTE: We don't release the XhrIo object from the pool here.
|
||||
// It is released in the retry method, when we know it is back in the
|
||||
// ready state.
|
||||
this.dispatchEvent(
|
||||
new goog.net.XhrManager.Event(
|
||||
goog.net.EventType.SUCCESS, this, id, xhrIo));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handles the error of a request. If the request has not reach its maximum
|
||||
* number of retries, then it lets the request retry naturally (will let the
|
||||
* request hit the READY state). Else, it dispatches the ERROR event.
|
||||
* @param {string} id The id of the request.
|
||||
* @param {goog.net.XhrIo} xhrIo The XhrIo object.
|
||||
* @private
|
||||
*/
|
||||
goog.net.XhrManager.prototype.handleError_ = function(id, xhrIo) {
|
||||
'use strict';
|
||||
const request = this.requests_.get(id);
|
||||
|
||||
// If the maximum number of retries has been reached.
|
||||
if (request.hasReachedMaxRetries()) {
|
||||
// Fire event.
|
||||
// NOTE: We don't release the XhrIo object from the pool here.
|
||||
// It is released in the retry method, when we know it is back in the
|
||||
// ready state.
|
||||
this.dispatchEvent(
|
||||
new goog.net.XhrManager.Event(
|
||||
goog.net.EventType.ERROR, this, id, xhrIo));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Remove listeners for XHR events on an XhrIo object.
|
||||
* @param {goog.net.XhrIo} xhrIo The object to stop listenening to events on.
|
||||
* @param {Function} func The callback to remove from event handling.
|
||||
* @param {string|Array<string>=} opt_types Event types to remove listeners
|
||||
* for. Defaults to XHR_EVENT_TYPES_.
|
||||
* @private
|
||||
*/
|
||||
goog.net.XhrManager.prototype.removeXhrListener_ = function(
|
||||
xhrIo, func, opt_types) {
|
||||
'use strict';
|
||||
const types = opt_types || goog.net.XhrManager.XHR_EVENT_TYPES_;
|
||||
this.eventHandler_.unlisten(xhrIo, types, func);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Adds a listener for XHR events on an XhrIo object.
|
||||
* @param {goog.net.XhrIo} xhrIo The object listen to events on.
|
||||
* @param {Function} func The callback when the event occurs.
|
||||
* @param {string|Array<string>=} opt_types Event types to attach listeners to.
|
||||
* Defaults to XHR_EVENT_TYPES_.
|
||||
* @private
|
||||
*/
|
||||
goog.net.XhrManager.prototype.addXhrListener_ = function(
|
||||
xhrIo, func, opt_types) {
|
||||
'use strict';
|
||||
const types = opt_types || goog.net.XhrManager.XHR_EVENT_TYPES_;
|
||||
this.eventHandler_.listen(xhrIo, types, func);
|
||||
};
|
||||
|
||||
|
||||
/** @override */
|
||||
goog.net.XhrManager.prototype.disposeInternal = function() {
|
||||
'use strict';
|
||||
goog.net.XhrManager.superClass_.disposeInternal.call(this);
|
||||
|
||||
this.xhrPool_.dispose();
|
||||
this.xhrPool_ = null;
|
||||
|
||||
this.eventHandler_.dispose();
|
||||
this.eventHandler_ = null;
|
||||
|
||||
this.requests_.clear();
|
||||
this.requests_ = null;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* An event dispatched by XhrManager.
|
||||
*
|
||||
* @param {goog.net.EventType} type Event Type.
|
||||
* @param {goog.net.XhrManager} target Reference to the object that is the
|
||||
* target of this event.
|
||||
* @param {string} id The id of the request this event is for.
|
||||
* @param {goog.net.XhrIo} xhrIo The XhrIo object of the request.
|
||||
* @constructor
|
||||
* @extends {goog.events.Event}
|
||||
* @final
|
||||
*/
|
||||
goog.net.XhrManager.Event = function(type, target, id, xhrIo) {
|
||||
'use strict';
|
||||
goog.events.Event.call(this, type, target);
|
||||
|
||||
/**
|
||||
* The id of the request this event is for.
|
||||
* @type {string}
|
||||
*/
|
||||
this.id = id;
|
||||
|
||||
/**
|
||||
* The XhrIo object of the request.
|
||||
* @type {goog.net.XhrIo}
|
||||
*/
|
||||
this.xhrIo = xhrIo;
|
||||
};
|
||||
goog.inherits(goog.net.XhrManager.Event, goog.events.Event);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* An encapsulation of everything needed to make a Xhr request.
|
||||
* NOTE: This is used internal to the XhrManager.
|
||||
*
|
||||
* @param {string} url Uri to make the request too.
|
||||
* @param {Function} xhrEventCallback Callback attached to the events of the
|
||||
* XhrIo object of the request.
|
||||
* @param {string=} opt_method Send method, default: GET.
|
||||
* @param {ArrayBuffer|ArrayBufferView|Blob|Document|FormData|string=}
|
||||
* opt_content Post data.
|
||||
* @param {Object|goog.structs.Map=} opt_headers Map of headers to add to the
|
||||
* request.
|
||||
* @param {Function=} opt_callback Callback function for when request is
|
||||
* complete. NOTE: Only 1 callback supported across all events.
|
||||
* @param {number=} opt_maxRetries The maximum number of times the request
|
||||
* should be retried (Default: 1).
|
||||
* @param {goog.net.XhrIo.ResponseType=} opt_responseType The response type of
|
||||
* this request; defaults to goog.net.XhrIo.ResponseType.DEFAULT.
|
||||
* @param {boolean=} opt_withCredentials Add credentials to this request,
|
||||
* default: false.
|
||||
*
|
||||
* @constructor
|
||||
* @final
|
||||
*/
|
||||
goog.net.XhrManager.Request = function(
|
||||
url, xhrEventCallback, opt_method, opt_content, opt_headers, opt_callback,
|
||||
opt_maxRetries, opt_responseType, opt_withCredentials) {
|
||||
'use strict';
|
||||
/**
|
||||
* Uri to make the request too.
|
||||
* @type {string}
|
||||
* @private
|
||||
*/
|
||||
this.url_ = url;
|
||||
|
||||
/**
|
||||
* Send method.
|
||||
* @type {string}
|
||||
* @private
|
||||
*/
|
||||
this.method_ = opt_method || 'GET';
|
||||
|
||||
/**
|
||||
* Post data.
|
||||
* @type {ArrayBuffer|ArrayBufferView|Blob|Document|FormData|string|undefined}
|
||||
* @private
|
||||
*/
|
||||
this.content_ = opt_content;
|
||||
|
||||
/**
|
||||
* Map of headers
|
||||
* @type {Object|goog.structs.Map|null}
|
||||
* @private
|
||||
*/
|
||||
this.headers_ = opt_headers || null;
|
||||
|
||||
/**
|
||||
* The maximum number of times the request should be retried.
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
this.maxRetries_ = (opt_maxRetries !== undefined) ? opt_maxRetries : 1;
|
||||
|
||||
/**
|
||||
* The number of attempts so far.
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
this.attemptCount_ = 0;
|
||||
|
||||
/**
|
||||
* Whether the request has been completed.
|
||||
* @type {boolean}
|
||||
* @private
|
||||
*/
|
||||
this.completed_ = false;
|
||||
|
||||
/**
|
||||
* Whether the request has been aborted.
|
||||
* @type {boolean}
|
||||
* @private
|
||||
*/
|
||||
this.aborted_ = false;
|
||||
|
||||
/**
|
||||
* Callback attached to the events of the XhrIo object.
|
||||
* @type {Function}
|
||||
* @private
|
||||
*/
|
||||
this.xhrEventCallback_ = xhrEventCallback;
|
||||
|
||||
/**
|
||||
* Callback function called when request is complete.
|
||||
* @type {Function|undefined}
|
||||
* @private
|
||||
*/
|
||||
this.completeCallback_ = opt_callback;
|
||||
|
||||
/**
|
||||
* A response type to set on this.xhrIo when it's populated.
|
||||
* @type {!goog.net.XhrIo.ResponseType}
|
||||
* @private
|
||||
*/
|
||||
this.responseType_ = opt_responseType || goog.net.XhrIo.ResponseType.DEFAULT;
|
||||
|
||||
/**
|
||||
* Send credentials with this request, or not.
|
||||
* @private {boolean}
|
||||
*/
|
||||
this.withCredentials_ = !!opt_withCredentials;
|
||||
|
||||
/**
|
||||
* The XhrIo instance handling this request. Set in handleAvailableXhr.
|
||||
* @type {?goog.net.XhrIo}
|
||||
*/
|
||||
this.xhrIo = null;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Gets the uri.
|
||||
* @return {string} The uri to make the request to.
|
||||
*/
|
||||
goog.net.XhrManager.Request.prototype.getUrl = function() {
|
||||
'use strict';
|
||||
return this.url_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Gets the send method.
|
||||
* @return {string} The send method.
|
||||
*/
|
||||
goog.net.XhrManager.Request.prototype.getMethod = function() {
|
||||
'use strict';
|
||||
return this.method_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Gets the post data.
|
||||
* @return {ArrayBuffer|ArrayBufferView|Blob|Document|FormData|string|undefined}
|
||||
* The post data.
|
||||
*/
|
||||
goog.net.XhrManager.Request.prototype.getContent = function() {
|
||||
'use strict';
|
||||
return this.content_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Gets the map of headers.
|
||||
* @return {Object|goog.structs.Map} The map of headers.
|
||||
*/
|
||||
goog.net.XhrManager.Request.prototype.getHeaders = function() {
|
||||
'use strict';
|
||||
return this.headers_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Gets the withCredentials flag.
|
||||
* @return {boolean} Add credentials, or not.
|
||||
*/
|
||||
goog.net.XhrManager.Request.prototype.getWithCredentials = function() {
|
||||
'use strict';
|
||||
return this.withCredentials_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Gets the maximum number of times the request should be retried.
|
||||
* @return {number} The maximum number of times the request should be retried.
|
||||
*/
|
||||
goog.net.XhrManager.Request.prototype.getMaxRetries = function() {
|
||||
'use strict';
|
||||
return this.maxRetries_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Gets the number of attempts so far.
|
||||
* @return {number} The number of attempts so far.
|
||||
*/
|
||||
goog.net.XhrManager.Request.prototype.getAttemptCount = function() {
|
||||
'use strict';
|
||||
return this.attemptCount_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Increases the number of attempts so far.
|
||||
*/
|
||||
goog.net.XhrManager.Request.prototype.increaseAttemptCount = function() {
|
||||
'use strict';
|
||||
this.attemptCount_++;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns whether the request has reached the maximum number of retries.
|
||||
* @return {boolean} Whether the request has reached the maximum number of
|
||||
* retries.
|
||||
*/
|
||||
goog.net.XhrManager.Request.prototype.hasReachedMaxRetries = function() {
|
||||
'use strict';
|
||||
return this.attemptCount_ > this.maxRetries_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Sets the completed status.
|
||||
* @param {boolean} complete The completed status.
|
||||
*/
|
||||
goog.net.XhrManager.Request.prototype.setCompleted = function(complete) {
|
||||
'use strict';
|
||||
this.completed_ = complete;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Gets the completed status.
|
||||
* @return {boolean} The completed status.
|
||||
*/
|
||||
goog.net.XhrManager.Request.prototype.getCompleted = function() {
|
||||
'use strict';
|
||||
return this.completed_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Sets the aborted status.
|
||||
* @param {boolean} aborted True if the request was aborted, otherwise False.
|
||||
*/
|
||||
goog.net.XhrManager.Request.prototype.setAborted = function(aborted) {
|
||||
'use strict';
|
||||
this.aborted_ = aborted;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Gets the aborted status.
|
||||
* @return {boolean} True if request was aborted, otherwise False.
|
||||
*/
|
||||
goog.net.XhrManager.Request.prototype.getAborted = function() {
|
||||
'use strict';
|
||||
return this.aborted_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Gets the callback attached to the events of the XhrIo object.
|
||||
* @return {Function} The callback attached to the events of the
|
||||
* XhrIo object.
|
||||
*/
|
||||
goog.net.XhrManager.Request.prototype.getXhrEventCallback = function() {
|
||||
'use strict';
|
||||
return this.xhrEventCallback_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Gets the callback for when the request is complete.
|
||||
* @return {Function|undefined} The callback for when the request is complete.
|
||||
*/
|
||||
goog.net.XhrManager.Request.prototype.getCompleteCallback = function() {
|
||||
'use strict';
|
||||
return this.completeCallback_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Gets the response type that will be set on this request's XhrIo when it's
|
||||
* available.
|
||||
* @return {!goog.net.XhrIo.ResponseType} The response type to be set
|
||||
* when an XhrIo becomes available to this request.
|
||||
*/
|
||||
goog.net.XhrManager.Request.prototype.getResponseType = function() {
|
||||
'use strict';
|
||||
return this.responseType_;
|
||||
};
|
||||
Executable
+250
@@ -0,0 +1,250 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright The Closure Library Authors.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @fileoverview Low level handling of XMLHttpRequest.
|
||||
*/
|
||||
|
||||
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');
|
||||
goog.requireType('goog.net.XhrLike');
|
||||
|
||||
|
||||
/**
|
||||
* Static class for creating XMLHttpRequest objects.
|
||||
* @return {!goog.net.XhrLike.OrNative} A new XMLHttpRequest object.
|
||||
*/
|
||||
goog.net.XmlHttp = function() {
|
||||
'use strict';
|
||||
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
|
||||
* `goog.net.XmlHttpDefines.ASSUME_NATIVE_XHR` instead.
|
||||
* TODO(ruilopes): Collapse both defines.
|
||||
*/
|
||||
goog.net.XmlHttp.ASSUME_NATIVE_XHR =
|
||||
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.net.XmlHttpDefines.ASSUME_NATIVE_XHR =
|
||||
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() {
|
||||
'use strict';
|
||||
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) {
|
||||
'use strict';
|
||||
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) {
|
||||
'use strict';
|
||||
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() {
|
||||
'use strict';
|
||||
goog.net.XmlHttpFactory.call(this);
|
||||
};
|
||||
goog.inherits(goog.net.DefaultXmlHttpFactory, goog.net.XmlHttpFactory);
|
||||
|
||||
|
||||
/** @override */
|
||||
goog.net.DefaultXmlHttpFactory.prototype.createInstance = function() {
|
||||
'use strict';
|
||||
const progId = this.getProgId_();
|
||||
if (progId) {
|
||||
return new ActiveXObject(progId);
|
||||
} else {
|
||||
return new XMLHttpRequest();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/** @override */
|
||||
goog.net.DefaultXmlHttpFactory.prototype.internalGetOptions = function() {
|
||||
'use strict';
|
||||
const progId = this.getProgId_();
|
||||
const 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() {
|
||||
'use strict';
|
||||
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.
|
||||
const ACTIVE_X_IDENTS = [
|
||||
'MSXML2.XMLHTTP.6.0',
|
||||
'MSXML2.XMLHTTP.3.0',
|
||||
'MSXML2.XMLHTTP',
|
||||
'Microsoft.XMLHTTP',
|
||||
];
|
||||
for (let i = 0; i < ACTIVE_X_IDENTS.length; i++) {
|
||||
const 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 new 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());
|
||||
Executable
+58
@@ -0,0 +1,58 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright The Closure Library Authors.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @fileoverview Interface for a factory for creating XMLHttpRequest objects
|
||||
* and metadata about them.
|
||||
*/
|
||||
|
||||
goog.provide('goog.net.XmlHttpFactory');
|
||||
|
||||
/** @suppress {extraRequire} Typedef. */
|
||||
goog.require('goog.net.XhrLike');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Abstract base class for an XmlHttpRequest factory.
|
||||
* @constructor
|
||||
*/
|
||||
goog.net.XmlHttpFactory = function() {};
|
||||
|
||||
|
||||
/**
|
||||
* Cache of options - we only actually call internalGetOptions once.
|
||||
* @type {?Object}
|
||||
* @private
|
||||
*/
|
||||
goog.net.XmlHttpFactory.prototype.cachedOptions_ = null;
|
||||
|
||||
|
||||
/**
|
||||
* @return {!goog.net.XhrLike.OrNative} A new XhrLike instance.
|
||||
*/
|
||||
goog.net.XmlHttpFactory.prototype.createInstance = goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* @return {Object} Options describing how xhr objects obtained from this
|
||||
* factory should be used.
|
||||
*/
|
||||
goog.net.XmlHttpFactory.prototype.getOptions = function() {
|
||||
'use strict';
|
||||
return this.cachedOptions_ ||
|
||||
(this.cachedOptions_ = this.internalGetOptions());
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Override this method in subclasses to preserve the caching offered by
|
||||
* getOptions().
|
||||
* @return {Object} Options describing how xhr objects obtained from this
|
||||
* factory should be used.
|
||||
* @protected
|
||||
*/
|
||||
goog.net.XmlHttpFactory.prototype.internalGetOptions = goog.abstractMethod;
|
||||
Reference in New Issue
Block a user