mirror of
https://github.com/musix-org/musix-oss
synced 2024-11-14 16:00:17 +00:00
1 line
1.1 MiB
1 line
1.1 MiB
{"version":3,"file":"index.esm.js","sources":["../../../node_modules/closure-builder/third_party/closure-library/closure/goog/base.js","../../../node_modules/closure-builder/third_party/closure-library/closure/goog/disposable/disposable.js","../../../node_modules/closure-builder/third_party/closure-library/closure/goog/array/array.js","../../../node_modules/closure-builder/third_party/closure-library/closure/goog/net/xhrio.js","../../../node_modules/closure-builder/third_party/closure-library/closure/goog/string/internal.js","../../../node_modules/closure-builder/third_party/closure-library/closure/goog/labs/useragent/util.js","../../../node_modules/closure-builder/third_party/closure-library/closure/goog/object/object.js","../../../node_modules/closure-builder/third_party/closure-library/closure/goog/reflect/reflect.js","../../../node_modules/closure-builder/third_party/closure-library/closure/goog/useragent/useragent.js","../../../node_modules/closure-builder/third_party/closure-library/closure/goog/labs/useragent/browser.js","../../../node_modules/closure-builder/third_party/closure-library/closure/goog/labs/useragent/engine.js","../../../node_modules/closure-builder/third_party/closure-library/closure/goog/events/browserfeature.js","../../../node_modules/closure-builder/third_party/closure-library/closure/goog/events/event.js","../../../node_modules/closure-builder/third_party/closure-library/closure/goog/events/browserevent.js","../../../node_modules/closure-builder/third_party/closure-library/closure/goog/events/eventtype.js","../../../node_modules/closure-builder/third_party/closure-library/closure/goog/events/listenable.js","../../../node_modules/closure-builder/third_party/closure-library/closure/goog/events/listener.js","../../../node_modules/closure-builder/third_party/closure-library/closure/goog/events/listenermap.js","../../../node_modules/closure-builder/third_party/closure-library/closure/goog/events/events.js","../../../node_modules/closure-builder/third_party/closure-library/closure/goog/events/eventtarget.js","../../../node_modules/closure-builder/third_party/closure-library/closure/goog/json/json.js","../../../node_modules/closure-builder/third_party/closure-library/closure/goog/async/freelist.js","../../../node_modules/closure-builder/third_party/closure-library/closure/goog/async/workqueue.js","../../../node_modules/closure-builder/third_party/closure-library/closure/goog/async/run.js","../../../node_modules/closure-builder/third_party/closure-library/closure/goog/async/nexttick.js","../../../node_modules/closure-builder/third_party/closure-library/closure/goog/timer/timer.js","../../../node_modules/closure-builder/third_party/closure-library/closure/goog/async/throttle.js","../../../node_modules/closure-builder/third_party/closure-library/closure/goog/events/eventhandler.js","../../../node_modules/closure-builder/third_party/closure-library/closure/goog/labs/net/webchannel/webchanneldebug.js","../../../node_modules/closure-builder/third_party/closure-library/closure/goog/labs/net/webchannel/requeststats.js","../../../node_modules/closure-builder/third_party/closure-library/closure/goog/net/errorcode.js","../../../node_modules/closure-builder/third_party/closure-library/closure/goog/net/eventtype.js","../../../node_modules/closure-builder/third_party/closure-library/closure/goog/net/xmlhttpfactory.js","../../../node_modules/closure-builder/third_party/closure-library/closure/goog/net/xmlhttp.js","../../../node_modules/closure-builder/third_party/closure-library/closure/goog/labs/net/webchannel.js","../../../node_modules/closure-builder/third_party/closure-library/closure/goog/labs/net/webchannel/channelrequest.js","../../../node_modules/closure-builder/third_party/closure-library/closure/goog/labs/net/webchannel/environment.js","../../../node_modules/closure-builder/third_party/closure-library/closure/goog/labs/net/webchannel/webchannelbase.js","../../../node_modules/closure-builder/third_party/closure-library/closure/goog/string/string.js","../../../node_modules/closure-builder/third_party/closure-library/closure/goog/structs/structs.js","../../../node_modules/closure-builder/third_party/closure-library/closure/goog/structs/map.js","../../../node_modules/closure-builder/third_party/closure-library/closure/goog/uri/utils.js","../../../node_modules/closure-builder/third_party/closure-library/closure/goog/uri/uri.js","../../../node_modules/closure-builder/third_party/closure-library/closure/goog/debug/formatter.js","../../../node_modules/closure-builder/third_party/closure-library/closure/goog/labs/net/webchannel/basetestchannel.js","../../../node_modules/closure-builder/third_party/closure-library/closure/goog/labs/net/webchannel/wirev8.js","../../../node_modules/closure-builder/third_party/closure-library/closure/goog/labs/net/webchannel/connectionstate.js","../../../node_modules/closure-builder/third_party/closure-library/closure/goog/structs/set.js","../../../node_modules/closure-builder/third_party/closure-library/closure/goog/labs/net/webchannel/wire.js","../../../node_modules/closure-builder/third_party/closure-library/closure/goog/labs/net/webchannel/forwardchannelrequestpool.js","../../../node_modules/closure-builder/third_party/closure-library/closure/goog/json/nativejsonprocessor.js","../../../node_modules/closure-builder/third_party/closure-library/closure/goog/labs/net/webchannel/netutils.js","../../../node_modules/closure-builder/third_party/closure-library/closure/goog/json/hybrid.js","../../../node_modules/closure-builder/third_party/closure-library/closure/goog/net/httpstatus.js","../../../node_modules/closure-builder/third_party/closure-library/closure/goog/net/rpc/httpcors.js","../../../node_modules/closure-builder/third_party/closure-library/closure/goog/labs/net/webchanneltransport.js","../../../node_modules/closure-builder/third_party/closure-library/closure/goog/string/path.js","../../../node_modules/closure-builder/third_party/closure-library/closure/goog/labs/net/webchannel/webchannelbasetransport.js","../../../node_modules/closure-builder/third_party/closure-library/closure/goog/labs/net/webchanneltransportfactory.js","../../../node_modules/closure-builder/third_party/closure-library/closure/goog/functions/functions.js","../src/index.js"],"sourcesContent":["// Copyright 2006 The Closure Library Authors. All Rights Reserved.\r\n//\r\n// Licensed under the Apache License, Version 2.0 (the \"License\");\r\n// you may not use this file except in compliance with the License.\r\n// You may obtain a copy of the License at\r\n//\r\n// http://www.apache.org/licenses/LICENSE-2.0\r\n//\r\n// Unless required by applicable law or agreed to in writing, software\r\n// distributed under the License is distributed on an \"AS-IS\" BASIS,\r\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n// See the License for the specific language governing permissions and\r\n// limitations under the License.\r\n\r\n/**\r\n * @fileoverview Bootstrap for the Google JS Library (Closure).\r\n *\r\n * In uncompiled mode base.js will attempt to load Closure's deps file, unless\r\n * the global <code>CLOSURE_NO_DEPS</code> is set to true. This allows projects\r\n * to include their own deps file(s) from different locations.\r\n *\r\n * Avoid including base.js more than once. This is strictly discouraged and not\r\n * supported. goog.require(...) won't work properly in that case.\r\n *\r\n * @provideGoog\r\n */\r\n\r\n\r\n/**\r\n * @define {boolean} Overridden to true by the compiler.\r\n */\r\nvar COMPILED = false;\r\n\r\n\r\n/**\r\n * Base namespace for the Closure library. Checks to see goog is already\r\n * defined in the current scope before assigning to prevent clobbering if\r\n * base.js is loaded more than once.\r\n *\r\n * @const\r\n */\r\nvar goog = goog || {};\r\n\r\n/**\r\n * Reference to the global context. In most cases this will be 'window'.\r\n * @const\r\n * @suppress {newCheckTypes}\r\n */\r\ngoog.global = this;\r\n\r\n\r\n/**\r\n * A hook for overriding the define values in uncompiled mode.\r\n *\r\n * In uncompiled mode, `CLOSURE_UNCOMPILED_DEFINES` may be defined before\r\n * loading base.js. If a key is defined in `CLOSURE_UNCOMPILED_DEFINES`,\r\n * `goog.define` will use the value instead of the default value. This\r\n * allows flags to be overwritten without compilation (this is normally\r\n * accomplished with the compiler's \"define\" flag).\r\n *\r\n * Example:\r\n * <pre>\r\n * var CLOSURE_UNCOMPILED_DEFINES = {'goog.DEBUG': false};\r\n * </pre>\r\n *\r\n * @type {Object<string, (string|number|boolean)>|undefined}\r\n */\r\ngoog.global.CLOSURE_UNCOMPILED_DEFINES;\r\n\r\n\r\n/**\r\n * A hook for overriding the define values in uncompiled or compiled mode,\r\n * like CLOSURE_UNCOMPILED_DEFINES but effective in compiled code. In\r\n * uncompiled code CLOSURE_UNCOMPILED_DEFINES takes precedence.\r\n *\r\n * Also unlike CLOSURE_UNCOMPILED_DEFINES the values must be number, boolean or\r\n * string literals or the compiler will emit an error.\r\n *\r\n * While any @define value may be set, only those set with goog.define will be\r\n * effective for uncompiled code.\r\n *\r\n * Example:\r\n * <pre>\r\n * var CLOSURE_DEFINES = {'goog.DEBUG': false} ;\r\n * </pre>\r\n *\r\n * @type {Object<string, (string|number|boolean)>|undefined}\r\n */\r\ngoog.global.CLOSURE_DEFINES;\r\n\r\n\r\n/**\r\n * Returns true if the specified value is not undefined.\r\n *\r\n * @param {?} val Variable to test.\r\n * @return {boolean} Whether variable is defined.\r\n */\r\ngoog.isDef = function(val) {\r\n // void 0 always evaluates to undefined and hence we do not need to depend on\r\n // the definition of the global variable named 'undefined'.\r\n return val !== void 0;\r\n};\r\n\r\n/**\r\n * Returns true if the specified value is a string.\r\n * @param {?} val Variable to test.\r\n * @return {boolean} Whether variable is a string.\r\n */\r\ngoog.isString = function(val) {\r\n return typeof val == 'string';\r\n};\r\n\r\n\r\n/**\r\n * Returns true if the specified value is a boolean.\r\n * @param {?} val Variable to test.\r\n * @return {boolean} Whether variable is boolean.\r\n */\r\ngoog.isBoolean = function(val) {\r\n return typeof val == 'boolean';\r\n};\r\n\r\n\r\n/**\r\n * Returns true if the specified value is a number.\r\n * @param {?} val Variable to test.\r\n * @return {boolean} Whether variable is a number.\r\n */\r\ngoog.isNumber = function(val) {\r\n return typeof val == 'number';\r\n};\r\n\r\n\r\n/**\r\n * Builds an object structure for the provided namespace path, ensuring that\r\n * names that already exist are not overwritten. For example:\r\n * \"a.b.c\" -> a = {};a.b={};a.b.c={};\r\n * Used by goog.provide and goog.exportSymbol.\r\n * @param {string} name name of the object that this file defines.\r\n * @param {*=} opt_object the object to expose at the end of the path.\r\n * @param {Object=} opt_objectToExportTo The object to add the path to; default\r\n * is `goog.global`.\r\n * @private\r\n */\r\ngoog.exportPath_ = function(name, opt_object, opt_objectToExportTo) {\r\n var parts = name.split('.');\r\n var cur = opt_objectToExportTo || goog.global;\r\n\r\n // Internet Explorer exhibits strange behavior when throwing errors from\r\n // methods externed in this manner. See the testExportSymbolExceptions in\r\n // base_test.html for an example.\r\n if (!(parts[0] in cur) && typeof cur.execScript != 'undefined') {\r\n cur.execScript('var ' + parts[0]);\r\n }\r\n\r\n for (var part; parts.length && (part = parts.shift());) {\r\n if (!parts.length && goog.isDef(opt_object)) {\r\n // last part and we have an object; use it\r\n cur[part] = opt_object;\r\n } else if (cur[part] && cur[part] !== Object.prototype[part]) {\r\n cur = cur[part];\r\n } else {\r\n cur = cur[part] = {};\r\n }\r\n }\r\n};\r\n\r\n\r\n/**\r\n * Defines a named value. In uncompiled mode, the value is retrieved from\r\n * CLOSURE_DEFINES or CLOSURE_UNCOMPILED_DEFINES if the object is defined and\r\n * has the property specified, and otherwise used the defined defaultValue.\r\n * When compiled the default can be overridden using the compiler options or the\r\n * value set in the CLOSURE_DEFINES object. Returns the defined value so that it\r\n * can be used safely in modules. Note that the value type MUST be either\r\n * boolean, number, or string.\r\n *\r\n * @param {string} name The distinguished name to provide.\r\n * @param {T} defaultValue\r\n * @return {T} The defined value.\r\n * @template T\r\n */\r\ngoog.define = function(name, defaultValue) {\r\n var value = defaultValue;\r\n if (!COMPILED) {\r\n var uncompiledDefines = goog.global.CLOSURE_UNCOMPILED_DEFINES;\r\n var defines = goog.global.CLOSURE_DEFINES;\r\n if (uncompiledDefines &&\r\n // Anti DOM-clobbering runtime check (b/37736576).\r\n /** @type {?} */ (uncompiledDefines).nodeType === undefined &&\r\n Object.prototype.hasOwnProperty.call(uncompiledDefines, name)) {\r\n value = uncompiledDefines[name];\r\n } else if (\r\n defines &&\r\n // Anti DOM-clobbering runtime check (b/37736576).\r\n /** @type {?} */ (defines).nodeType === undefined &&\r\n Object.prototype.hasOwnProperty.call(defines, name)) {\r\n value = defines[name];\r\n }\r\n }\r\n goog.exportPath_(name, value);\r\n return value;\r\n};\r\n\r\n\r\n/**\r\n * @define {number} Integer year indicating the set of browser features that are\r\n * guaranteed to be present. This is defined to include exactly features that\r\n * work correctly on all \"modern\" browsers that are stable on January 1 of the\r\n * specified year. For example,\r\n * ```js\r\n * if (goog.FEATURESET_YEAR >= 2019) {\r\n * // use APIs known to be available on all major stable browsers Jan 1, 2019\r\n * } else {\r\n * // polyfill for older browsers\r\n * }\r\n * ```\r\n * This is intended to be the primary define for removing\r\n * unnecessary browser compatibility code (such as ponyfills and workarounds),\r\n * and should inform the default value for most other defines:\r\n * ```js\r\n * const ASSUME_NATIVE_PROMISE =\r\n * goog.define('ASSUME_NATIVE_PROMISE', goog.FEATURESET_YEAR >= 2016);\r\n * ```\r\n *\r\n * The default assumption is that IE9 is the lowest supported browser, which was\r\n * first available Jan 1, 2012.\r\n *\r\n * TODO(user): Reference more thorough documentation when it's available.\r\n */\r\ngoog.FEATURESET_YEAR = goog.define('goog.FEATURESET_YEAR', 2012);\r\n\r\n\r\n/**\r\n * @define {boolean} DEBUG is provided as a convenience so that debugging code\r\n * that should not be included in a production. It can be easily stripped\r\n * by specifying --define goog.DEBUG=false to the Closure Compiler aka\r\n * JSCompiler. For example, most toString() methods should be declared inside an\r\n * \"if (goog.DEBUG)\" conditional because they are generally used for debugging\r\n * purposes and it is difficult for the JSCompiler to statically determine\r\n * whether they are used.\r\n */\r\ngoog.DEBUG = goog.define('goog.DEBUG', true);\r\n\r\n\r\n/**\r\n * @define {string} LOCALE defines the locale being used for compilation. It is\r\n * used to select locale specific data to be compiled in js binary. BUILD rule\r\n * can specify this value by \"--define goog.LOCALE=<locale_name>\" as a compiler\r\n * option.\r\n *\r\n * Take into account that the locale code format is important. You should use\r\n * the canonical Unicode format with hyphen as a delimiter. Language must be\r\n * lowercase, Language Script - Capitalized, Region - UPPERCASE.\r\n * There are few examples: pt-BR, en, en-US, sr-Latin-BO, zh-Hans-CN.\r\n *\r\n * See more info about locale codes here:\r\n * http://www.unicode.org/reports/tr35/#Unicode_Language_and_Locale_Identifiers\r\n *\r\n * For language codes you should use values defined by ISO 693-1. See it here\r\n * http://www.w3.org/WAI/ER/IG/ert/iso639.htm. There is only one exception from\r\n * this rule: the Hebrew language. For legacy reasons the old code (iw) should\r\n * be used instead of the new code (he).\r\n *\r\n */\r\ngoog.LOCALE = goog.define('goog.LOCALE', 'en'); // default to en\r\n\r\n\r\n/**\r\n * @define {boolean} Whether this code is running on trusted sites.\r\n *\r\n * On untrusted sites, several native functions can be defined or overridden by\r\n * external libraries like Prototype, Datejs, and JQuery and setting this flag\r\n * to false forces closure to use its own implementations when possible.\r\n *\r\n * If your JavaScript can be loaded by a third party site and you are wary about\r\n * relying on non-standard implementations, specify\r\n * \"--define goog.TRUSTED_SITE=false\" to the compiler.\r\n */\r\ngoog.TRUSTED_SITE = goog.define('goog.TRUSTED_SITE', true);\r\n\r\n\r\n/**\r\n * @define {boolean} Whether a project is expected to be running in strict mode.\r\n *\r\n * This define can be used to trigger alternate implementations compatible with\r\n * running in EcmaScript Strict mode or warn about unavailable functionality.\r\n * @see https://goo.gl/PudQ4y\r\n *\r\n */\r\ngoog.STRICT_MODE_COMPATIBLE = goog.define('goog.STRICT_MODE_COMPATIBLE', false);\r\n\r\n\r\n/**\r\n * @define {boolean} Whether code that calls {@link goog.setTestOnly} should\r\n * be disallowed in the compilation unit.\r\n */\r\ngoog.DISALLOW_TEST_ONLY_CODE =\r\n goog.define('goog.DISALLOW_TEST_ONLY_CODE', COMPILED && !goog.DEBUG);\r\n\r\n\r\n/**\r\n * @define {boolean} Whether to use a Chrome app CSP-compliant method for\r\n * loading scripts via goog.require. @see appendScriptSrcNode_.\r\n */\r\ngoog.ENABLE_CHROME_APP_SAFE_SCRIPT_LOADING =\r\n goog.define('goog.ENABLE_CHROME_APP_SAFE_SCRIPT_LOADING', false);\r\n\r\n\r\n/**\r\n * Defines a namespace in Closure.\r\n *\r\n * A namespace may only be defined once in a codebase. It may be defined using\r\n * goog.provide() or goog.module().\r\n *\r\n * The presence of one or more goog.provide() calls in a file indicates\r\n * that the file defines the given objects/namespaces.\r\n * Provided symbols must not be null or undefined.\r\n *\r\n * In addition, goog.provide() creates the object stubs for a namespace\r\n * (for example, goog.provide(\"goog.foo.bar\") will create the object\r\n * goog.foo.bar if it does not already exist).\r\n *\r\n * Build tools also scan for provide/require/module statements\r\n * to discern dependencies, build dependency files (see deps.js), etc.\r\n *\r\n * @see goog.require\r\n * @see goog.module\r\n * @param {string} name Namespace provided by this file in the form\r\n * \"goog.package.part\".\r\n */\r\ngoog.provide = function(name) {\r\n if (goog.isInModuleLoader_()) {\r\n throw new Error('goog.provide cannot be used within a module.');\r\n }\r\n if (!COMPILED) {\r\n // Ensure that the same namespace isn't provided twice.\r\n // A goog.module/goog.provide maps a goog.require to a specific file\r\n if (goog.isProvided_(name)) {\r\n throw new Error('Namespace \"' + name + '\" already declared.');\r\n }\r\n }\r\n\r\n goog.constructNamespace_(name);\r\n};\r\n\r\n\r\n/**\r\n * @param {string} name Namespace provided by this file in the form\r\n * \"goog.package.part\".\r\n * @param {Object=} opt_obj The object to embed in the namespace.\r\n * @private\r\n */\r\ngoog.constructNamespace_ = function(name, opt_obj) {\r\n if (!COMPILED) {\r\n delete goog.implicitNamespaces_[name];\r\n\r\n var namespace = name;\r\n while ((namespace = namespace.substring(0, namespace.lastIndexOf('.')))) {\r\n if (goog.getObjectByName(namespace)) {\r\n break;\r\n }\r\n goog.implicitNamespaces_[namespace] = true;\r\n }\r\n }\r\n\r\n goog.exportPath_(name, opt_obj);\r\n};\r\n\r\n\r\n/**\r\n * Returns CSP nonce, if set for any script tag.\r\n * @param {?Window=} opt_window The window context used to retrieve the nonce.\r\n * Defaults to global context.\r\n * @return {string} CSP nonce or empty string if no nonce is present.\r\n */\r\ngoog.getScriptNonce = function(opt_window) {\r\n if (opt_window && opt_window != goog.global) {\r\n return goog.getScriptNonce_(opt_window.document);\r\n }\r\n if (goog.cspNonce_ === null) {\r\n goog.cspNonce_ = goog.getScriptNonce_(goog.global.document);\r\n }\r\n return goog.cspNonce_;\r\n};\r\n\r\n\r\n/**\r\n * According to the CSP3 spec a nonce must be a valid base64 string.\r\n * @see https://www.w3.org/TR/CSP3/#grammardef-base64-value\r\n * @private @const\r\n */\r\ngoog.NONCE_PATTERN_ = /^[\\w+/_-]+[=]{0,2}$/;\r\n\r\n\r\n/**\r\n * @private {?string}\r\n */\r\ngoog.cspNonce_ = null;\r\n\r\n\r\n/**\r\n * Returns CSP nonce, if set for any script tag.\r\n * @param {!Document} doc\r\n * @return {string} CSP nonce or empty string if no nonce is present.\r\n * @private\r\n */\r\ngoog.getScriptNonce_ = function(doc) {\r\n var script = doc.querySelector && doc.querySelector('script[nonce]');\r\n if (script) {\r\n // Try to get the nonce from the IDL property first, because browsers that\r\n // implement additional nonce protection features (currently only Chrome) to\r\n // prevent nonce stealing via CSS do not expose the nonce via attributes.\r\n // See https://github.com/whatwg/html/issues/2369\r\n var nonce = script['nonce'] || script.getAttribute('nonce');\r\n if (nonce && goog.NONCE_PATTERN_.test(nonce)) {\r\n return nonce;\r\n }\r\n }\r\n return '';\r\n};\r\n\r\n\r\n/**\r\n * Module identifier validation regexp.\r\n * Note: This is a conservative check, it is very possible to be more lenient,\r\n * the primary exclusion here is \"/\" and \"\\\" and a leading \".\", these\r\n * restrictions are intended to leave the door open for using goog.require\r\n * with relative file paths rather than module identifiers.\r\n * @private\r\n */\r\ngoog.VALID_MODULE_RE_ = /^[a-zA-Z_$][a-zA-Z0-9._$]*$/;\r\n\r\n\r\n/**\r\n * Defines a module in Closure.\r\n *\r\n * Marks that this file must be loaded as a module and claims the namespace.\r\n *\r\n * A namespace may only be defined once in a codebase. It may be defined using\r\n * goog.provide() or goog.module().\r\n *\r\n * goog.module() has three requirements:\r\n * - goog.module may not be used in the same file as goog.provide.\r\n * - goog.module must be the first statement in the file.\r\n * - only one goog.module is allowed per file.\r\n *\r\n * When a goog.module annotated file is loaded, it is enclosed in\r\n * a strict function closure. This means that:\r\n * - any variables declared in a goog.module file are private to the file\r\n * (not global), though the compiler is expected to inline the module.\r\n * - The code must obey all the rules of \"strict\" JavaScript.\r\n * - the file will be marked as \"use strict\"\r\n *\r\n * NOTE: unlike goog.provide, goog.module does not declare any symbols by\r\n * itself. If declared symbols are desired, use\r\n * goog.module.declareLegacyNamespace().\r\n *\r\n *\r\n * See the public goog.module proposal: http://goo.gl/Va1hin\r\n *\r\n * @param {string} name Namespace provided by this file in the form\r\n * \"goog.package.part\", is expected but not required.\r\n * @return {void}\r\n */\r\ngoog.module = function(name) {\r\n if (!goog.isString(name) || !name ||\r\n name.search(goog.VALID_MODULE_RE_) == -1) {\r\n throw new Error('Invalid module identifier');\r\n }\r\n if (!goog.isInGoogModuleLoader_()) {\r\n throw new Error(\r\n 'Module ' + name + ' has been loaded incorrectly. Note, ' +\r\n 'modules cannot be loaded as normal scripts. They require some kind of ' +\r\n 'pre-processing step. You\\'re likely trying to load a module via a ' +\r\n 'script tag or as a part of a concatenated bundle without rewriting the ' +\r\n 'module. For more info see: ' +\r\n 'https://github.com/google/closure-library/wiki/goog.module:-an-ES6-module-like-alternative-to-goog.provide.');\r\n }\r\n if (goog.moduleLoaderState_.moduleName) {\r\n throw new Error('goog.module may only be called once per module.');\r\n }\r\n\r\n // Store the module name for the loader.\r\n goog.moduleLoaderState_.moduleName = name;\r\n if (!COMPILED) {\r\n // Ensure that the same namespace isn't provided twice.\r\n // A goog.module/goog.provide maps a goog.require to a specific file\r\n if (goog.isProvided_(name)) {\r\n throw new Error('Namespace \"' + name + '\" already declared.');\r\n }\r\n delete goog.implicitNamespaces_[name];\r\n }\r\n};\r\n\r\n\r\n/**\r\n * @param {string} name The module identifier.\r\n * @return {?} The module exports for an already loaded module or null.\r\n *\r\n * Note: This is not an alternative to goog.require, it does not\r\n * indicate a hard dependency, instead it is used to indicate\r\n * an optional dependency or to access the exports of a module\r\n * that has already been loaded.\r\n * @suppress {missingProvide}\r\n */\r\ngoog.module.get = function(name) {\r\n\r\n return goog.module.getInternal_(name);\r\n};\r\n\r\n\r\n/**\r\n * @param {string} name The module identifier.\r\n * @return {?} The module exports for an already loaded module or null.\r\n * @private\r\n */\r\ngoog.module.getInternal_ = function(name) {\r\n if (!COMPILED) {\r\n if (name in goog.loadedModules_) {\r\n return goog.loadedModules_[name].exports;\r\n } else if (!goog.implicitNamespaces_[name]) {\r\n var ns = goog.getObjectByName(name);\r\n return ns != null ? ns : null;\r\n }\r\n }\r\n return null;\r\n};\r\n\r\n\r\n/**\r\n * Types of modules the debug loader can load.\r\n * @enum {string}\r\n */\r\ngoog.ModuleType = {\r\n ES6: 'es6',\r\n GOOG: 'goog'\r\n};\r\n\r\n\r\n/**\r\n * @private {?{\r\n * moduleName: (string|undefined),\r\n * declareLegacyNamespace:boolean,\r\n * type: ?goog.ModuleType\r\n * }}\r\n */\r\ngoog.moduleLoaderState_ = null;\r\n\r\n\r\n/**\r\n * @private\r\n * @return {boolean} Whether a goog.module or an es6 module is currently being\r\n * initialized.\r\n */\r\ngoog.isInModuleLoader_ = function() {\r\n return goog.isInGoogModuleLoader_() || goog.isInEs6ModuleLoader_();\r\n};\r\n\r\n\r\n/**\r\n * @private\r\n * @return {boolean} Whether a goog.module is currently being initialized.\r\n */\r\ngoog.isInGoogModuleLoader_ = function() {\r\n return !!goog.moduleLoaderState_ &&\r\n goog.moduleLoaderState_.type == goog.ModuleType.GOOG;\r\n};\r\n\r\n\r\n/**\r\n * @private\r\n * @return {boolean} Whether an es6 module is currently being initialized.\r\n */\r\ngoog.isInEs6ModuleLoader_ = function() {\r\n var inLoader = !!goog.moduleLoaderState_ &&\r\n goog.moduleLoaderState_.type == goog.ModuleType.ES6;\r\n\r\n if (inLoader) {\r\n return true;\r\n }\r\n\r\n var jscomp = goog.global['$jscomp'];\r\n\r\n if (jscomp) {\r\n // jscomp may not have getCurrentModulePath if this is a compiled bundle\r\n // that has some of the runtime, but not all of it. This can happen if\r\n // optimizations are turned on so the unused runtime is removed but renaming\r\n // and Closure pass are off (so $jscomp is still named $jscomp and the\r\n // goog.provide/require calls still exist).\r\n if (typeof jscomp.getCurrentModulePath != 'function') {\r\n return false;\r\n }\r\n\r\n // Bundled ES6 module.\r\n return !!jscomp.getCurrentModulePath();\r\n }\r\n\r\n return false;\r\n};\r\n\r\n\r\n/**\r\n * Provide the module's exports as a globally accessible object under the\r\n * module's declared name. This is intended to ease migration to goog.module\r\n * for files that have existing usages.\r\n * @suppress {missingProvide}\r\n */\r\ngoog.module.declareLegacyNamespace = function() {\r\n if (!COMPILED && !goog.isInGoogModuleLoader_()) {\r\n throw new Error(\r\n 'goog.module.declareLegacyNamespace must be called from ' +\r\n 'within a goog.module');\r\n }\r\n if (!COMPILED && !goog.moduleLoaderState_.moduleName) {\r\n throw new Error(\r\n 'goog.module must be called prior to ' +\r\n 'goog.module.declareLegacyNamespace.');\r\n }\r\n goog.moduleLoaderState_.declareLegacyNamespace = true;\r\n};\r\n\r\n\r\n/**\r\n * Associates an ES6 module with a Closure module ID so that is available via\r\n * goog.require. The associated ID acts like a goog.module ID - it does not\r\n * create any global names, it is merely available via goog.require /\r\n * goog.module.get / goog.forwardDeclare / goog.requireType. goog.require and\r\n * goog.module.get will return the entire module as if it was import *'d. This\r\n * allows Closure files to reference ES6 modules for the sake of migration.\r\n *\r\n * @param {string} namespace\r\n * @suppress {missingProvide}\r\n */\r\ngoog.declareModuleId = function(namespace) {\r\n if (!COMPILED) {\r\n if (!goog.isInEs6ModuleLoader_()) {\r\n throw new Error(\r\n 'goog.declareModuleId may only be called from ' +\r\n 'within an ES6 module');\r\n }\r\n if (goog.moduleLoaderState_ && goog.moduleLoaderState_.moduleName) {\r\n throw new Error(\r\n 'goog.declareModuleId may only be called once per module.');\r\n }\r\n if (namespace in goog.loadedModules_) {\r\n throw new Error(\r\n 'Module with namespace \"' + namespace + '\" already exists.');\r\n }\r\n }\r\n if (goog.moduleLoaderState_) {\r\n // Not bundled - debug loading.\r\n goog.moduleLoaderState_.moduleName = namespace;\r\n } else {\r\n // Bundled - not debug loading, no module loader state.\r\n var jscomp = goog.global['$jscomp'];\r\n if (!jscomp || typeof jscomp.getCurrentModulePath != 'function') {\r\n throw new Error(\r\n 'Module with namespace \"' + namespace +\r\n '\" has been loaded incorrectly.');\r\n }\r\n var exports = jscomp.require(jscomp.getCurrentModulePath());\r\n goog.loadedModules_[namespace] = {\r\n exports: exports,\r\n type: goog.ModuleType.ES6,\r\n moduleId: namespace\r\n };\r\n }\r\n};\r\n\r\n\r\n/**\r\n * Marks that the current file should only be used for testing, and never for\r\n * live code in production.\r\n *\r\n * In the case of unit tests, the message may optionally be an exact namespace\r\n * for the test (e.g. 'goog.stringTest'). The linter will then ignore the extra\r\n * provide (if not explicitly defined in the code).\r\n *\r\n * @param {string=} opt_message Optional message to add to the error that's\r\n * raised when used in production code.\r\n */\r\ngoog.setTestOnly = function(opt_message) {\r\n if (goog.DISALLOW_TEST_ONLY_CODE) {\r\n opt_message = opt_message || '';\r\n throw new Error(\r\n 'Importing test-only code into non-debug environment' +\r\n (opt_message ? ': ' + opt_message : '.'));\r\n }\r\n};\r\n\r\n\r\n/**\r\n * Forward declares a symbol. This is an indication to the compiler that the\r\n * symbol may be used in the source yet is not required and may not be provided\r\n * in compilation.\r\n *\r\n * The most common usage of forward declaration is code that takes a type as a\r\n * function parameter but does not need to require it. By forward declaring\r\n * instead of requiring, no hard dependency is made, and (if not required\r\n * elsewhere) the namespace may never be required and thus, not be pulled\r\n * into the JavaScript binary. If it is required elsewhere, it will be type\r\n * checked as normal.\r\n *\r\n * Before using goog.forwardDeclare, please read the documentation at\r\n * https://github.com/google/closure-compiler/wiki/Bad-Type-Annotation to\r\n * understand the options and tradeoffs when working with forward declarations.\r\n *\r\n * @param {string} name The namespace to forward declare in the form of\r\n * \"goog.package.part\".\r\n */\r\ngoog.forwardDeclare = function(name) {};\r\n\r\n\r\n/**\r\n * Forward declare type information. Used to assign types to goog.global\r\n * referenced object that would otherwise result in unknown type references\r\n * and thus block property disambiguation.\r\n */\r\ngoog.forwardDeclare('Document');\r\ngoog.forwardDeclare('HTMLScriptElement');\r\ngoog.forwardDeclare('XMLHttpRequest');\r\n\r\n\r\nif (!COMPILED) {\r\n /**\r\n * Check if the given name has been goog.provided. This will return false for\r\n * names that are available only as implicit namespaces.\r\n * @param {string} name name of the object to look for.\r\n * @return {boolean} Whether the name has been provided.\r\n * @private\r\n */\r\n goog.isProvided_ = function(name) {\r\n return (name in goog.loadedModules_) ||\r\n (!goog.implicitNamespaces_[name] &&\r\n goog.isDefAndNotNull(goog.getObjectByName(name)));\r\n };\r\n\r\n /**\r\n * Namespaces implicitly defined by goog.provide. For example,\r\n * goog.provide('goog.events.Event') implicitly declares that 'goog' and\r\n * 'goog.events' must be namespaces.\r\n *\r\n * @type {!Object<string, (boolean|undefined)>}\r\n * @private\r\n */\r\n goog.implicitNamespaces_ = {'goog.module': true};\r\n\r\n // NOTE: We add goog.module as an implicit namespace as goog.module is defined\r\n // here and because the existing module package has not been moved yet out of\r\n // the goog.module namespace. This satisifies both the debug loader and\r\n // ahead-of-time dependency management.\r\n}\r\n\r\n\r\n/**\r\n * Returns an object based on its fully qualified external name. The object\r\n * is not found if null or undefined. If you are using a compilation pass that\r\n * renames property names beware that using this function will not find renamed\r\n * properties.\r\n *\r\n * @param {string} name The fully qualified name.\r\n * @param {Object=} opt_obj The object within which to look; default is\r\n * |goog.global|.\r\n * @return {?} The value (object or primitive) or, if not found, null.\r\n */\r\ngoog.getObjectByName = function(name, opt_obj) {\r\n var parts = name.split('.');\r\n var cur = opt_obj || goog.global;\r\n for (var i = 0; i < parts.length; i++) {\r\n cur = cur[parts[i]];\r\n if (!goog.isDefAndNotNull(cur)) {\r\n return null;\r\n }\r\n }\r\n return cur;\r\n};\r\n\r\n\r\n/**\r\n * Globalizes a whole namespace, such as goog or goog.lang.\r\n *\r\n * @param {!Object} obj The namespace to globalize.\r\n * @param {Object=} opt_global The object to add the properties to.\r\n * @deprecated Properties may be explicitly exported to the global scope, but\r\n * this should no longer be done in bulk.\r\n */\r\ngoog.globalize = function(obj, opt_global) {\r\n var global = opt_global || goog.global;\r\n for (var x in obj) {\r\n global[x] = obj[x];\r\n }\r\n};\r\n\r\n\r\n/**\r\n * Adds a dependency from a file to the files it requires.\r\n * @param {string} relPath The path to the js file.\r\n * @param {!Array<string>} provides An array of strings with\r\n * the names of the objects this file provides.\r\n * @param {!Array<string>} requires An array of strings with\r\n * the names of the objects this file requires.\r\n * @param {boolean|!Object<string>=} opt_loadFlags Parameters indicating\r\n * how the file must be loaded. The boolean 'true' is equivalent\r\n * to {'module': 'goog'} for backwards-compatibility. Valid properties\r\n * and values include {'module': 'goog'} and {'lang': 'es6'}.\r\n */\r\ngoog.addDependency = function(relPath, provides, requires, opt_loadFlags) {\r\n if (!COMPILED && goog.DEPENDENCIES_ENABLED) {\r\n goog.debugLoader_.addDependency(relPath, provides, requires, opt_loadFlags);\r\n }\r\n};\r\n\r\n\r\n\r\n\r\n// NOTE(nnaze): The debug DOM loader was included in base.js as an original way\r\n// to do \"debug-mode\" development. The dependency system can sometimes be\r\n// confusing, as can the debug DOM loader's asynchronous nature.\r\n//\r\n// With the DOM loader, a call to goog.require() is not blocking -- the script\r\n// will not load until some point after the current script. If a namespace is\r\n// needed at runtime, it needs to be defined in a previous script, or loaded via\r\n// require() with its registered dependencies.\r\n//\r\n// User-defined namespaces may need their own deps file. For a reference on\r\n// creating a deps file, see:\r\n// Externally: https://developers.google.com/closure/library/docs/depswriter\r\n//\r\n// Because of legacy clients, the DOM loader can't be easily removed from\r\n// base.js. Work was done to make it disableable or replaceable for\r\n// different environments (DOM-less JavaScript interpreters like Rhino or V8,\r\n// for example). See bootstrap/ for more information.\r\n\r\n\r\n/**\r\n * @define {boolean} Whether to enable the debug loader.\r\n *\r\n * If enabled, a call to goog.require() will attempt to load the namespace by\r\n * appending a script tag to the DOM (if the namespace has been registered).\r\n *\r\n * If disabled, goog.require() will simply assert that the namespace has been\r\n * provided (and depend on the fact that some outside tool correctly ordered\r\n * the script).\r\n */\r\ngoog.ENABLE_DEBUG_LOADER = goog.define('goog.ENABLE_DEBUG_LOADER', true);\r\n\r\n\r\n/**\r\n * @param {string} msg\r\n * @private\r\n */\r\ngoog.logToConsole_ = function(msg) {\r\n if (goog.global.console) {\r\n goog.global.console['error'](msg);\r\n }\r\n};\r\n\r\n\r\n/**\r\n * Implements a system for the dynamic resolution of dependencies that works in\r\n * parallel with the BUILD system.\r\n *\r\n * Note that all calls to goog.require will be stripped by the compiler.\r\n *\r\n * @see goog.provide\r\n * @param {string} namespace Namespace (as was given in goog.provide,\r\n * goog.module, or goog.declareModuleId) in the form\r\n * \"goog.package.part\".\r\n * @return {?} If called within a goog.module or ES6 module file, the associated\r\n * namespace or module otherwise null.\r\n */\r\ngoog.require = function(namespace) {\r\n if (!COMPILED) {\r\n // Might need to lazy load on old IE.\r\n if (goog.ENABLE_DEBUG_LOADER) {\r\n goog.debugLoader_.requested(namespace);\r\n }\r\n\r\n // If the object already exists we do not need to do anything.\r\n if (goog.isProvided_(namespace)) {\r\n if (goog.isInModuleLoader_()) {\r\n return goog.module.getInternal_(namespace);\r\n }\r\n } else if (goog.ENABLE_DEBUG_LOADER) {\r\n var moduleLoaderState = goog.moduleLoaderState_;\r\n goog.moduleLoaderState_ = null;\r\n try {\r\n goog.debugLoader_.load_(namespace);\r\n } finally {\r\n goog.moduleLoaderState_ = moduleLoaderState;\r\n }\r\n }\r\n\r\n return null;\r\n }\r\n};\r\n\r\n\r\n/**\r\n * Requires a symbol for its type information. This is an indication to the\r\n * compiler that the symbol may appear in type annotations, yet it is not\r\n * referenced at runtime.\r\n *\r\n * When called within a goog.module or ES6 module file, the return value may be\r\n * assigned to or destructured into a variable, but it may not be otherwise used\r\n * in code outside of a type annotation.\r\n *\r\n * Note that all calls to goog.requireType will be stripped by the compiler.\r\n *\r\n * @param {string} namespace Namespace (as was given in goog.provide,\r\n * goog.module, or goog.declareModuleId) in the form\r\n * \"goog.package.part\".\r\n * @return {?}\r\n */\r\ngoog.requireType = function(namespace) {\r\n // Return an empty object so that single-level destructuring of the return\r\n // value doesn't crash at runtime when using the debug loader. Multi-level\r\n // destructuring isn't supported.\r\n return {};\r\n};\r\n\r\n\r\n/**\r\n * Path for included scripts.\r\n * @type {string}\r\n */\r\ngoog.basePath = '';\r\n\r\n\r\n/**\r\n * A hook for overriding the base path.\r\n * @type {string|undefined}\r\n */\r\ngoog.global.CLOSURE_BASE_PATH;\r\n\r\n\r\n/**\r\n * Whether to attempt to load Closure's deps file. By default, when uncompiled,\r\n * deps files will attempt to be loaded.\r\n * @type {boolean|undefined}\r\n */\r\ngoog.global.CLOSURE_NO_DEPS;\r\n\r\n\r\n/**\r\n * A function to import a single script. This is meant to be overridden when\r\n * Closure is being run in non-HTML contexts, such as web workers. It's defined\r\n * in the global scope so that it can be set before base.js is loaded, which\r\n * allows deps.js to be imported properly.\r\n *\r\n * The first parameter the script source, which is a relative URI. The second,\r\n * optional parameter is the script contents, in the event the script needed\r\n * transformation. It should return true if the script was imported, false\r\n * otherwise.\r\n * @type {(function(string, string=): boolean)|undefined}\r\n */\r\ngoog.global.CLOSURE_IMPORT_SCRIPT;\r\n\r\n\r\n/**\r\n * Null function used for default values of callbacks, etc.\r\n * @return {void} Nothing.\r\n */\r\ngoog.nullFunction = function() {};\r\n\r\n\r\n/**\r\n * When defining a class Foo with an abstract method bar(), you can do:\r\n * Foo.prototype.bar = goog.abstractMethod\r\n *\r\n * Now if a subclass of Foo fails to override bar(), an error will be thrown\r\n * when bar() is invoked.\r\n *\r\n * @type {!Function}\r\n * @throws {Error} when invoked to indicate the method should be overridden.\r\n */\r\ngoog.abstractMethod = function() {\r\n throw new Error('unimplemented abstract method');\r\n};\r\n\r\n\r\n/**\r\n * Adds a `getInstance` static method that always returns the same\r\n * instance object.\r\n * @param {!Function} ctor The constructor for the class to add the static\r\n * method to.\r\n * @suppress {missingProperties} 'instance_' isn't a property on 'Function'\r\n * but we don't have a better type to use here.\r\n */\r\ngoog.addSingletonGetter = function(ctor) {\r\n // instance_ is immediately set to prevent issues with sealed constructors\r\n // such as are encountered when a constructor is returned as the export object\r\n // of a goog.module in unoptimized code.\r\n // Delcare type to avoid conformance violations that ctor.instance_ is unknown\r\n /** @type {undefined|!Object} @suppress {underscore} */\r\n ctor.instance_ = undefined;\r\n ctor.getInstance = function() {\r\n if (ctor.instance_) {\r\n return ctor.instance_;\r\n }\r\n if (goog.DEBUG) {\r\n // NOTE: JSCompiler can't optimize away Array#push.\r\n goog.instantiatedSingletons_[goog.instantiatedSingletons_.length] = ctor;\r\n }\r\n // Cast to avoid conformance violations that ctor.instance_ is unknown\r\n return /** @type {!Object|undefined} */ (ctor.instance_) = new ctor;\r\n };\r\n};\r\n\r\n\r\n/**\r\n * All singleton classes that have been instantiated, for testing. Don't read\r\n * it directly, use the `goog.testing.singleton` module. The compiler\r\n * removes this variable if unused.\r\n * @type {!Array<!Function>}\r\n * @private\r\n */\r\ngoog.instantiatedSingletons_ = [];\r\n\r\n\r\n/**\r\n * @define {boolean} Whether to load goog.modules using `eval` when using\r\n * the debug loader. This provides a better debugging experience as the\r\n * source is unmodified and can be edited using Chrome Workspaces or similar.\r\n * However in some environments the use of `eval` is banned\r\n * so we provide an alternative.\r\n */\r\ngoog.LOAD_MODULE_USING_EVAL = goog.define('goog.LOAD_MODULE_USING_EVAL', true);\r\n\r\n\r\n/**\r\n * @define {boolean} Whether the exports of goog.modules should be sealed when\r\n * possible.\r\n */\r\ngoog.SEAL_MODULE_EXPORTS = goog.define('goog.SEAL_MODULE_EXPORTS', goog.DEBUG);\r\n\r\n\r\n/**\r\n * The registry of initialized modules:\r\n * The module identifier or path to module exports map.\r\n * @private @const {!Object<string, {exports:?,type:string,moduleId:string}>}\r\n */\r\ngoog.loadedModules_ = {};\r\n\r\n\r\n/**\r\n * True if the debug loader enabled and used.\r\n * @const {boolean}\r\n */\r\ngoog.DEPENDENCIES_ENABLED = !COMPILED && goog.ENABLE_DEBUG_LOADER;\r\n\r\n\r\n/**\r\n * @define {string} How to decide whether to transpile. Valid values\r\n * are 'always', 'never', and 'detect'. The default ('detect') is to\r\n * use feature detection to determine which language levels need\r\n * transpilation.\r\n */\r\n// NOTE(sdh): we could expand this to accept a language level to bypass\r\n// detection: e.g. goog.TRANSPILE == 'es5' would transpile ES6 files but\r\n// would leave ES3 and ES5 files alone.\r\ngoog.TRANSPILE = goog.define('goog.TRANSPILE', 'detect');\r\n\r\n/**\r\n * @define {boolean} If true assume that ES modules have already been\r\n * transpiled by the jscompiler (in the same way that transpile.js would\r\n * transpile them - to jscomp modules). Useful only for servers that wish to use\r\n * the debug loader and transpile server side. Thus this is only respected if\r\n * goog.TRANSPILE is \"never\".\r\n */\r\ngoog.ASSUME_ES_MODULES_TRANSPILED =\r\n goog.define('goog.ASSUME_ES_MODULES_TRANSPILED', false);\r\n\r\n\r\n/**\r\n * @define {string} If a file needs to be transpiled what the output language\r\n * should be. By default this is the highest language level this file detects\r\n * the current environment supports. Generally this flag should not be set, but\r\n * it could be useful to override. Example: If the current environment supports\r\n * ES6 then by default ES7+ files will be transpiled to ES6, unless this is\r\n * overridden.\r\n *\r\n * Valid values include: es3, es5, es6, es7, and es8. Anything not recognized\r\n * is treated as es3.\r\n *\r\n * Note that setting this value does not force transpilation. Just if\r\n * transpilation occurs this will be the output. So this is most useful when\r\n * goog.TRANSPILE is set to 'always' and then forcing the language level to be\r\n * something lower than what the environment detects.\r\n */\r\ngoog.TRANSPILE_TO_LANGUAGE = goog.define('goog.TRANSPILE_TO_LANGUAGE', '');\r\n\r\n\r\n/**\r\n * @define {string} Path to the transpiler. Executing the script at this\r\n * path (relative to base.js) should define a function $jscomp.transpile.\r\n */\r\ngoog.TRANSPILER = goog.define('goog.TRANSPILER', 'transpile.js');\r\n\r\n\r\n/**\r\n * @package {?boolean}\r\n * Visible for testing.\r\n */\r\ngoog.hasBadLetScoping = null;\r\n\r\n\r\n/**\r\n * @return {boolean}\r\n * @package Visible for testing.\r\n */\r\ngoog.useSafari10Workaround = function() {\r\n if (goog.hasBadLetScoping == null) {\r\n var hasBadLetScoping;\r\n try {\r\n hasBadLetScoping = !eval(\r\n '\"use strict\";' +\r\n 'let x = 1; function f() { return typeof x; };' +\r\n 'f() == \"number\";');\r\n } catch (e) {\r\n // Assume that ES6 syntax isn't supported.\r\n hasBadLetScoping = false;\r\n }\r\n goog.hasBadLetScoping = hasBadLetScoping;\r\n }\r\n return goog.hasBadLetScoping;\r\n};\r\n\r\n\r\n/**\r\n * @param {string} moduleDef\r\n * @return {string}\r\n * @package Visible for testing.\r\n */\r\ngoog.workaroundSafari10EvalBug = function(moduleDef) {\r\n return '(function(){' + moduleDef +\r\n '\\n' + // Terminate any trailing single line comment.\r\n ';' + // Terminate any trailing expression.\r\n '})();\\n';\r\n};\r\n\r\n\r\n/**\r\n * @param {function(?):?|string} moduleDef The module definition.\r\n */\r\ngoog.loadModule = function(moduleDef) {\r\n // NOTE: we allow function definitions to be either in the from\r\n // of a string to eval (which keeps the original source intact) or\r\n // in a eval forbidden environment (CSP) we allow a function definition\r\n // which in its body must call `goog.module`, and return the exports\r\n // of the module.\r\n var previousState = goog.moduleLoaderState_;\r\n try {\r\n goog.moduleLoaderState_ = {\r\n moduleName: '',\r\n declareLegacyNamespace: false,\r\n type: goog.ModuleType.GOOG\r\n };\r\n var exports;\r\n if (goog.isFunction(moduleDef)) {\r\n exports = moduleDef.call(undefined, {});\r\n } else if (goog.isString(moduleDef)) {\r\n if (goog.useSafari10Workaround()) {\r\n moduleDef = goog.workaroundSafari10EvalBug(moduleDef);\r\n }\r\n\r\n exports = goog.loadModuleFromSource_.call(undefined, moduleDef);\r\n } else {\r\n throw new Error('Invalid module definition');\r\n }\r\n\r\n var moduleName = goog.moduleLoaderState_.moduleName;\r\n if (goog.isString(moduleName) && moduleName) {\r\n // Don't seal legacy namespaces as they may be used as a parent of\r\n // another namespace\r\n if (goog.moduleLoaderState_.declareLegacyNamespace) {\r\n goog.constructNamespace_(moduleName, exports);\r\n } else if (\r\n goog.SEAL_MODULE_EXPORTS && Object.seal &&\r\n typeof exports == 'object' && exports != null) {\r\n Object.seal(exports);\r\n }\r\n\r\n var data = {\r\n exports: exports,\r\n type: goog.ModuleType.GOOG,\r\n moduleId: goog.moduleLoaderState_.moduleName\r\n };\r\n goog.loadedModules_[moduleName] = data;\r\n } else {\r\n throw new Error('Invalid module name \\\"' + moduleName + '\\\"');\r\n }\r\n } finally {\r\n goog.moduleLoaderState_ = previousState;\r\n }\r\n};\r\n\r\n\r\n/**\r\n * @private @const\r\n */\r\ngoog.loadModuleFromSource_ = /** @type {function(string):?} */ (function() {\r\n // NOTE: we avoid declaring parameters or local variables here to avoid\r\n // masking globals or leaking values into the module definition.\r\n 'use strict';\r\n var exports = {};\r\n eval(arguments[0]);\r\n return exports;\r\n});\r\n\r\n\r\n/**\r\n * Normalize a file path by removing redundant \"..\" and extraneous \".\" file\r\n * path components.\r\n * @param {string} path\r\n * @return {string}\r\n * @private\r\n */\r\ngoog.normalizePath_ = function(path) {\r\n var components = path.split('/');\r\n var i = 0;\r\n while (i < components.length) {\r\n if (components[i] == '.') {\r\n components.splice(i, 1);\r\n } else if (\r\n i && components[i] == '..' && components[i - 1] &&\r\n components[i - 1] != '..') {\r\n components.splice(--i, 2);\r\n } else {\r\n i++;\r\n }\r\n }\r\n return components.join('/');\r\n};\r\n\r\n\r\n/**\r\n * Provides a hook for loading a file when using Closure's goog.require() API\r\n * with goog.modules. In particular this hook is provided to support Node.js.\r\n *\r\n * @type {(function(string):string)|undefined}\r\n */\r\ngoog.global.CLOSURE_LOAD_FILE_SYNC;\r\n\r\n\r\n/**\r\n * Loads file by synchronous XHR. Should not be used in production environments.\r\n * @param {string} src Source URL.\r\n * @return {?string} File contents, or null if load failed.\r\n * @private\r\n */\r\ngoog.loadFileSync_ = function(src) {\r\n if (goog.global.CLOSURE_LOAD_FILE_SYNC) {\r\n return goog.global.CLOSURE_LOAD_FILE_SYNC(src);\r\n } else {\r\n try {\r\n /** @type {XMLHttpRequest} */\r\n var xhr = new goog.global['XMLHttpRequest']();\r\n xhr.open('get', src, false);\r\n xhr.send();\r\n // NOTE: Successful http: requests have a status of 200, but successful\r\n // file: requests may have a status of zero. Any other status, or a\r\n // thrown exception (particularly in case of file: requests) indicates\r\n // some sort of error, which we treat as a missing or unavailable file.\r\n return xhr.status == 0 || xhr.status == 200 ? xhr.responseText : null;\r\n } catch (err) {\r\n // No need to rethrow or log, since errors should show up on their own.\r\n return null;\r\n }\r\n }\r\n};\r\n\r\n\r\n/**\r\n * Lazily retrieves the transpiler and applies it to the source.\r\n * @param {string} code JS code.\r\n * @param {string} path Path to the code.\r\n * @param {string} target Language level output.\r\n * @return {string} The transpiled code.\r\n * @private\r\n */\r\ngoog.transpile_ = function(code, path, target) {\r\n var jscomp = goog.global['$jscomp'];\r\n if (!jscomp) {\r\n goog.global['$jscomp'] = jscomp = {};\r\n }\r\n var transpile = jscomp.transpile;\r\n if (!transpile) {\r\n var transpilerPath = goog.basePath + goog.TRANSPILER;\r\n var transpilerCode = goog.loadFileSync_(transpilerPath);\r\n if (transpilerCode) {\r\n // This must be executed synchronously, since by the time we know we\r\n // need it, we're about to load and write the ES6 code synchronously,\r\n // so a normal script-tag load will be too slow. Wrapped in a function\r\n // so that code is eval'd in the global scope.\r\n (function() {\r\n eval(transpilerCode + '\\n//# sourceURL=' + transpilerPath);\r\n }).call(goog.global);\r\n // Even though the transpiler is optional, if $gwtExport is found, it's\r\n // a sign the transpiler was loaded and the $jscomp.transpile *should*\r\n // be there.\r\n if (goog.global['$gwtExport'] && goog.global['$gwtExport']['$jscomp'] &&\r\n !goog.global['$gwtExport']['$jscomp']['transpile']) {\r\n throw new Error(\r\n 'The transpiler did not properly export the \"transpile\" ' +\r\n 'method. $gwtExport: ' + JSON.stringify(goog.global['$gwtExport']));\r\n }\r\n // transpile.js only exports a single $jscomp function, transpile. We\r\n // grab just that and add it to the existing definition of $jscomp which\r\n // contains the polyfills.\r\n goog.global['$jscomp'].transpile =\r\n goog.global['$gwtExport']['$jscomp']['transpile'];\r\n jscomp = goog.global['$jscomp'];\r\n transpile = jscomp.transpile;\r\n }\r\n }\r\n if (!transpile) {\r\n // The transpiler is an optional component. If it's not available then\r\n // replace it with a pass-through function that simply logs.\r\n var suffix = ' requires transpilation but no transpiler was found.';\r\n transpile = jscomp.transpile = function(code, path) {\r\n // TODO(sdh): figure out some way to get this error to show up\r\n // in test results, noting that the failure may occur in many\r\n // different ways, including in loadModule() before the test\r\n // runner even comes up.\r\n goog.logToConsole_(path + suffix);\r\n return code;\r\n };\r\n }\r\n // Note: any transpilation errors/warnings will be logged to the console.\r\n return transpile(code, path, target);\r\n};\r\n\r\n//==============================================================================\r\n// Language Enhancements\r\n//==============================================================================\r\n\r\n\r\n/**\r\n * This is a \"fixed\" version of the typeof operator. It differs from the typeof\r\n * operator in such a way that null returns 'null' and arrays return 'array'.\r\n * @param {?} value The value to get the type of.\r\n * @return {string} The name of the type.\r\n */\r\ngoog.typeOf = function(value) {\r\n var s = typeof value;\r\n if (s == 'object') {\r\n if (value) {\r\n // Check these first, so we can avoid calling Object.prototype.toString if\r\n // possible.\r\n //\r\n // IE improperly marshals typeof across execution contexts, but a\r\n // cross-context object will still return false for \"instanceof Object\".\r\n if (value instanceof Array) {\r\n return 'array';\r\n } else if (value instanceof Object) {\r\n return s;\r\n }\r\n\r\n // HACK: In order to use an Object prototype method on the arbitrary\r\n // value, the compiler requires the value be cast to type Object,\r\n // even though the ECMA spec explicitly allows it.\r\n var className = Object.prototype.toString.call(\r\n /** @type {!Object} */ (value));\r\n // In Firefox 3.6, attempting to access iframe window objects' length\r\n // property throws an NS_ERROR_FAILURE, so we need to special-case it\r\n // here.\r\n if (className == '[object Window]') {\r\n return 'object';\r\n }\r\n\r\n // We cannot always use constructor == Array or instanceof Array because\r\n // different frames have different Array objects. In IE6, if the iframe\r\n // where the array was created is destroyed, the array loses its\r\n // prototype. Then dereferencing val.splice here throws an exception, so\r\n // we can't use goog.isFunction. Calling typeof directly returns 'unknown'\r\n // so that will work. In this case, this function will return false and\r\n // most array functions will still work because the array is still\r\n // array-like (supports length and []) even though it has lost its\r\n // prototype.\r\n // Mark Miller noticed that Object.prototype.toString\r\n // allows access to the unforgeable [[Class]] property.\r\n // 15.2.4.2 Object.prototype.toString ( )\r\n // When the toString method is called, the following steps are taken:\r\n // 1. Get the [[Class]] property of this object.\r\n // 2. Compute a string value by concatenating the three strings\r\n // \"[object \", Result(1), and \"]\".\r\n // 3. Return Result(2).\r\n // and this behavior survives the destruction of the execution context.\r\n if ((className == '[object Array]' ||\r\n // In IE all non value types are wrapped as objects across window\r\n // boundaries (not iframe though) so we have to do object detection\r\n // for this edge case.\r\n typeof value.length == 'number' &&\r\n typeof value.splice != 'undefined' &&\r\n typeof value.propertyIsEnumerable != 'undefined' &&\r\n !value.propertyIsEnumerable('splice')\r\n\r\n )) {\r\n return 'array';\r\n }\r\n // HACK: There is still an array case that fails.\r\n // function ArrayImpostor() {}\r\n // ArrayImpostor.prototype = [];\r\n // var impostor = new ArrayImpostor;\r\n // this can be fixed by getting rid of the fast path\r\n // (value instanceof Array) and solely relying on\r\n // (value && Object.prototype.toString.vall(value) === '[object Array]')\r\n // but that would require many more function calls and is not warranted\r\n // unless closure code is receiving objects from untrusted sources.\r\n\r\n // IE in cross-window calls does not correctly marshal the function type\r\n // (it appears just as an object) so we cannot use just typeof val ==\r\n // 'function'. However, if the object has a call property, it is a\r\n // function.\r\n if ((className == '[object Function]' ||\r\n typeof value.call != 'undefined' &&\r\n typeof value.propertyIsEnumerable != 'undefined' &&\r\n !value.propertyIsEnumerable('call'))) {\r\n return 'function';\r\n }\r\n\r\n } else {\r\n return 'null';\r\n }\r\n\r\n } else if (s == 'function' && typeof value.call == 'undefined') {\r\n // In Safari typeof nodeList returns 'function', and on Firefox typeof\r\n // behaves similarly for HTML{Applet,Embed,Object}, Elements and RegExps. We\r\n // would like to return object for those and we can detect an invalid\r\n // function by making sure that the function object has a call method.\r\n return 'object';\r\n }\r\n return s;\r\n};\r\n\r\n\r\n/**\r\n * Returns true if the specified value is null.\r\n * @param {?} val Variable to test.\r\n * @return {boolean} Whether variable is null.\r\n */\r\ngoog.isNull = function(val) {\r\n return val === null;\r\n};\r\n\r\n\r\n/**\r\n * Returns true if the specified value is defined and not null.\r\n * @param {?} val Variable to test.\r\n * @return {boolean} Whether variable is defined and not null.\r\n */\r\ngoog.isDefAndNotNull = function(val) {\r\n // Note that undefined == null.\r\n return val != null;\r\n};\r\n\r\n\r\n/**\r\n * Returns true if the specified value is an array.\r\n * @param {?} val Variable to test.\r\n * @return {boolean} Whether variable is an array.\r\n */\r\ngoog.isArray = function(val) {\r\n return goog.typeOf(val) == 'array';\r\n};\r\n\r\n\r\n/**\r\n * Returns true if the object looks like an array. To qualify as array like\r\n * the value needs to be either a NodeList or an object with a Number length\r\n * property. Note that for this function neither strings nor functions are\r\n * considered \"array-like\".\r\n *\r\n * @param {?} val Variable to test.\r\n * @return {boolean} Whether variable is an array.\r\n */\r\ngoog.isArrayLike = function(val) {\r\n var type = goog.typeOf(val);\r\n // We do not use goog.isObject here in order to exclude function values.\r\n return type == 'array' || type == 'object' && typeof val.length == 'number';\r\n};\r\n\r\n\r\n/**\r\n * Returns true if the object looks like a Date. To qualify as Date-like the\r\n * value needs to be an object and have a getFullYear() function.\r\n * @param {?} val Variable to test.\r\n * @return {boolean} Whether variable is a like a Date.\r\n */\r\ngoog.isDateLike = function(val) {\r\n return goog.isObject(val) && typeof val.getFullYear == 'function';\r\n};\r\n\r\n\r\n/**\r\n * Returns true if the specified value is a function.\r\n * @param {?} val Variable to test.\r\n * @return {boolean} Whether variable is a function.\r\n */\r\ngoog.isFunction = function(val) {\r\n return goog.typeOf(val) == 'function';\r\n};\r\n\r\n\r\n/**\r\n * Returns true if the specified value is an object. This includes arrays and\r\n * functions.\r\n * @param {?} val Variable to test.\r\n * @return {boolean} Whether variable is an object.\r\n */\r\ngoog.isObject = function(val) {\r\n var type = typeof val;\r\n return type == 'object' && val != null || type == 'function';\r\n // return Object(val) === val also works, but is slower, especially if val is\r\n // not an object.\r\n};\r\n\r\n\r\n/**\r\n * Gets a unique ID for an object. This mutates the object so that further calls\r\n * with the same object as a parameter returns the same value. The unique ID is\r\n * guaranteed to be unique across the current session amongst objects that are\r\n * passed into `getUid`. There is no guarantee that the ID is unique or\r\n * consistent across sessions. It is unsafe to generate unique ID for function\r\n * prototypes.\r\n *\r\n * @param {Object} obj The object to get the unique ID for.\r\n * @return {number} The unique ID for the object.\r\n */\r\ngoog.getUid = function(obj) {\r\n // TODO(arv): Make the type stricter, do not accept null.\r\n\r\n // In Opera window.hasOwnProperty exists but always returns false so we avoid\r\n // using it. As a consequence the unique ID generated for BaseClass.prototype\r\n // and SubClass.prototype will be the same.\r\n return obj[goog.UID_PROPERTY_] ||\r\n (obj[goog.UID_PROPERTY_] = ++goog.uidCounter_);\r\n};\r\n\r\n\r\n/**\r\n * Whether the given object is already assigned a unique ID.\r\n *\r\n * This does not modify the object.\r\n *\r\n * @param {!Object} obj The object to check.\r\n * @return {boolean} Whether there is an assigned unique id for the object.\r\n */\r\ngoog.hasUid = function(obj) {\r\n return !!obj[goog.UID_PROPERTY_];\r\n};\r\n\r\n\r\n/**\r\n * Removes the unique ID from an object. This is useful if the object was\r\n * previously mutated using `goog.getUid` in which case the mutation is\r\n * undone.\r\n * @param {Object} obj The object to remove the unique ID field from.\r\n */\r\ngoog.removeUid = function(obj) {\r\n // TODO(arv): Make the type stricter, do not accept null.\r\n\r\n // In IE, DOM nodes are not instances of Object and throw an exception if we\r\n // try to delete. Instead we try to use removeAttribute.\r\n if (obj !== null && 'removeAttribute' in obj) {\r\n obj.removeAttribute(goog.UID_PROPERTY_);\r\n }\r\n\r\n try {\r\n delete obj[goog.UID_PROPERTY_];\r\n } catch (ex) {\r\n }\r\n};\r\n\r\n\r\n/**\r\n * Name for unique ID property. Initialized in a way to help avoid collisions\r\n * with other closure JavaScript on the same page.\r\n * @type {string}\r\n * @private\r\n */\r\ngoog.UID_PROPERTY_ = 'closure_uid_' + ((Math.random() * 1e9) >>> 0);\r\n\r\n\r\n/**\r\n * Counter for UID.\r\n * @type {number}\r\n * @private\r\n */\r\ngoog.uidCounter_ = 0;\r\n\r\n\r\n/**\r\n * Adds a hash code field to an object. The hash code is unique for the\r\n * given object.\r\n * @param {Object} obj The object to get the hash code for.\r\n * @return {number} The hash code for the object.\r\n * @deprecated Use goog.getUid instead.\r\n */\r\ngoog.getHashCode = goog.getUid;\r\n\r\n\r\n/**\r\n * Removes the hash code field from an object.\r\n * @param {Object} obj The object to remove the field from.\r\n * @deprecated Use goog.removeUid instead.\r\n */\r\ngoog.removeHashCode = goog.removeUid;\r\n\r\n\r\n/**\r\n * Clones a value. The input may be an Object, Array, or basic type. Objects and\r\n * arrays will be cloned recursively.\r\n *\r\n * WARNINGS:\r\n * <code>goog.cloneObject</code> does not detect reference loops. Objects that\r\n * refer to themselves will cause infinite recursion.\r\n *\r\n * <code>goog.cloneObject</code> is unaware of unique identifiers, and copies\r\n * UIDs created by <code>getUid</code> into cloned results.\r\n *\r\n * @param {*} obj The value to clone.\r\n * @return {*} A clone of the input value.\r\n * @deprecated goog.cloneObject is unsafe. Prefer the goog.object methods.\r\n */\r\ngoog.cloneObject = function(obj) {\r\n var type = goog.typeOf(obj);\r\n if (type == 'object' || type == 'array') {\r\n if (typeof obj.clone === 'function') {\r\n return obj.clone();\r\n }\r\n var clone = type == 'array' ? [] : {};\r\n for (var key in obj) {\r\n clone[key] = goog.cloneObject(obj[key]);\r\n }\r\n return clone;\r\n }\r\n\r\n return obj;\r\n};\r\n\r\n\r\n/**\r\n * A native implementation of goog.bind.\r\n * @param {?function(this:T, ...)} fn A function to partially apply.\r\n * @param {T} selfObj Specifies the object which this should point to when the\r\n * function is run.\r\n * @param {...*} var_args Additional arguments that are partially applied to the\r\n * function.\r\n * @return {!Function} A partially-applied form of the function goog.bind() was\r\n * invoked as a method of.\r\n * @template T\r\n * @private\r\n */\r\ngoog.bindNative_ = function(fn, selfObj, var_args) {\r\n return /** @type {!Function} */ (fn.call.apply(fn.bind, arguments));\r\n};\r\n\r\n\r\n/**\r\n * A pure-JS implementation of goog.bind.\r\n * @param {?function(this:T, ...)} fn A function to partially apply.\r\n * @param {T} selfObj Specifies the object which this should point to when the\r\n * function is run.\r\n * @param {...*} var_args Additional arguments that are partially applied to the\r\n * function.\r\n * @return {!Function} A partially-applied form of the function goog.bind() was\r\n * invoked as a method of.\r\n * @template T\r\n * @private\r\n */\r\ngoog.bindJs_ = function(fn, selfObj, var_args) {\r\n if (!fn) {\r\n throw new Error();\r\n }\r\n\r\n if (arguments.length > 2) {\r\n var boundArgs = Array.prototype.slice.call(arguments, 2);\r\n return function() {\r\n // Prepend the bound arguments to the current arguments.\r\n var newArgs = Array.prototype.slice.call(arguments);\r\n Array.prototype.unshift.apply(newArgs, boundArgs);\r\n return fn.apply(selfObj, newArgs);\r\n };\r\n\r\n } else {\r\n return function() {\r\n return fn.apply(selfObj, arguments);\r\n };\r\n }\r\n};\r\n\r\n\r\n/**\r\n * Partially applies this function to a particular 'this object' and zero or\r\n * more arguments. The result is a new function with some arguments of the first\r\n * function pre-filled and the value of this 'pre-specified'.\r\n *\r\n * Remaining arguments specified at call-time are appended to the pre-specified\r\n * ones.\r\n *\r\n * Also see: {@link #partial}.\r\n *\r\n * Usage:\r\n * <pre>var barMethBound = goog.bind(myFunction, myObj, 'arg1', 'arg2');\r\n * barMethBound('arg3', 'arg4');</pre>\r\n *\r\n * @param {?function(this:T, ...)} fn A function to partially apply.\r\n * @param {T} selfObj Specifies the object which this should point to when the\r\n * function is run.\r\n * @param {...*} var_args Additional arguments that are partially applied to the\r\n * function.\r\n * @return {!Function} A partially-applied form of the function goog.bind() was\r\n * invoked as a method of.\r\n * @template T\r\n * @suppress {deprecated} See above.\r\n */\r\ngoog.bind = function(fn, selfObj, var_args) {\r\n // TODO(nicksantos): narrow the type signature.\r\n if (Function.prototype.bind &&\r\n // NOTE(nicksantos): Somebody pulled base.js into the default Chrome\r\n // extension environment. This means that for Chrome extensions, they get\r\n // the implementation of Function.prototype.bind that calls goog.bind\r\n // instead of the native one. Even worse, we don't want to introduce a\r\n // circular dependency between goog.bind and Function.prototype.bind, so\r\n // we have to hack this to make sure it works correctly.\r\n Function.prototype.bind.toString().indexOf('native code') != -1) {\r\n goog.bind = goog.bindNative_;\r\n } else {\r\n goog.bind = goog.bindJs_;\r\n }\r\n return goog.bind.apply(null, arguments);\r\n};\r\n\r\n\r\n/**\r\n * Like goog.bind(), except that a 'this object' is not required. Useful when\r\n * the target function is already bound.\r\n *\r\n * Usage:\r\n * var g = goog.partial(f, arg1, arg2);\r\n * g(arg3, arg4);\r\n *\r\n * @param {Function} fn A function to partially apply.\r\n * @param {...*} var_args Additional arguments that are partially applied to fn.\r\n * @return {!Function} A partially-applied form of the function goog.partial()\r\n * was invoked as a method of.\r\n */\r\ngoog.partial = function(fn, var_args) {\r\n var args = Array.prototype.slice.call(arguments, 1);\r\n return function() {\r\n // Clone the array (with slice()) and append additional arguments\r\n // to the existing arguments.\r\n var newArgs = args.slice();\r\n newArgs.push.apply(newArgs, arguments);\r\n return fn.apply(/** @type {?} */ (this), newArgs);\r\n };\r\n};\r\n\r\n\r\n/**\r\n * Copies all the members of a source object to a target object. This method\r\n * does not work on all browsers for all objects that contain keys such as\r\n * toString or hasOwnProperty. Use goog.object.extend for this purpose.\r\n * @param {Object} target Target.\r\n * @param {Object} source Source.\r\n */\r\ngoog.mixin = function(target, source) {\r\n for (var x in source) {\r\n target[x] = source[x];\r\n }\r\n\r\n // For IE7 or lower, the for-in-loop does not contain any properties that are\r\n // not enumerable on the prototype object (for example, isPrototypeOf from\r\n // Object.prototype) but also it will not include 'replace' on objects that\r\n // extend String and change 'replace' (not that it is common for anyone to\r\n // extend anything except Object).\r\n};\r\n\r\n\r\n/**\r\n * @return {number} An integer value representing the number of milliseconds\r\n * between midnight, January 1, 1970 and the current time.\r\n */\r\ngoog.now = (goog.TRUSTED_SITE && Date.now) || (function() {\r\n // Unary plus operator converts its operand to a number which in\r\n // the case of\r\n // a date is done by calling getTime().\r\n return +new Date();\r\n });\r\n\r\n\r\n/**\r\n * Evals JavaScript in the global scope. In IE this uses execScript, other\r\n * browsers use goog.global.eval. If goog.global.eval does not evaluate in the\r\n * global scope (for example, in Safari), appends a script tag instead.\r\n * Throws an exception if neither execScript or eval is defined.\r\n * @param {string} script JavaScript string.\r\n */\r\ngoog.globalEval = function(script) {\r\n if (goog.global.execScript) {\r\n goog.global.execScript(script, 'JavaScript');\r\n } else if (goog.global.eval) {\r\n // Test to see if eval works\r\n if (goog.evalWorksForGlobals_ == null) {\r\n try {\r\n goog.global.eval('var _evalTest_ = 1;');\r\n } catch (ignore) {\r\n }\r\n if (typeof goog.global['_evalTest_'] != 'undefined') {\r\n try {\r\n delete goog.global['_evalTest_'];\r\n } catch (ignore) {\r\n // Microsoft edge fails the deletion above in strict mode.\r\n }\r\n goog.evalWorksForGlobals_ = true;\r\n } else {\r\n goog.evalWorksForGlobals_ = false;\r\n }\r\n }\r\n\r\n if (goog.evalWorksForGlobals_) {\r\n goog.global.eval(script);\r\n } else {\r\n /** @type {!Document} */\r\n var doc = goog.global.document;\r\n var scriptElt =\r\n /** @type {!HTMLScriptElement} */ (doc.createElement('SCRIPT'));\r\n scriptElt.type = 'text/javascript';\r\n scriptElt.defer = false;\r\n // Note(user): can't use .innerHTML since \"t('<test>')\" will fail and\r\n // .text doesn't work in Safari 2. Therefore we append a text node.\r\n scriptElt.appendChild(doc.createTextNode(script));\r\n doc.head.appendChild(scriptElt);\r\n doc.head.removeChild(scriptElt);\r\n }\r\n } else {\r\n throw new Error('goog.globalEval not available');\r\n }\r\n};\r\n\r\n\r\n/**\r\n * Indicates whether or not we can call 'eval' directly to eval code in the\r\n * global scope. Set to a Boolean by the first call to goog.globalEval (which\r\n * empirically tests whether eval works for globals). @see goog.globalEval\r\n * @type {?boolean}\r\n * @private\r\n */\r\ngoog.evalWorksForGlobals_ = null;\r\n\r\n\r\n/**\r\n * Optional map of CSS class names to obfuscated names used with\r\n * goog.getCssName().\r\n * @private {!Object<string, string>|undefined}\r\n * @see goog.setCssNameMapping\r\n */\r\ngoog.cssNameMapping_;\r\n\r\n\r\n/**\r\n * Optional obfuscation style for CSS class names. Should be set to either\r\n * 'BY_WHOLE' or 'BY_PART' if defined.\r\n * @type {string|undefined}\r\n * @private\r\n * @see goog.setCssNameMapping\r\n */\r\ngoog.cssNameMappingStyle_;\r\n\r\n\r\n\r\n/**\r\n * A hook for modifying the default behavior goog.getCssName. The function\r\n * if present, will receive the standard output of the goog.getCssName as\r\n * its input.\r\n *\r\n * @type {(function(string):string)|undefined}\r\n */\r\ngoog.global.CLOSURE_CSS_NAME_MAP_FN;\r\n\r\n\r\n/**\r\n * Handles strings that are intended to be used as CSS class names.\r\n *\r\n * This function works in tandem with @see goog.setCssNameMapping.\r\n *\r\n * Without any mapping set, the arguments are simple joined with a hyphen and\r\n * passed through unaltered.\r\n *\r\n * When there is a mapping, there are two possible styles in which these\r\n * mappings are used. In the BY_PART style, each part (i.e. in between hyphens)\r\n * of the passed in css name is rewritten according to the map. In the BY_WHOLE\r\n * style, the full css name is looked up in the map directly. If a rewrite is\r\n * not specified by the map, the compiler will output a warning.\r\n *\r\n * When the mapping is passed to the compiler, it will replace calls to\r\n * goog.getCssName with the strings from the mapping, e.g.\r\n * var x = goog.getCssName('foo');\r\n * var y = goog.getCssName(this.baseClass, 'active');\r\n * becomes:\r\n * var x = 'foo';\r\n * var y = this.baseClass + '-active';\r\n *\r\n * If one argument is passed it will be processed, if two are passed only the\r\n * modifier will be processed, as it is assumed the first argument was generated\r\n * as a result of calling goog.getCssName.\r\n *\r\n * @param {string} className The class name.\r\n * @param {string=} opt_modifier A modifier to be appended to the class name.\r\n * @return {string} The class name or the concatenation of the class name and\r\n * the modifier.\r\n */\r\ngoog.getCssName = function(className, opt_modifier) {\r\n // String() is used for compatibility with compiled soy where the passed\r\n // className can be non-string objects.\r\n if (String(className).charAt(0) == '.') {\r\n throw new Error(\r\n 'className passed in goog.getCssName must not start with \".\".' +\r\n ' You passed: ' + className);\r\n }\r\n\r\n var getMapping = function(cssName) {\r\n return goog.cssNameMapping_[cssName] || cssName;\r\n };\r\n\r\n var renameByParts = function(cssName) {\r\n // Remap all the parts individually.\r\n var parts = cssName.split('-');\r\n var mapped = [];\r\n for (var i = 0; i < parts.length; i++) {\r\n mapped.push(getMapping(parts[i]));\r\n }\r\n return mapped.join('-');\r\n };\r\n\r\n var rename;\r\n if (goog.cssNameMapping_) {\r\n rename =\r\n goog.cssNameMappingStyle_ == 'BY_WHOLE' ? getMapping : renameByParts;\r\n } else {\r\n rename = function(a) {\r\n return a;\r\n };\r\n }\r\n\r\n var result =\r\n opt_modifier ? className + '-' + rename(opt_modifier) : rename(className);\r\n\r\n // The special CLOSURE_CSS_NAME_MAP_FN allows users to specify further\r\n // processing of the class name.\r\n if (goog.global.CLOSURE_CSS_NAME_MAP_FN) {\r\n return goog.global.CLOSURE_CSS_NAME_MAP_FN(result);\r\n }\r\n\r\n return result;\r\n};\r\n\r\n\r\n/**\r\n * Sets the map to check when returning a value from goog.getCssName(). Example:\r\n * <pre>\r\n * goog.setCssNameMapping({\r\n * \"goog\": \"a\",\r\n * \"disabled\": \"b\",\r\n * });\r\n *\r\n * var x = goog.getCssName('goog');\r\n * // The following evaluates to: \"a a-b\".\r\n * goog.getCssName('goog') + ' ' + goog.getCssName(x, 'disabled')\r\n * </pre>\r\n * When declared as a map of string literals to string literals, the JSCompiler\r\n * will replace all calls to goog.getCssName() using the supplied map if the\r\n * --process_closure_primitives flag is set.\r\n *\r\n * @param {!Object} mapping A map of strings to strings where keys are possible\r\n * arguments to goog.getCssName() and values are the corresponding values\r\n * that should be returned.\r\n * @param {string=} opt_style The style of css name mapping. There are two valid\r\n * options: 'BY_PART', and 'BY_WHOLE'.\r\n * @see goog.getCssName for a description.\r\n */\r\ngoog.setCssNameMapping = function(mapping, opt_style) {\r\n goog.cssNameMapping_ = mapping;\r\n goog.cssNameMappingStyle_ = opt_style;\r\n};\r\n\r\n\r\n/**\r\n * To use CSS renaming in compiled mode, one of the input files should have a\r\n * call to goog.setCssNameMapping() with an object literal that the JSCompiler\r\n * can extract and use to replace all calls to goog.getCssName(). In uncompiled\r\n * mode, JavaScript code should be loaded before this base.js file that declares\r\n * a global variable, CLOSURE_CSS_NAME_MAPPING, which is used below. This is\r\n * to ensure that the mapping is loaded before any calls to goog.getCssName()\r\n * are made in uncompiled mode.\r\n *\r\n * A hook for overriding the CSS name mapping.\r\n * @type {!Object<string, string>|undefined}\r\n */\r\ngoog.global.CLOSURE_CSS_NAME_MAPPING;\r\n\r\n\r\nif (!COMPILED && goog.global.CLOSURE_CSS_NAME_MAPPING) {\r\n // This does not call goog.setCssNameMapping() because the JSCompiler\r\n // requires that goog.setCssNameMapping() be called with an object literal.\r\n goog.cssNameMapping_ = goog.global.CLOSURE_CSS_NAME_MAPPING;\r\n}\r\n\r\n\r\n/**\r\n * Gets a localized message.\r\n *\r\n * This function is a compiler primitive. If you give the compiler a localized\r\n * message bundle, it will replace the string at compile-time with a localized\r\n * version, and expand goog.getMsg call to a concatenated string.\r\n *\r\n * Messages must be initialized in the form:\r\n * <code>\r\n * var MSG_NAME = goog.getMsg('Hello {$placeholder}', {'placeholder': 'world'});\r\n * </code>\r\n *\r\n * This function produces a string which should be treated as plain text. Use\r\n * {@link goog.html.SafeHtmlFormatter} in conjunction with goog.getMsg to\r\n * produce SafeHtml.\r\n *\r\n * @param {string} str Translatable string, places holders in the form {$foo}.\r\n * @param {Object<string, string>=} opt_values Maps place holder name to value.\r\n * @return {string} message with placeholders filled.\r\n */\r\ngoog.getMsg = function(str, opt_values) {\r\n if (opt_values) {\r\n str = str.replace(/\\{\\$([^}]+)}/g, function(match, key) {\r\n return (opt_values != null && key in opt_values) ? opt_values[key] :\r\n match;\r\n });\r\n }\r\n return str;\r\n};\r\n\r\n\r\n/**\r\n * Gets a localized message. If the message does not have a translation, gives a\r\n * fallback message.\r\n *\r\n * This is useful when introducing a new message that has not yet been\r\n * translated into all languages.\r\n *\r\n * This function is a compiler primitive. Must be used in the form:\r\n * <code>var x = goog.getMsgWithFallback(MSG_A, MSG_B);</code>\r\n * where MSG_A and MSG_B were initialized with goog.getMsg.\r\n *\r\n * @param {string} a The preferred message.\r\n * @param {string} b The fallback message.\r\n * @return {string} The best translated message.\r\n */\r\ngoog.getMsgWithFallback = function(a, b) {\r\n return a;\r\n};\r\n\r\n\r\n/**\r\n * Exposes an unobfuscated global namespace path for the given object.\r\n * Note that fields of the exported object *will* be obfuscated, unless they are\r\n * exported in turn via this function or goog.exportProperty.\r\n *\r\n * Also handy for making public items that are defined in anonymous closures.\r\n *\r\n * ex. goog.exportSymbol('public.path.Foo', Foo);\r\n *\r\n * ex. goog.exportSymbol('public.path.Foo.staticFunction', Foo.staticFunction);\r\n * public.path.Foo.staticFunction();\r\n *\r\n * ex. goog.exportSymbol('public.path.Foo.prototype.myMethod',\r\n * Foo.prototype.myMethod);\r\n * new public.path.Foo().myMethod();\r\n *\r\n * @param {string} publicPath Unobfuscated name to export.\r\n * @param {*} object Object the name should point to.\r\n * @param {Object=} opt_objectToExportTo The object to add the path to; default\r\n * is goog.global.\r\n */\r\ngoog.exportSymbol = function(publicPath, object, opt_objectToExportTo) {\r\n goog.exportPath_(publicPath, object, opt_objectToExportTo);\r\n};\r\n\r\n\r\n/**\r\n * Exports a property unobfuscated into the object's namespace.\r\n * ex. goog.exportProperty(Foo, 'staticFunction', Foo.staticFunction);\r\n * ex. goog.exportProperty(Foo.prototype, 'myMethod', Foo.prototype.myMethod);\r\n * @param {Object} object Object whose static property is being exported.\r\n * @param {string} publicName Unobfuscated name to export.\r\n * @param {*} symbol Object the name should point to.\r\n */\r\ngoog.exportProperty = function(object, publicName, symbol) {\r\n object[publicName] = symbol;\r\n};\r\n\r\n\r\n/**\r\n * Inherit the prototype methods from one constructor into another.\r\n *\r\n * Usage:\r\n * <pre>\r\n * function ParentClass(a, b) { }\r\n * ParentClass.prototype.foo = function(a) { };\r\n *\r\n * function ChildClass(a, b, c) {\r\n * ChildClass.base(this, 'constructor', a, b);\r\n * }\r\n * goog.inherits(ChildClass, ParentClass);\r\n *\r\n * var child = new ChildClass('a', 'b', 'see');\r\n * child.foo(); // This works.\r\n * </pre>\r\n *\r\n * @param {!Function} childCtor Child class.\r\n * @param {!Function} parentCtor Parent class.\r\n * @suppress {strictMissingProperties} superClass_ and base is not defined on\r\n * Function.\r\n */\r\ngoog.inherits = function(childCtor, parentCtor) {\r\n /** @constructor */\r\n function tempCtor() {}\r\n tempCtor.prototype = parentCtor.prototype;\r\n childCtor.superClass_ = parentCtor.prototype;\r\n childCtor.prototype = new tempCtor();\r\n /** @override */\r\n childCtor.prototype.constructor = childCtor;\r\n\r\n /**\r\n * Calls superclass constructor/method.\r\n *\r\n * This function is only available if you use goog.inherits to\r\n * express inheritance relationships between classes.\r\n *\r\n * NOTE: This is a replacement for goog.base and for superClass_\r\n * property defined in childCtor.\r\n *\r\n * @param {!Object} me Should always be \"this\".\r\n * @param {string} methodName The method name to call. Calling\r\n * superclass constructor can be done with the special string\r\n * 'constructor'.\r\n * @param {...*} var_args The arguments to pass to superclass\r\n * method/constructor.\r\n * @return {*} The return value of the superclass method/constructor.\r\n */\r\n childCtor.base = function(me, methodName, var_args) {\r\n // Copying using loop to avoid deop due to passing arguments object to\r\n // function. This is faster in many JS engines as of late 2014.\r\n var args = new Array(arguments.length - 2);\r\n for (var i = 2; i < arguments.length; i++) {\r\n args[i - 2] = arguments[i];\r\n }\r\n return parentCtor.prototype[methodName].apply(me, args);\r\n };\r\n};\r\n\r\n\r\n/**\r\n * Call up to the superclass.\r\n *\r\n * If this is called from a constructor, then this calls the superclass\r\n * constructor with arguments 1-N.\r\n *\r\n * If this is called from a prototype method, then you must pass the name of the\r\n * method as the second argument to this function. If you do not, you will get a\r\n * runtime error. This calls the superclass' method with arguments 2-N.\r\n *\r\n * This function only works if you use goog.inherits to express inheritance\r\n * relationships between your classes.\r\n *\r\n * This function is a compiler primitive. At compile-time, the compiler will do\r\n * macro expansion to remove a lot of the extra overhead that this function\r\n * introduces. The compiler will also enforce a lot of the assumptions that this\r\n * function makes, and treat it as a compiler error if you break them.\r\n *\r\n * @param {!Object} me Should always be \"this\".\r\n * @param {*=} opt_methodName The method name if calling a super method.\r\n * @param {...*} var_args The rest of the arguments.\r\n * @return {*} The return value of the superclass method.\r\n * @suppress {es5Strict} This method can not be used in strict mode, but\r\n * all Closure Library consumers must depend on this file.\r\n * @deprecated goog.base is not strict mode compatible. Prefer the static\r\n * \"base\" method added to the constructor by goog.inherits\r\n * or ES6 classes and the \"super\" keyword.\r\n */\r\ngoog.base = function(me, opt_methodName, var_args) {\r\n var caller = arguments.callee.caller;\r\n\r\n if (goog.STRICT_MODE_COMPATIBLE || (goog.DEBUG && !caller)) {\r\n throw new Error(\r\n 'arguments.caller not defined. goog.base() cannot be used ' +\r\n 'with strict mode code. See ' +\r\n 'http://www.ecma-international.org/ecma-262/5.1/#sec-C');\r\n }\r\n\r\n if (typeof caller.superClass_ !== 'undefined') {\r\n // Copying using loop to avoid deop due to passing arguments object to\r\n // function. This is faster in many JS engines as of late 2014.\r\n var ctorArgs = new Array(arguments.length - 1);\r\n for (var i = 1; i < arguments.length; i++) {\r\n ctorArgs[i - 1] = arguments[i];\r\n }\r\n // This is a constructor. Call the superclass constructor.\r\n return /** @type {!Function} */ (caller.superClass_)\r\n .constructor.apply(me, ctorArgs);\r\n }\r\n\r\n if (typeof opt_methodName != 'string' && typeof opt_methodName != 'symbol') {\r\n throw new Error(\r\n 'method names provided to goog.base must be a string or a symbol');\r\n }\r\n\r\n // Copying using loop to avoid deop due to passing arguments object to\r\n // function. This is faster in many JS engines as of late 2014.\r\n var args = new Array(arguments.length - 2);\r\n for (var i = 2; i < arguments.length; i++) {\r\n args[i - 2] = arguments[i];\r\n }\r\n var foundCaller = false;\r\n for (var ctor = me.constructor; ctor;\r\n ctor = ctor.superClass_ && ctor.superClass_.constructor) {\r\n if (ctor.prototype[opt_methodName] === caller) {\r\n foundCaller = true;\r\n } else if (foundCaller) {\r\n return ctor.prototype[opt_methodName].apply(me, args);\r\n }\r\n }\r\n\r\n // If we did not find the caller in the prototype chain, then one of two\r\n // things happened:\r\n // 1) The caller is an instance method.\r\n // 2) This method was not called by the right caller.\r\n if (me[opt_methodName] === caller) {\r\n return me.constructor.prototype[opt_methodName].apply(me, args);\r\n } else {\r\n throw new Error(\r\n 'goog.base called from a method of one name ' +\r\n 'to a method of a different name');\r\n }\r\n};\r\n\r\n\r\n/**\r\n * Allow for aliasing within scope functions. This function exists for\r\n * uncompiled code - in compiled code the calls will be inlined and the aliases\r\n * applied. In uncompiled code the function is simply run since the aliases as\r\n * written are valid JavaScript.\r\n *\r\n *\r\n * @param {function()} fn Function to call. This function can contain aliases\r\n * to namespaces (e.g. \"var dom = goog.dom\") or classes\r\n * (e.g. \"var Timer = goog.Timer\").\r\n */\r\ngoog.scope = function(fn) {\r\n if (goog.isInModuleLoader_()) {\r\n throw new Error('goog.scope is not supported within a module.');\r\n }\r\n fn.call(goog.global);\r\n};\r\n\r\n\r\n/*\r\n * To support uncompiled, strict mode bundles that use eval to divide source\r\n * like so:\r\n * eval('someSource;//# sourceUrl sourcefile.js');\r\n * We need to export the globally defined symbols \"goog\" and \"COMPILED\".\r\n * Exporting \"goog\" breaks the compiler optimizations, so we required that\r\n * be defined externally.\r\n * NOTE: We don't use goog.exportSymbol here because we don't want to trigger\r\n * extern generation when that compiler option is enabled.\r\n */\r\nif (!COMPILED) {\r\n goog.global['COMPILED'] = COMPILED;\r\n}\r\n\r\n\r\n//==============================================================================\r\n// goog.defineClass implementation\r\n//==============================================================================\r\n\r\n\r\n/**\r\n * Creates a restricted form of a Closure \"class\":\r\n * - from the compiler's perspective, the instance returned from the\r\n * constructor is sealed (no new properties may be added). This enables\r\n * better checks.\r\n * - the compiler will rewrite this definition to a form that is optimal\r\n * for type checking and optimization (initially this will be a more\r\n * traditional form).\r\n *\r\n * @param {Function} superClass The superclass, Object or null.\r\n * @param {goog.defineClass.ClassDescriptor} def\r\n * An object literal describing\r\n * the class. It may have the following properties:\r\n * \"constructor\": the constructor function\r\n * \"statics\": an object literal containing methods to add to the constructor\r\n * as \"static\" methods or a function that will receive the constructor\r\n * function as its only parameter to which static properties can\r\n * be added.\r\n * all other properties are added to the prototype.\r\n * @return {!Function} The class constructor.\r\n */\r\ngoog.defineClass = function(superClass, def) {\r\n // TODO(johnlenz): consider making the superClass an optional parameter.\r\n var constructor = def.constructor;\r\n var statics = def.statics;\r\n // Wrap the constructor prior to setting up the prototype and static methods.\r\n if (!constructor || constructor == Object.prototype.constructor) {\r\n constructor = function() {\r\n throw new Error(\r\n 'cannot instantiate an interface (no constructor defined).');\r\n };\r\n }\r\n\r\n var cls = goog.defineClass.createSealingConstructor_(constructor, superClass);\r\n if (superClass) {\r\n goog.inherits(cls, superClass);\r\n }\r\n\r\n // Remove all the properties that should not be copied to the prototype.\r\n delete def.constructor;\r\n delete def.statics;\r\n\r\n goog.defineClass.applyProperties_(cls.prototype, def);\r\n if (statics != null) {\r\n if (statics instanceof Function) {\r\n statics(cls);\r\n } else {\r\n goog.defineClass.applyProperties_(cls, statics);\r\n }\r\n }\r\n\r\n return cls;\r\n};\r\n\r\n\r\n/**\r\n * @typedef {{\r\n * constructor: (!Function|undefined),\r\n * statics: (Object|undefined|function(Function):void)\r\n * }}\r\n */\r\ngoog.defineClass.ClassDescriptor;\r\n\r\n\r\n/**\r\n * @define {boolean} Whether the instances returned by goog.defineClass should\r\n * be sealed when possible.\r\n *\r\n * When sealing is disabled the constructor function will not be wrapped by\r\n * goog.defineClass, making it incompatible with ES6 class methods.\r\n */\r\ngoog.defineClass.SEAL_CLASS_INSTANCES =\r\n goog.define('goog.defineClass.SEAL_CLASS_INSTANCES', goog.DEBUG);\r\n\r\n\r\n/**\r\n * If goog.defineClass.SEAL_CLASS_INSTANCES is enabled and Object.seal is\r\n * defined, this function will wrap the constructor in a function that seals the\r\n * results of the provided constructor function.\r\n *\r\n * @param {!Function} ctr The constructor whose results maybe be sealed.\r\n * @param {Function} superClass The superclass constructor.\r\n * @return {!Function} The replacement constructor.\r\n * @private\r\n */\r\ngoog.defineClass.createSealingConstructor_ = function(ctr, superClass) {\r\n if (!goog.defineClass.SEAL_CLASS_INSTANCES) {\r\n // Do now wrap the constructor when sealing is disabled. Angular code\r\n // depends on this for injection to work properly.\r\n return ctr;\r\n }\r\n\r\n // Compute whether the constructor is sealable at definition time, rather\r\n // than when the instance is being constructed.\r\n var superclassSealable = !goog.defineClass.isUnsealable_(superClass);\r\n\r\n /**\r\n * @this {Object}\r\n * @return {?}\r\n */\r\n var wrappedCtr = function() {\r\n // Don't seal an instance of a subclass when it calls the constructor of\r\n // its super class as there is most likely still setup to do.\r\n var instance = ctr.apply(this, arguments) || this;\r\n instance[goog.UID_PROPERTY_] = instance[goog.UID_PROPERTY_];\r\n\r\n if (this.constructor === wrappedCtr && superclassSealable &&\r\n Object.seal instanceof Function) {\r\n Object.seal(instance);\r\n }\r\n return instance;\r\n };\r\n\r\n return wrappedCtr;\r\n};\r\n\r\n\r\n/**\r\n * @param {Function} ctr The constructor to test.\r\n * @return {boolean} Whether the constructor has been tagged as unsealable\r\n * using goog.tagUnsealableClass.\r\n * @private\r\n */\r\ngoog.defineClass.isUnsealable_ = function(ctr) {\r\n return ctr && ctr.prototype &&\r\n ctr.prototype[goog.UNSEALABLE_CONSTRUCTOR_PROPERTY_];\r\n};\r\n\r\n\r\n// TODO(johnlenz): share these values with the goog.object\r\n/**\r\n * The names of the fields that are defined on Object.prototype.\r\n * @type {!Array<string>}\r\n * @private\r\n * @const\r\n */\r\ngoog.defineClass.OBJECT_PROTOTYPE_FIELDS_ = [\r\n 'constructor', 'hasOwnProperty', 'isPrototypeOf', 'propertyIsEnumerable',\r\n 'toLocaleString', 'toString', 'valueOf'\r\n];\r\n\r\n\r\n// TODO(johnlenz): share this function with the goog.object\r\n/**\r\n * @param {!Object} target The object to add properties to.\r\n * @param {!Object} source The object to copy properties from.\r\n * @private\r\n */\r\ngoog.defineClass.applyProperties_ = function(target, source) {\r\n // TODO(johnlenz): update this to support ES5 getters/setters\r\n\r\n var key;\r\n for (key in source) {\r\n if (Object.prototype.hasOwnProperty.call(source, key)) {\r\n target[key] = source[key];\r\n }\r\n }\r\n\r\n // For IE the for-in-loop does not contain any properties that are not\r\n // enumerable on the prototype object (for example isPrototypeOf from\r\n // Object.prototype) and it will also not include 'replace' on objects that\r\n // extend String and change 'replace' (not that it is common for anyone to\r\n // extend anything except Object).\r\n for (var i = 0; i < goog.defineClass.OBJECT_PROTOTYPE_FIELDS_.length; i++) {\r\n key = goog.defineClass.OBJECT_PROTOTYPE_FIELDS_[i];\r\n if (Object.prototype.hasOwnProperty.call(source, key)) {\r\n target[key] = source[key];\r\n }\r\n }\r\n};\r\n\r\n\r\n/**\r\n * Sealing classes breaks the older idiom of assigning properties on the\r\n * prototype rather than in the constructor. As such, goog.defineClass\r\n * must not seal subclasses of these old-style classes until they are fixed.\r\n * Until then, this marks a class as \"broken\", instructing defineClass\r\n * not to seal subclasses.\r\n * @param {!Function} ctr The legacy constructor to tag as unsealable.\r\n */\r\ngoog.tagUnsealableClass = function(ctr) {\r\n if (!COMPILED && goog.defineClass.SEAL_CLASS_INSTANCES) {\r\n ctr.prototype[goog.UNSEALABLE_CONSTRUCTOR_PROPERTY_] = true;\r\n }\r\n};\r\n\r\n\r\n/**\r\n * Name for unsealable tag property.\r\n * @const @private {string}\r\n */\r\ngoog.UNSEALABLE_CONSTRUCTOR_PROPERTY_ = 'goog_defineClass_legacy_unsealable';\r\n\r\n\r\n// There's a bug in the compiler where without collapse properties the\r\n// Closure namespace defines do not guard code correctly. To help reduce code\r\n// size also check for !COMPILED even though it redundant until this is fixed.\r\nif (!COMPILED && goog.DEPENDENCIES_ENABLED) {\r\n\r\n /**\r\n * Tries to detect whether is in the context of an HTML document.\r\n * @return {boolean} True if it looks like HTML document.\r\n * @private\r\n */\r\n goog.inHtmlDocument_ = function() {\r\n /** @type {!Document} */\r\n var doc = goog.global.document;\r\n return doc != null && 'write' in doc; // XULDocument misses write.\r\n };\r\n\r\n\r\n /**\r\n * We'd like to check for if the document readyState is 'loading'; however\r\n * there are bugs on IE 10 and below where the readyState being anything other\r\n * than 'complete' is not reliable.\r\n * @return {boolean}\r\n * @private\r\n */\r\n goog.isDocumentLoading_ = function() {\r\n // attachEvent is available on IE 6 thru 10 only, and thus can be used to\r\n // detect those browsers.\r\n /** @type {!HTMLDocument} */\r\n var doc = goog.global.document;\r\n return doc.attachEvent ? doc.readyState != 'complete' :\r\n doc.readyState == 'loading';\r\n };\r\n\r\n\r\n /**\r\n * Tries to detect the base path of base.js script that bootstraps Closure.\r\n * @private\r\n */\r\n goog.findBasePath_ = function() {\r\n if (goog.isDef(goog.global.CLOSURE_BASE_PATH) &&\r\n // Anti DOM-clobbering runtime check (b/37736576).\r\n goog.isString(goog.global.CLOSURE_BASE_PATH)) {\r\n goog.basePath = goog.global.CLOSURE_BASE_PATH;\r\n return;\r\n } else if (!goog.inHtmlDocument_()) {\r\n return;\r\n }\r\n /** @type {!Document} */\r\n var doc = goog.global.document;\r\n // If we have a currentScript available, use it exclusively.\r\n var currentScript = doc.currentScript;\r\n if (currentScript) {\r\n var scripts = [currentScript];\r\n } else {\r\n var scripts = doc.getElementsByTagName('SCRIPT');\r\n }\r\n // Search backwards since the current script is in almost all cases the one\r\n // that has base.js.\r\n for (var i = scripts.length - 1; i >= 0; --i) {\r\n var script = /** @type {!HTMLScriptElement} */ (scripts[i]);\r\n var src = script.src;\r\n var qmark = src.lastIndexOf('?');\r\n var l = qmark == -1 ? src.length : qmark;\r\n if (src.substr(l - 7, 7) == 'base.js') {\r\n goog.basePath = src.substr(0, l - 7);\r\n return;\r\n }\r\n }\r\n };\r\n\r\n goog.findBasePath_();\r\n\r\n /** @struct @constructor @final */\r\n goog.Transpiler = function() {\r\n /** @private {?Object<string, boolean>} */\r\n this.requiresTranspilation_ = null;\r\n /** @private {string} */\r\n this.transpilationTarget_ = goog.TRANSPILE_TO_LANGUAGE;\r\n };\r\n\r\n\r\n /**\r\n * Returns a newly created map from language mode string to a boolean\r\n * indicating whether transpilation should be done for that mode as well as\r\n * the highest level language that this environment supports.\r\n *\r\n * Guaranteed invariant:\r\n * For any two modes, l1 and l2 where l2 is a newer mode than l1,\r\n * `map[l1] == true` implies that `map[l2] == true`.\r\n *\r\n * Note this method is extracted and used elsewhere, so it cannot rely on\r\n * anything external (it should easily be able to be transformed into a\r\n * standalone, top level function).\r\n *\r\n * @private\r\n * @return {{\r\n * target: string,\r\n * map: !Object<string, boolean>\r\n * }}\r\n */\r\n goog.Transpiler.prototype.createRequiresTranspilation_ = function() {\r\n var transpilationTarget = 'es3';\r\n var /** !Object<string, boolean> */ requiresTranspilation = {'es3': false};\r\n var transpilationRequiredForAllLaterModes = false;\r\n\r\n /**\r\n * Adds an entry to requiresTranspliation for the given language mode.\r\n *\r\n * IMPORTANT: Calls must be made in order from oldest to newest language\r\n * mode.\r\n * @param {string} modeName\r\n * @param {function(): boolean} isSupported Returns true if the JS engine\r\n * supports the given mode.\r\n */\r\n function addNewerLanguageTranspilationCheck(modeName, isSupported) {\r\n if (transpilationRequiredForAllLaterModes) {\r\n requiresTranspilation[modeName] = true;\r\n } else if (isSupported()) {\r\n transpilationTarget = modeName;\r\n requiresTranspilation[modeName] = false;\r\n } else {\r\n requiresTranspilation[modeName] = true;\r\n transpilationRequiredForAllLaterModes = true;\r\n }\r\n }\r\n\r\n /**\r\n * Does the given code evaluate without syntax errors and return a truthy\r\n * result?\r\n */\r\n function /** boolean */ evalCheck(/** string */ code) {\r\n try {\r\n return !!eval(code);\r\n } catch (ignored) {\r\n return false;\r\n }\r\n }\r\n\r\n var userAgent = goog.global.navigator && goog.global.navigator.userAgent ?\r\n goog.global.navigator.userAgent :\r\n '';\r\n\r\n // Identify ES3-only browsers by their incorrect treatment of commas.\r\n addNewerLanguageTranspilationCheck('es5', function() {\r\n return evalCheck('[1,].length==1');\r\n });\r\n addNewerLanguageTranspilationCheck('es6', function() {\r\n // Edge has a non-deterministic (i.e., not reproducible) bug with ES6:\r\n // https://github.com/Microsoft/ChakraCore/issues/1496.\r\n var re = /Edge\\/(\\d+)(\\.\\d)*/i;\r\n var edgeUserAgent = userAgent.match(re);\r\n if (edgeUserAgent) {\r\n // The Reflect.construct test below is flaky on Edge. It can sometimes\r\n // pass or fail on 40 15.15063, so just exit early for Edge and treat\r\n // it as ES5. Until we're on a more up to date version just always use\r\n // ES5. See https://github.com/Microsoft/ChakraCore/issues/3217.\r\n return false;\r\n }\r\n // Test es6: [FF50 (?), Edge 14 (?), Chrome 50]\r\n // (a) default params (specifically shadowing locals),\r\n // (b) destructuring, (c) block-scoped functions,\r\n // (d) for-of (const), (e) new.target/Reflect.construct\r\n var es6fullTest =\r\n 'class X{constructor(){if(new.target!=String)throw 1;this.x=42}}' +\r\n 'let q=Reflect.construct(X,[],String);if(q.x!=42||!(q instanceof ' +\r\n 'String))throw 1;for(const a of[2,3]){if(a==2)continue;function ' +\r\n 'f(z={a}){let a=0;return z.a}{function f(){return 0;}}return f()' +\r\n '==3}';\r\n\r\n return evalCheck('(()=>{\"use strict\";' + es6fullTest + '})()');\r\n });\r\n // ** and **= are the only new features in 'es7'\r\n addNewerLanguageTranspilationCheck('es7', function() {\r\n return evalCheck('2 ** 2 == 4');\r\n });\r\n // async functions are the only new features in 'es8'\r\n addNewerLanguageTranspilationCheck('es8', function() {\r\n return evalCheck('async () => 1, true');\r\n });\r\n addNewerLanguageTranspilationCheck('es9', function() {\r\n return evalCheck('({...rest} = {}), true');\r\n });\r\n addNewerLanguageTranspilationCheck('es_next', function() {\r\n return false; // assume it always need to transpile\r\n });\r\n return {target: transpilationTarget, map: requiresTranspilation};\r\n };\r\n\r\n\r\n /**\r\n * Determines whether the given language needs to be transpiled.\r\n * @param {string} lang\r\n * @param {string|undefined} module\r\n * @return {boolean}\r\n */\r\n goog.Transpiler.prototype.needsTranspile = function(lang, module) {\r\n if (goog.TRANSPILE == 'always') {\r\n return true;\r\n } else if (goog.TRANSPILE == 'never') {\r\n return false;\r\n } else if (!this.requiresTranspilation_) {\r\n var obj = this.createRequiresTranspilation_();\r\n this.requiresTranspilation_ = obj.map;\r\n this.transpilationTarget_ = this.transpilationTarget_ || obj.target;\r\n }\r\n if (lang in this.requiresTranspilation_) {\r\n if (this.requiresTranspilation_[lang]) {\r\n return true;\r\n } else if (\r\n goog.inHtmlDocument_() && module == 'es6' &&\r\n !('noModule' in goog.global.document.createElement('script'))) {\r\n return true;\r\n } else {\r\n return false;\r\n }\r\n } else {\r\n throw new Error('Unknown language mode: ' + lang);\r\n }\r\n };\r\n\r\n\r\n /**\r\n * Lazily retrieves the transpiler and applies it to the source.\r\n * @param {string} code JS code.\r\n * @param {string} path Path to the code.\r\n * @return {string} The transpiled code.\r\n */\r\n goog.Transpiler.prototype.transpile = function(code, path) {\r\n // TODO(johnplaisted): We should delete goog.transpile_ and just have this\r\n // function. But there's some compile error atm where goog.global is being\r\n // stripped incorrectly without this.\r\n return goog.transpile_(code, path, this.transpilationTarget_);\r\n };\r\n\r\n\r\n /** @private @final {!goog.Transpiler} */\r\n goog.transpiler_ = new goog.Transpiler();\r\n\r\n /**\r\n * Rewrites closing script tags in input to avoid ending an enclosing script\r\n * tag.\r\n *\r\n * @param {string} str\r\n * @return {string}\r\n * @private\r\n */\r\n goog.protectScriptTag_ = function(str) {\r\n return str.replace(/<\\/(SCRIPT)/ig, '\\\\x3c/$1');\r\n };\r\n\r\n\r\n /**\r\n * A debug loader is responsible for downloading and executing javascript\r\n * files in an unbundled, uncompiled environment.\r\n *\r\n * This can be custimized via the setDependencyFactory method, or by\r\n * CLOSURE_IMPORT_SCRIPT/CLOSURE_LOAD_FILE_SYNC.\r\n *\r\n * @struct @constructor @final @private\r\n */\r\n goog.DebugLoader_ = function() {\r\n /** @private @const {!Object<string, !goog.Dependency>} */\r\n this.dependencies_ = {};\r\n /** @private @const {!Object<string, string>} */\r\n this.idToPath_ = {};\r\n /** @private @const {!Object<string, boolean>} */\r\n this.written_ = {};\r\n /** @private @const {!Array<!goog.Dependency>} */\r\n this.loadingDeps_ = [];\r\n /** @private {!Array<!goog.Dependency>} */\r\n this.depsToLoad_ = [];\r\n /** @private {boolean} */\r\n this.paused_ = false;\r\n /** @private {!goog.DependencyFactory} */\r\n this.factory_ = new goog.DependencyFactory(goog.transpiler_);\r\n /** @private @const {!Object<string, !Function>} */\r\n this.deferredCallbacks_ = {};\r\n /** @private @const {!Array<string>} */\r\n this.deferredQueue_ = [];\r\n };\r\n\r\n /**\r\n * @param {!Array<string>} namespaces\r\n * @param {function(): undefined} callback Function to call once all the\r\n * namespaces have loaded.\r\n */\r\n goog.DebugLoader_.prototype.bootstrap = function(namespaces, callback) {\r\n var cb = callback;\r\n function resolve() {\r\n if (cb) {\r\n goog.global.setTimeout(cb, 0);\r\n cb = null;\r\n }\r\n }\r\n\r\n if (!namespaces.length) {\r\n resolve();\r\n return;\r\n }\r\n\r\n var deps = [];\r\n for (var i = 0; i < namespaces.length; i++) {\r\n var path = this.getPathFromDeps_(namespaces[i]);\r\n if (!path) {\r\n throw new Error('Unregonized namespace: ' + namespaces[i]);\r\n }\r\n deps.push(this.dependencies_[path]);\r\n }\r\n\r\n var require = goog.require;\r\n var loaded = 0;\r\n for (var i = 0; i < namespaces.length; i++) {\r\n require(namespaces[i]);\r\n deps[i].onLoad(function() {\r\n if (++loaded == namespaces.length) {\r\n resolve();\r\n }\r\n });\r\n }\r\n };\r\n\r\n\r\n /**\r\n * Loads the Closure Dependency file.\r\n *\r\n * Exposed a public function so CLOSURE_NO_DEPS can be set to false, base\r\n * loaded, setDependencyFactory called, and then this called. i.e. allows\r\n * custom loading of the deps file.\r\n */\r\n goog.DebugLoader_.prototype.loadClosureDeps = function() {\r\n // Circumvent addDependency, which would try to transpile deps.js if\r\n // transpile is set to always.\r\n var relPath = 'deps.js';\r\n this.depsToLoad_.push(this.factory_.createDependency(\r\n goog.normalizePath_(goog.basePath + relPath), relPath, [], [], {},\r\n false));\r\n this.loadDeps_();\r\n };\r\n\r\n\r\n /**\r\n * Notifies the debug loader when a dependency has been requested.\r\n *\r\n * @param {string} absPathOrId Path of the dependency or goog id.\r\n * @param {boolean=} opt_force\r\n */\r\n goog.DebugLoader_.prototype.requested = function(absPathOrId, opt_force) {\r\n var path = this.getPathFromDeps_(absPathOrId);\r\n if (path &&\r\n (opt_force || this.areDepsLoaded_(this.dependencies_[path].requires))) {\r\n var callback = this.deferredCallbacks_[path];\r\n if (callback) {\r\n delete this.deferredCallbacks_[path];\r\n callback();\r\n }\r\n }\r\n };\r\n\r\n\r\n /**\r\n * Sets the dependency factory, which can be used to create custom\r\n * goog.Dependency implementations to control how dependencies are loaded.\r\n *\r\n * @param {!goog.DependencyFactory} factory\r\n */\r\n goog.DebugLoader_.prototype.setDependencyFactory = function(factory) {\r\n this.factory_ = factory;\r\n };\r\n\r\n\r\n /**\r\n * Travserses the dependency graph and queues the given dependency, and all of\r\n * its transitive dependencies, for loading and then starts loading if not\r\n * paused.\r\n *\r\n * @param {string} namespace\r\n * @private\r\n */\r\n goog.DebugLoader_.prototype.load_ = function(namespace) {\r\n if (!this.getPathFromDeps_(namespace)) {\r\n var errorMessage = 'goog.require could not find: ' + namespace;\r\n\r\n goog.logToConsole_(errorMessage);\r\n throw Error(errorMessage);\r\n } else {\r\n var loader = this;\r\n\r\n var deps = [];\r\n\r\n /** @param {string} namespace */\r\n var visit = function(namespace) {\r\n var path = loader.getPathFromDeps_(namespace);\r\n\r\n if (!path) {\r\n throw new Error('Bad dependency path or symbol: ' + namespace);\r\n }\r\n\r\n if (loader.written_[path]) {\r\n return;\r\n }\r\n\r\n loader.written_[path] = true;\r\n\r\n var dep = loader.dependencies_[path];\r\n for (var i = 0; i < dep.requires.length; i++) {\r\n if (!goog.isProvided_(dep.requires[i])) {\r\n visit(dep.requires[i]);\r\n }\r\n }\r\n\r\n deps.push(dep);\r\n };\r\n\r\n visit(namespace);\r\n\r\n var wasLoading = !!this.depsToLoad_.length;\r\n this.depsToLoad_ = this.depsToLoad_.concat(deps);\r\n\r\n if (!this.paused_ && !wasLoading) {\r\n this.loadDeps_();\r\n }\r\n }\r\n };\r\n\r\n\r\n /**\r\n * Loads any queued dependencies until they are all loaded or paused.\r\n *\r\n * @private\r\n */\r\n goog.DebugLoader_.prototype.loadDeps_ = function() {\r\n var loader = this;\r\n var paused = this.paused_;\r\n\r\n while (this.depsToLoad_.length && !paused) {\r\n (function() {\r\n var loadCallDone = false;\r\n var dep = loader.depsToLoad_.shift();\r\n\r\n var loaded = false;\r\n loader.loading_(dep);\r\n\r\n var controller = {\r\n pause: function() {\r\n if (loadCallDone) {\r\n throw new Error('Cannot call pause after the call to load.');\r\n } else {\r\n paused = true;\r\n }\r\n },\r\n resume: function() {\r\n if (loadCallDone) {\r\n loader.resume_();\r\n } else {\r\n // Some dep called pause and then resume in the same load call.\r\n // Just keep running this same loop.\r\n paused = false;\r\n }\r\n },\r\n loaded: function() {\r\n if (loaded) {\r\n throw new Error('Double call to loaded.');\r\n }\r\n\r\n loaded = true;\r\n loader.loaded_(dep);\r\n },\r\n pending: function() {\r\n // Defensive copy.\r\n var pending = [];\r\n for (var i = 0; i < loader.loadingDeps_.length; i++) {\r\n pending.push(loader.loadingDeps_[i]);\r\n }\r\n return pending;\r\n },\r\n /**\r\n * @param {goog.ModuleType} type\r\n */\r\n setModuleState: function(type) {\r\n goog.moduleLoaderState_ = {\r\n type: type,\r\n moduleName: '',\r\n declareLegacyNamespace: false\r\n };\r\n },\r\n /** @type {function(string, string, string=)} */\r\n registerEs6ModuleExports: function(\r\n path, exports, opt_closureNamespace) {\r\n if (opt_closureNamespace) {\r\n goog.loadedModules_[opt_closureNamespace] = {\r\n exports: exports,\r\n type: goog.ModuleType.ES6,\r\n moduleId: opt_closureNamespace || ''\r\n };\r\n }\r\n },\r\n /** @type {function(string, ?)} */\r\n registerGoogModuleExports: function(moduleId, exports) {\r\n goog.loadedModules_[moduleId] = {\r\n exports: exports,\r\n type: goog.ModuleType.GOOG,\r\n moduleId: moduleId\r\n };\r\n },\r\n clearModuleState: function() {\r\n goog.moduleLoaderState_ = null;\r\n },\r\n defer: function(callback) {\r\n if (loadCallDone) {\r\n throw new Error(\r\n 'Cannot register with defer after the call to load.');\r\n }\r\n loader.defer_(dep, callback);\r\n },\r\n areDepsLoaded: function() {\r\n return loader.areDepsLoaded_(dep.requires);\r\n }\r\n };\r\n\r\n try {\r\n dep.load(controller);\r\n } finally {\r\n loadCallDone = true;\r\n }\r\n })();\r\n }\r\n\r\n if (paused) {\r\n this.pause_();\r\n }\r\n };\r\n\r\n\r\n /** @private */\r\n goog.DebugLoader_.prototype.pause_ = function() {\r\n this.paused_ = true;\r\n };\r\n\r\n\r\n /** @private */\r\n goog.DebugLoader_.prototype.resume_ = function() {\r\n if (this.paused_) {\r\n this.paused_ = false;\r\n this.loadDeps_();\r\n }\r\n };\r\n\r\n\r\n /**\r\n * Marks the given dependency as loading (load has been called but it has not\r\n * yet marked itself as finished). Useful for dependencies that want to know\r\n * what else is loading. Example: goog.modules cannot eval if there are\r\n * loading dependencies.\r\n *\r\n * @param {!goog.Dependency} dep\r\n * @private\r\n */\r\n goog.DebugLoader_.prototype.loading_ = function(dep) {\r\n this.loadingDeps_.push(dep);\r\n };\r\n\r\n\r\n /**\r\n * Marks the given dependency as having finished loading and being available\r\n * for require.\r\n *\r\n * @param {!goog.Dependency} dep\r\n * @private\r\n */\r\n goog.DebugLoader_.prototype.loaded_ = function(dep) {\r\n for (var i = 0; i < this.loadingDeps_.length; i++) {\r\n if (this.loadingDeps_[i] == dep) {\r\n this.loadingDeps_.splice(i, 1);\r\n break;\r\n }\r\n }\r\n\r\n for (var i = 0; i < this.deferredQueue_.length; i++) {\r\n if (this.deferredQueue_[i] == dep.path) {\r\n this.deferredQueue_.splice(i, 1);\r\n break;\r\n }\r\n }\r\n\r\n if (this.loadingDeps_.length == this.deferredQueue_.length &&\r\n !this.depsToLoad_.length) {\r\n // Something has asked to load these, but they may not be directly\r\n // required again later, so load them now that we know we're done loading\r\n // everything else. e.g. a goog module entry point.\r\n while (this.deferredQueue_.length) {\r\n this.requested(this.deferredQueue_.shift(), true);\r\n }\r\n }\r\n\r\n dep.loaded();\r\n };\r\n\r\n\r\n /**\r\n * @param {!Array<string>} pathsOrIds\r\n * @return {boolean}\r\n * @private\r\n */\r\n goog.DebugLoader_.prototype.areDepsLoaded_ = function(pathsOrIds) {\r\n for (var i = 0; i < pathsOrIds.length; i++) {\r\n var path = this.getPathFromDeps_(pathsOrIds[i]);\r\n if (!path ||\r\n (!(path in this.deferredCallbacks_) &&\r\n !goog.isProvided_(pathsOrIds[i]))) {\r\n return false;\r\n }\r\n }\r\n\r\n return true;\r\n };\r\n\r\n\r\n /**\r\n * @param {string} absPathOrId\r\n * @return {?string}\r\n * @private\r\n */\r\n goog.DebugLoader_.prototype.getPathFromDeps_ = function(absPathOrId) {\r\n if (absPathOrId in this.idToPath_) {\r\n return this.idToPath_[absPathOrId];\r\n } else if (absPathOrId in this.dependencies_) {\r\n return absPathOrId;\r\n } else {\r\n return null;\r\n }\r\n };\r\n\r\n\r\n /**\r\n * @param {!goog.Dependency} dependency\r\n * @param {!Function} callback\r\n * @private\r\n */\r\n goog.DebugLoader_.prototype.defer_ = function(dependency, callback) {\r\n this.deferredCallbacks_[dependency.path] = callback;\r\n this.deferredQueue_.push(dependency.path);\r\n };\r\n\r\n\r\n /**\r\n * Interface for goog.Dependency implementations to have some control over\r\n * loading of dependencies.\r\n *\r\n * @record\r\n */\r\n goog.LoadController = function() {};\r\n\r\n\r\n /**\r\n * Tells the controller to halt loading of more dependencies.\r\n */\r\n goog.LoadController.prototype.pause = function() {};\r\n\r\n\r\n /**\r\n * Tells the controller to resume loading of more dependencies if paused.\r\n */\r\n goog.LoadController.prototype.resume = function() {};\r\n\r\n\r\n /**\r\n * Tells the controller that this dependency has finished loading.\r\n *\r\n * This causes this to be removed from pending() and any load callbacks to\r\n * fire.\r\n */\r\n goog.LoadController.prototype.loaded = function() {};\r\n\r\n\r\n /**\r\n * List of dependencies on which load has been called but which have not\r\n * called loaded on their controller. This includes the current dependency.\r\n *\r\n * @return {!Array<!goog.Dependency>}\r\n */\r\n goog.LoadController.prototype.pending = function() {};\r\n\r\n\r\n /**\r\n * Registers an object as an ES6 module's exports so that goog.modules may\r\n * require it by path.\r\n *\r\n * @param {string} path Full path of the module.\r\n * @param {?} exports\r\n * @param {string=} opt_closureNamespace Closure namespace to associate with\r\n * this module.\r\n */\r\n goog.LoadController.prototype.registerEs6ModuleExports = function(\r\n path, exports, opt_closureNamespace) {};\r\n\r\n\r\n /**\r\n * Sets the current module state.\r\n *\r\n * @param {goog.ModuleType} type Type of module.\r\n */\r\n goog.LoadController.prototype.setModuleState = function(type) {};\r\n\r\n\r\n /**\r\n * Clears the current module state.\r\n */\r\n goog.LoadController.prototype.clearModuleState = function() {};\r\n\r\n\r\n /**\r\n * Registers a callback to call once the dependency is actually requested\r\n * via goog.require + all of the immediate dependencies have been loaded or\r\n * all other files have been loaded. Allows for lazy loading until\r\n * require'd without pausing dependency loading, which is needed on old IE.\r\n *\r\n * @param {!Function} callback\r\n */\r\n goog.LoadController.prototype.defer = function(callback) {};\r\n\r\n\r\n /**\r\n * @return {boolean}\r\n */\r\n goog.LoadController.prototype.areDepsLoaded = function() {};\r\n\r\n\r\n /**\r\n * Basic super class for all dependencies Closure Library can load.\r\n *\r\n * This default implementation is designed to load untranspiled, non-module\r\n * scripts in a web broswer.\r\n *\r\n * For transpiled non-goog.module files {@see goog.TranspiledDependency}.\r\n * For goog.modules see {@see goog.GoogModuleDependency}.\r\n * For untranspiled ES6 modules {@see goog.Es6ModuleDependency}.\r\n *\r\n * @param {string} path Absolute path of this script.\r\n * @param {string} relativePath Path of this script relative to goog.basePath.\r\n * @param {!Array<string>} provides goog.provided or goog.module symbols\r\n * in this file.\r\n * @param {!Array<string>} requires goog symbols or relative paths to Closure\r\n * this depends on.\r\n * @param {!Object<string, string>} loadFlags\r\n * @struct @constructor\r\n */\r\n goog.Dependency = function(\r\n path, relativePath, provides, requires, loadFlags) {\r\n /** @const */\r\n this.path = path;\r\n /** @const */\r\n this.relativePath = relativePath;\r\n /** @const */\r\n this.provides = provides;\r\n /** @const */\r\n this.requires = requires;\r\n /** @const */\r\n this.loadFlags = loadFlags;\r\n /** @private {boolean} */\r\n this.loaded_ = false;\r\n /** @private {!Array<function()>} */\r\n this.loadCallbacks_ = [];\r\n };\r\n\r\n\r\n /**\r\n * @return {string} The pathname part of this dependency's path if it is a\r\n * URI.\r\n */\r\n goog.Dependency.prototype.getPathName = function() {\r\n var pathName = this.path;\r\n var protocolIndex = pathName.indexOf('://');\r\n if (protocolIndex >= 0) {\r\n pathName = pathName.substring(protocolIndex + 3);\r\n var slashIndex = pathName.indexOf('/');\r\n if (slashIndex >= 0) {\r\n pathName = pathName.substring(slashIndex + 1);\r\n }\r\n }\r\n return pathName;\r\n };\r\n\r\n\r\n /**\r\n * @param {function()} callback Callback to fire as soon as this has loaded.\r\n * @final\r\n */\r\n goog.Dependency.prototype.onLoad = function(callback) {\r\n if (this.loaded_) {\r\n callback();\r\n } else {\r\n this.loadCallbacks_.push(callback);\r\n }\r\n };\r\n\r\n\r\n /**\r\n * Marks this dependency as loaded and fires any callbacks registered with\r\n * onLoad.\r\n * @final\r\n */\r\n goog.Dependency.prototype.loaded = function() {\r\n this.loaded_ = true;\r\n var callbacks = this.loadCallbacks_;\r\n this.loadCallbacks_ = [];\r\n for (var i = 0; i < callbacks.length; i++) {\r\n callbacks[i]();\r\n }\r\n };\r\n\r\n\r\n /**\r\n * Whether or not document.written / appended script tags should be deferred.\r\n *\r\n * @private {boolean}\r\n */\r\n goog.Dependency.defer_ = false;\r\n\r\n\r\n /**\r\n * Map of script ready / state change callbacks. Old IE cannot handle putting\r\n * these properties on goog.global.\r\n *\r\n * @private @const {!Object<string, function(?):undefined>}\r\n */\r\n goog.Dependency.callbackMap_ = {};\r\n\r\n\r\n /**\r\n * @param {function(...?):?} callback\r\n * @return {string}\r\n * @private\r\n */\r\n goog.Dependency.registerCallback_ = function(callback) {\r\n var key = Math.random().toString(32);\r\n goog.Dependency.callbackMap_[key] = callback;\r\n return key;\r\n };\r\n\r\n\r\n /**\r\n * @param {string} key\r\n * @private\r\n */\r\n goog.Dependency.unregisterCallback_ = function(key) {\r\n delete goog.Dependency.callbackMap_[key];\r\n };\r\n\r\n\r\n /**\r\n * @param {string} key\r\n * @param {...?} var_args\r\n * @private\r\n * @suppress {unusedPrivateMembers}\r\n */\r\n goog.Dependency.callback_ = function(key, var_args) {\r\n if (key in goog.Dependency.callbackMap_) {\r\n var callback = goog.Dependency.callbackMap_[key];\r\n var args = [];\r\n for (var i = 1; i < arguments.length; i++) {\r\n args.push(arguments[i]);\r\n }\r\n callback.apply(undefined, args);\r\n } else {\r\n var errorMessage = 'Callback key ' + key +\r\n ' does not exist (was base.js loaded more than once?).';\r\n throw Error(errorMessage);\r\n }\r\n };\r\n\r\n\r\n /**\r\n * Starts loading this dependency. This dependency can pause loading if it\r\n * needs to and resume it later via the controller interface.\r\n *\r\n * When this is loaded it should call controller.loaded(). Note that this will\r\n * end up calling the loaded method of this dependency; there is no need to\r\n * call it explicitly.\r\n *\r\n * @param {!goog.LoadController} controller\r\n */\r\n goog.Dependency.prototype.load = function(controller) {\r\n if (goog.global.CLOSURE_IMPORT_SCRIPT) {\r\n if (goog.global.CLOSURE_IMPORT_SCRIPT(this.path)) {\r\n controller.loaded();\r\n } else {\r\n controller.pause();\r\n }\r\n return;\r\n }\r\n\r\n if (!goog.inHtmlDocument_()) {\r\n goog.logToConsole_(\r\n 'Cannot use default debug loader outside of HTML documents.');\r\n if (this.relativePath == 'deps.js') {\r\n // Some old code is relying on base.js auto loading deps.js failing with\r\n // no error before later setting CLOSURE_IMPORT_SCRIPT.\r\n // CLOSURE_IMPORT_SCRIPT should be set *before* base.js is loaded, or\r\n // CLOSURE_NO_DEPS set to true.\r\n goog.logToConsole_(\r\n 'Consider setting CLOSURE_IMPORT_SCRIPT before loading base.js, ' +\r\n 'or setting CLOSURE_NO_DEPS to true.');\r\n controller.loaded();\r\n } else {\r\n controller.pause();\r\n }\r\n return;\r\n }\r\n\r\n /** @type {!HTMLDocument} */\r\n var doc = goog.global.document;\r\n\r\n // If the user tries to require a new symbol after document load,\r\n // something has gone terribly wrong. Doing a document.write would\r\n // wipe out the page. This does not apply to the CSP-compliant method\r\n // of writing script tags.\r\n if (doc.readyState == 'complete' &&\r\n !goog.ENABLE_CHROME_APP_SAFE_SCRIPT_LOADING) {\r\n // Certain test frameworks load base.js multiple times, which tries\r\n // to write deps.js each time. If that happens, just fail silently.\r\n // These frameworks wipe the page between each load of base.js, so this\r\n // is OK.\r\n var isDeps = /\\bdeps.js$/.test(this.path);\r\n if (isDeps) {\r\n controller.loaded();\r\n return;\r\n } else {\r\n throw Error('Cannot write \"' + this.path + '\" after document load');\r\n }\r\n }\r\n\r\n if (!goog.ENABLE_CHROME_APP_SAFE_SCRIPT_LOADING &&\r\n goog.isDocumentLoading_()) {\r\n var key = goog.Dependency.registerCallback_(function(script) {\r\n if (!goog.DebugLoader_.IS_OLD_IE_ || script.readyState == 'complete') {\r\n goog.Dependency.unregisterCallback_(key);\r\n controller.loaded();\r\n }\r\n });\r\n var nonceAttr = !goog.DebugLoader_.IS_OLD_IE_ && goog.getScriptNonce() ?\r\n ' nonce=\"' + goog.getScriptNonce() + '\"' :\r\n '';\r\n var event =\r\n goog.DebugLoader_.IS_OLD_IE_ ? 'onreadystatechange' : 'onload';\r\n var defer = goog.Dependency.defer_ ? 'defer' : '';\r\n var script = '<script src=\"' + this.path + '\" ' + event +\r\n '=\"goog.Dependency.callback_(\\'' + key +\r\n '\\', this)\" type=\"text/javascript\" ' + defer + nonceAttr + '><' +\r\n '/script>';\r\n doc.write(\r\n goog.TRUSTED_TYPES_POLICY_ ?\r\n goog.TRUSTED_TYPES_POLICY_.createHTML(script) :\r\n script);\r\n } else {\r\n var scriptEl =\r\n /** @type {!HTMLScriptElement} */ (doc.createElement('script'));\r\n scriptEl.defer = goog.Dependency.defer_;\r\n scriptEl.async = false;\r\n scriptEl.type = 'text/javascript';\r\n\r\n // If CSP nonces are used, propagate them to dynamically created scripts.\r\n // This is necessary to allow nonce-based CSPs without 'strict-dynamic'.\r\n var nonce = goog.getScriptNonce();\r\n if (nonce) {\r\n scriptEl.setAttribute('nonce', nonce);\r\n }\r\n\r\n if (goog.DebugLoader_.IS_OLD_IE_) {\r\n // Execution order is not guaranteed on old IE, halt loading and write\r\n // these scripts one at a time, after each loads.\r\n controller.pause();\r\n scriptEl.onreadystatechange = function() {\r\n if (scriptEl.readyState == 'loaded' ||\r\n scriptEl.readyState == 'complete') {\r\n controller.loaded();\r\n controller.resume();\r\n }\r\n };\r\n } else {\r\n scriptEl.onload = function() {\r\n scriptEl.onload = null;\r\n controller.loaded();\r\n };\r\n }\r\n\r\n scriptEl.src = goog.TRUSTED_TYPES_POLICY_ ?\r\n goog.TRUSTED_TYPES_POLICY_.createScriptURL(this.path) :\r\n this.path;\r\n doc.head.appendChild(scriptEl);\r\n }\r\n };\r\n\r\n\r\n /**\r\n * @param {string} path Absolute path of this script.\r\n * @param {string} relativePath Path of this script relative to goog.basePath.\r\n * @param {!Array<string>} provides Should be an empty array.\r\n * TODO(johnplaisted) add support for adding closure namespaces to ES6\r\n * modules for interop purposes.\r\n * @param {!Array<string>} requires goog symbols or relative paths to Closure\r\n * this depends on.\r\n * @param {!Object<string, string>} loadFlags\r\n * @struct @constructor\r\n * @extends {goog.Dependency}\r\n */\r\n goog.Es6ModuleDependency = function(\r\n path, relativePath, provides, requires, loadFlags) {\r\n goog.Es6ModuleDependency.base(\r\n this, 'constructor', path, relativePath, provides, requires, loadFlags);\r\n };\r\n goog.inherits(goog.Es6ModuleDependency, goog.Dependency);\r\n\r\n\r\n /** @override */\r\n goog.Es6ModuleDependency.prototype.load = function(controller) {\r\n if (goog.global.CLOSURE_IMPORT_SCRIPT) {\r\n if (goog.global.CLOSURE_IMPORT_SCRIPT(this.path)) {\r\n controller.loaded();\r\n } else {\r\n controller.pause();\r\n }\r\n return;\r\n }\r\n\r\n if (!goog.inHtmlDocument_()) {\r\n goog.logToConsole_(\r\n 'Cannot use default debug loader outside of HTML documents.');\r\n controller.pause();\r\n return;\r\n }\r\n\r\n /** @type {!HTMLDocument} */\r\n var doc = goog.global.document;\r\n\r\n var dep = this;\r\n\r\n // TODO(johnplaisted): Does document.writing really speed up anything? Any\r\n // difference between this and just waiting for interactive mode and then\r\n // appending?\r\n function write(src, contents) {\r\n if (contents) {\r\n var script = '<script type=\"module\" crossorigin>' + contents + '</' +\r\n 'script>';\r\n doc.write(\r\n goog.TRUSTED_TYPES_POLICY_ ?\r\n goog.TRUSTED_TYPES_POLICY_.createHTML(script) :\r\n script);\r\n } else {\r\n var script = '<script type=\"module\" crossorigin src=\"' + src + '\"></' +\r\n 'script>';\r\n doc.write(\r\n goog.TRUSTED_TYPES_POLICY_ ?\r\n goog.TRUSTED_TYPES_POLICY_.createHTML(script) :\r\n script);\r\n }\r\n }\r\n\r\n function append(src, contents) {\r\n var scriptEl =\r\n /** @type {!HTMLScriptElement} */ (doc.createElement('script'));\r\n scriptEl.defer = true;\r\n scriptEl.async = false;\r\n scriptEl.type = 'module';\r\n scriptEl.setAttribute('crossorigin', true);\r\n\r\n // If CSP nonces are used, propagate them to dynamically created scripts.\r\n // This is necessary to allow nonce-based CSPs without 'strict-dynamic'.\r\n var nonce = goog.getScriptNonce();\r\n if (nonce) {\r\n scriptEl.setAttribute('nonce', nonce);\r\n }\r\n\r\n if (contents) {\r\n scriptEl.textContent = goog.TRUSTED_TYPES_POLICY_ ?\r\n goog.TRUSTED_TYPES_POLICY_.createScript(contents) :\r\n contents;\r\n } else {\r\n scriptEl.src = goog.TRUSTED_TYPES_POLICY_ ?\r\n goog.TRUSTED_TYPES_POLICY_.createScriptURL(src) :\r\n src;\r\n }\r\n\r\n doc.head.appendChild(scriptEl);\r\n }\r\n\r\n var create;\r\n\r\n if (goog.isDocumentLoading_()) {\r\n create = write;\r\n // We can ONLY call document.write if we are guaranteed that any\r\n // non-module script tags document.written after this are deferred.\r\n // Small optimization, in theory document.writing is faster.\r\n goog.Dependency.defer_ = true;\r\n } else {\r\n create = append;\r\n }\r\n\r\n // Write 4 separate tags here:\r\n // 1) Sets the module state at the correct time (just before execution).\r\n // 2) A src node for this, which just hopefully lets the browser load it a\r\n // little early (no need to parse #3).\r\n // 3) Import the module and register it.\r\n // 4) Clear the module state at the correct time. Guaranteed to run even\r\n // if there is an error in the module (#3 will not run if there is an\r\n // error in the module).\r\n var beforeKey = goog.Dependency.registerCallback_(function() {\r\n goog.Dependency.unregisterCallback_(beforeKey);\r\n controller.setModuleState(goog.ModuleType.ES6);\r\n });\r\n create(undefined, 'goog.Dependency.callback_(\"' + beforeKey + '\")');\r\n\r\n // TODO(johnplaisted): Does this really speed up anything?\r\n create(this.path, undefined);\r\n\r\n var registerKey = goog.Dependency.registerCallback_(function(exports) {\r\n goog.Dependency.unregisterCallback_(registerKey);\r\n controller.registerEs6ModuleExports(\r\n dep.path, exports, goog.moduleLoaderState_.moduleName);\r\n });\r\n create(\r\n undefined,\r\n 'import * as m from \"' + this.path + '\"; goog.Dependency.callback_(\"' +\r\n registerKey + '\", m)');\r\n\r\n var afterKey = goog.Dependency.registerCallback_(function() {\r\n goog.Dependency.unregisterCallback_(afterKey);\r\n controller.clearModuleState();\r\n controller.loaded();\r\n });\r\n create(undefined, 'goog.Dependency.callback_(\"' + afterKey + '\")');\r\n };\r\n\r\n\r\n /**\r\n * Superclass of any dependency that needs to be loaded into memory,\r\n * transformed, and then eval'd (goog.modules and transpiled files).\r\n *\r\n * @param {string} path Absolute path of this script.\r\n * @param {string} relativePath Path of this script relative to goog.basePath.\r\n * @param {!Array<string>} provides goog.provided or goog.module symbols\r\n * in this file.\r\n * @param {!Array<string>} requires goog symbols or relative paths to Closure\r\n * this depends on.\r\n * @param {!Object<string, string>} loadFlags\r\n * @struct @constructor @abstract\r\n * @extends {goog.Dependency}\r\n */\r\n goog.TransformedDependency = function(\r\n path, relativePath, provides, requires, loadFlags) {\r\n goog.TransformedDependency.base(\r\n this, 'constructor', path, relativePath, provides, requires, loadFlags);\r\n /** @private {?string} */\r\n this.contents_ = null;\r\n\r\n /**\r\n * Whether to lazily make the synchronous XHR (when goog.require'd) or make\r\n * the synchronous XHR when initially loading. On FireFox 61 there is a bug\r\n * where an ES6 module cannot make a synchronous XHR (rather, it can, but if\r\n * it does then no other ES6 modules will load after).\r\n *\r\n * tl;dr we lazy load due to bugs on older browsers and eager load due to\r\n * bugs on newer ones.\r\n *\r\n * https://bugzilla.mozilla.org/show_bug.cgi?id=1477090\r\n *\r\n * @private @const {boolean}\r\n */\r\n this.lazyFetch_ = !goog.inHtmlDocument_() ||\r\n !('noModule' in goog.global.document.createElement('script'));\r\n };\r\n goog.inherits(goog.TransformedDependency, goog.Dependency);\r\n\r\n\r\n /** @override */\r\n goog.TransformedDependency.prototype.load = function(controller) {\r\n var dep = this;\r\n\r\n function fetch() {\r\n dep.contents_ = goog.loadFileSync_(dep.path);\r\n\r\n if (dep.contents_) {\r\n dep.contents_ = dep.transform(dep.contents_);\r\n if (dep.contents_) {\r\n dep.contents_ += '\\n//# sourceURL=' + dep.path;\r\n }\r\n }\r\n }\r\n\r\n if (goog.global.CLOSURE_IMPORT_SCRIPT) {\r\n fetch();\r\n if (this.contents_ &&\r\n goog.global.CLOSURE_IMPORT_SCRIPT('', this.contents_)) {\r\n this.contents_ = null;\r\n controller.loaded();\r\n } else {\r\n controller.pause();\r\n }\r\n return;\r\n }\r\n\r\n\r\n var isEs6 = this.loadFlags['module'] == goog.ModuleType.ES6;\r\n\r\n if (!this.lazyFetch_) {\r\n fetch();\r\n }\r\n\r\n function load() {\r\n if (dep.lazyFetch_) {\r\n fetch();\r\n }\r\n\r\n if (!dep.contents_) {\r\n // loadFileSync_ or transform are responsible. Assume they logged an\r\n // error.\r\n return;\r\n }\r\n\r\n if (isEs6) {\r\n controller.setModuleState(goog.ModuleType.ES6);\r\n }\r\n\r\n var namespace;\r\n\r\n try {\r\n var contents = dep.contents_;\r\n dep.contents_ = null;\r\n goog.globalEval(contents);\r\n if (isEs6) {\r\n namespace = goog.moduleLoaderState_.moduleName;\r\n }\r\n } finally {\r\n if (isEs6) {\r\n controller.clearModuleState();\r\n }\r\n }\r\n\r\n if (isEs6) {\r\n // Due to circular dependencies this may not be available for require\r\n // right now.\r\n goog.global['$jscomp']['require']['ensure'](\r\n [dep.getPathName()], function() {\r\n controller.registerEs6ModuleExports(\r\n dep.path,\r\n goog.global['$jscomp']['require'](dep.getPathName()),\r\n namespace);\r\n });\r\n }\r\n\r\n controller.loaded();\r\n }\r\n\r\n // Do not fetch now; in FireFox 47 the synchronous XHR doesn't block all\r\n // events. If we fetched now and then document.write'd the contents the\r\n // document.write would be an eval and would execute too soon! Instead write\r\n // a script tag to fetch and eval synchronously at the correct time.\r\n function fetchInOwnScriptThenLoad() {\r\n /** @type {!HTMLDocument} */\r\n var doc = goog.global.document;\r\n\r\n var key = goog.Dependency.registerCallback_(function() {\r\n goog.Dependency.unregisterCallback_(key);\r\n load();\r\n });\r\n\r\n var script = '<script type=\"text/javascript\">' +\r\n goog.protectScriptTag_('goog.Dependency.callback_(\"' + key + '\");') +\r\n '</' +\r\n 'script>';\r\n doc.write(\r\n goog.TRUSTED_TYPES_POLICY_ ?\r\n goog.TRUSTED_TYPES_POLICY_.createHTML(script) :\r\n script);\r\n }\r\n\r\n // If one thing is pending it is this.\r\n var anythingElsePending = controller.pending().length > 1;\r\n\r\n // If anything else is loading we need to lazy load due to bugs in old IE.\r\n // Specifically script tags with src and script tags with contents could\r\n // execute out of order if document.write is used, so we cannot use\r\n // document.write. Do not pause here; it breaks old IE as well.\r\n var useOldIeWorkAround =\r\n anythingElsePending && goog.DebugLoader_.IS_OLD_IE_;\r\n\r\n // Additionally if we are meant to defer scripts but the page is still\r\n // loading (e.g. an ES6 module is loading) then also defer. Or if we are\r\n // meant to defer and anything else is pending then defer (those may be\r\n // scripts that did not need transformation and are just script tags with\r\n // defer set to true, and we need to evaluate after that deferred script).\r\n var needsAsyncLoading = goog.Dependency.defer_ &&\r\n (anythingElsePending || goog.isDocumentLoading_());\r\n\r\n if (useOldIeWorkAround || needsAsyncLoading) {\r\n // Note that we only defer when we have to rather than 100% of the time.\r\n // Always defering would work, but then in theory the order of\r\n // goog.require calls would then matter. We want to enforce that most of\r\n // the time the order of the require calls does not matter.\r\n controller.defer(function() {\r\n load();\r\n });\r\n return;\r\n }\r\n // TODO(johnplaisted): Externs are missing onreadystatechange for\r\n // HTMLDocument.\r\n /** @type {?} */\r\n var doc = goog.global.document;\r\n\r\n var isInternetExplorer =\r\n goog.inHtmlDocument_() && 'ActiveXObject' in goog.global;\r\n\r\n // Don't delay in any version of IE. There's bug around this that will\r\n // cause out of order script execution. This means that on older IE ES6\r\n // modules will load too early (while the document is still loading + the\r\n // dom is not available). The other option is to load too late (when the\r\n // document is complete and the onload even will never fire). This seems\r\n // to be the lesser of two evils as scripts already act like the former.\r\n if (isEs6 && goog.inHtmlDocument_() && goog.isDocumentLoading_() &&\r\n !isInternetExplorer) {\r\n goog.Dependency.defer_ = true;\r\n // Transpiled ES6 modules still need to load like regular ES6 modules,\r\n // aka only after the document is interactive.\r\n controller.pause();\r\n var oldCallback = doc.onreadystatechange;\r\n doc.onreadystatechange = function() {\r\n if (doc.readyState == 'interactive') {\r\n doc.onreadystatechange = oldCallback;\r\n load();\r\n controller.resume();\r\n }\r\n if (goog.isFunction(oldCallback)) {\r\n oldCallback.apply(undefined, arguments);\r\n }\r\n };\r\n } else {\r\n // Always eval on old IE.\r\n if (goog.DebugLoader_.IS_OLD_IE_ || !goog.inHtmlDocument_() ||\r\n !goog.isDocumentLoading_()) {\r\n load();\r\n } else {\r\n fetchInOwnScriptThenLoad();\r\n }\r\n }\r\n };\r\n\r\n\r\n /**\r\n * @param {string} contents\r\n * @return {string}\r\n * @abstract\r\n */\r\n goog.TransformedDependency.prototype.transform = function(contents) {};\r\n\r\n\r\n /**\r\n * Any non-goog.module dependency which needs to be transpiled before eval.\r\n *\r\n * @param {string} path Absolute path of this script.\r\n * @param {string} relativePath Path of this script relative to goog.basePath.\r\n * @param {!Array<string>} provides goog.provided or goog.module symbols\r\n * in this file.\r\n * @param {!Array<string>} requires goog symbols or relative paths to Closure\r\n * this depends on.\r\n * @param {!Object<string, string>} loadFlags\r\n * @param {!goog.Transpiler} transpiler\r\n * @struct @constructor\r\n * @extends {goog.TransformedDependency}\r\n */\r\n goog.TranspiledDependency = function(\r\n path, relativePath, provides, requires, loadFlags, transpiler) {\r\n goog.TranspiledDependency.base(\r\n this, 'constructor', path, relativePath, provides, requires, loadFlags);\r\n /** @protected @const*/\r\n this.transpiler = transpiler;\r\n };\r\n goog.inherits(goog.TranspiledDependency, goog.TransformedDependency);\r\n\r\n\r\n /** @override */\r\n goog.TranspiledDependency.prototype.transform = function(contents) {\r\n // Transpile with the pathname so that ES6 modules are domain agnostic.\r\n return this.transpiler.transpile(contents, this.getPathName());\r\n };\r\n\r\n\r\n /**\r\n * An ES6 module dependency that was transpiled to a jscomp module outside\r\n * of the debug loader, e.g. server side.\r\n *\r\n * @param {string} path Absolute path of this script.\r\n * @param {string} relativePath Path of this script relative to goog.basePath.\r\n * @param {!Array<string>} provides goog.provided or goog.module symbols\r\n * in this file.\r\n * @param {!Array<string>} requires goog symbols or relative paths to Closure\r\n * this depends on.\r\n * @param {!Object<string, string>} loadFlags\r\n * @struct @constructor\r\n * @extends {goog.TransformedDependency}\r\n */\r\n goog.PreTranspiledEs6ModuleDependency = function(\r\n path, relativePath, provides, requires, loadFlags) {\r\n goog.PreTranspiledEs6ModuleDependency.base(\r\n this, 'constructor', path, relativePath, provides, requires, loadFlags);\r\n };\r\n goog.inherits(\r\n goog.PreTranspiledEs6ModuleDependency, goog.TransformedDependency);\r\n\r\n\r\n /** @override */\r\n goog.PreTranspiledEs6ModuleDependency.prototype.transform = function(\r\n contents) {\r\n return contents;\r\n };\r\n\r\n\r\n /**\r\n * A goog.module, transpiled or not. Will always perform some minimal\r\n * transformation even when not transpiled to wrap in a goog.loadModule\r\n * statement.\r\n *\r\n * @param {string} path Absolute path of this script.\r\n * @param {string} relativePath Path of this script relative to goog.basePath.\r\n * @param {!Array<string>} provides goog.provided or goog.module symbols\r\n * in this file.\r\n * @param {!Array<string>} requires goog symbols or relative paths to Closure\r\n * this depends on.\r\n * @param {!Object<string, string>} loadFlags\r\n * @param {boolean} needsTranspile\r\n * @param {!goog.Transpiler} transpiler\r\n * @struct @constructor\r\n * @extends {goog.TransformedDependency}\r\n */\r\n goog.GoogModuleDependency = function(\r\n path, relativePath, provides, requires, loadFlags, needsTranspile,\r\n transpiler) {\r\n goog.GoogModuleDependency.base(\r\n this, 'constructor', path, relativePath, provides, requires, loadFlags);\r\n /** @private @const */\r\n this.needsTranspile_ = needsTranspile;\r\n /** @private @const */\r\n this.transpiler_ = transpiler;\r\n };\r\n goog.inherits(goog.GoogModuleDependency, goog.TransformedDependency);\r\n\r\n\r\n /** @override */\r\n goog.GoogModuleDependency.prototype.transform = function(contents) {\r\n if (this.needsTranspile_) {\r\n contents = this.transpiler_.transpile(contents, this.getPathName());\r\n }\r\n\r\n if (!goog.LOAD_MODULE_USING_EVAL || !goog.isDef(goog.global.JSON)) {\r\n return '' +\r\n 'goog.loadModule(function(exports) {' +\r\n '\"use strict\";' + contents +\r\n '\\n' + // terminate any trailing single line comment.\r\n ';return exports' +\r\n '});' +\r\n '\\n//# sourceURL=' + this.path + '\\n';\r\n } else {\r\n return '' +\r\n 'goog.loadModule(' +\r\n goog.global.JSON.stringify(\r\n contents + '\\n//# sourceURL=' + this.path + '\\n') +\r\n ');';\r\n }\r\n };\r\n\r\n\r\n /**\r\n * Whether the browser is IE9 or earlier, which needs special handling\r\n * for deferred modules.\r\n * @const @private {boolean}\r\n */\r\n goog.DebugLoader_.IS_OLD_IE_ = !!(\r\n !goog.global.atob && goog.global.document && goog.global.document['all']);\r\n\r\n\r\n /**\r\n * @param {string} relPath\r\n * @param {!Array<string>|undefined} provides\r\n * @param {!Array<string>} requires\r\n * @param {boolean|!Object<string>=} opt_loadFlags\r\n * @see goog.addDependency\r\n */\r\n goog.DebugLoader_.prototype.addDependency = function(\r\n relPath, provides, requires, opt_loadFlags) {\r\n provides = provides || [];\r\n relPath = relPath.replace(/\\\\/g, '/');\r\n var path = goog.normalizePath_(goog.basePath + relPath);\r\n if (!opt_loadFlags || typeof opt_loadFlags === 'boolean') {\r\n opt_loadFlags = opt_loadFlags ? {'module': goog.ModuleType.GOOG} : {};\r\n }\r\n var dep = this.factory_.createDependency(\r\n path, relPath, provides, requires, opt_loadFlags,\r\n goog.transpiler_.needsTranspile(\r\n opt_loadFlags['lang'] || 'es3', opt_loadFlags['module']));\r\n this.dependencies_[path] = dep;\r\n for (var i = 0; i < provides.length; i++) {\r\n this.idToPath_[provides[i]] = path;\r\n }\r\n this.idToPath_[relPath] = path;\r\n };\r\n\r\n\r\n /**\r\n * Creates goog.Dependency instances for the debug loader to load.\r\n *\r\n * Should be overridden to have the debug loader use custom subclasses of\r\n * goog.Dependency.\r\n *\r\n * @param {!goog.Transpiler} transpiler\r\n * @struct @constructor\r\n */\r\n goog.DependencyFactory = function(transpiler) {\r\n /** @protected @const */\r\n this.transpiler = transpiler;\r\n };\r\n\r\n\r\n /**\r\n * @param {string} path Absolute path of the file.\r\n * @param {string} relativePath Path relative to closure’s base.js.\r\n * @param {!Array<string>} provides Array of provided goog.provide/module ids.\r\n * @param {!Array<string>} requires Array of required goog.provide/module /\r\n * relative ES6 module paths.\r\n * @param {!Object<string, string>} loadFlags\r\n * @param {boolean} needsTranspile True if the file needs to be transpiled\r\n * per the goog.Transpiler.\r\n * @return {!goog.Dependency}\r\n */\r\n goog.DependencyFactory.prototype.createDependency = function(\r\n path, relativePath, provides, requires, loadFlags, needsTranspile) {\r\n\r\n if (loadFlags['module'] == goog.ModuleType.GOOG) {\r\n return new goog.GoogModuleDependency(\r\n path, relativePath, provides, requires, loadFlags, needsTranspile,\r\n this.transpiler);\r\n } else if (needsTranspile) {\r\n return new goog.TranspiledDependency(\r\n path, relativePath, provides, requires, loadFlags, this.transpiler);\r\n } else {\r\n if (loadFlags['module'] == goog.ModuleType.ES6) {\r\n if (goog.TRANSPILE == 'never' && goog.ASSUME_ES_MODULES_TRANSPILED) {\r\n return new goog.PreTranspiledEs6ModuleDependency(\r\n path, relativePath, provides, requires, loadFlags);\r\n } else {\r\n return new goog.Es6ModuleDependency(\r\n path, relativePath, provides, requires, loadFlags);\r\n }\r\n } else {\r\n return new goog.Dependency(\r\n path, relativePath, provides, requires, loadFlags);\r\n }\r\n }\r\n };\r\n\r\n\r\n /** @private @const */\r\n goog.debugLoader_ = new goog.DebugLoader_();\r\n\r\n\r\n /**\r\n * Loads the Closure Dependency file.\r\n *\r\n * Exposed a public function so CLOSURE_NO_DEPS can be set to false, base\r\n * loaded, setDependencyFactory called, and then this called. i.e. allows\r\n * custom loading of the deps file.\r\n */\r\n goog.loadClosureDeps = function() {\r\n goog.debugLoader_.loadClosureDeps();\r\n };\r\n\r\n\r\n /**\r\n * Sets the dependency factory, which can be used to create custom\r\n * goog.Dependency implementations to control how dependencies are loaded.\r\n *\r\n * Note: if you wish to call this function and provide your own implemnetation\r\n * it is a wise idea to set CLOSURE_NO_DEPS to true, otherwise the dependency\r\n * file and all of its goog.addDependency calls will use the default factory.\r\n * You can call goog.loadClosureDeps to load the Closure dependency file\r\n * later, after your factory is injected.\r\n *\r\n * @param {!goog.DependencyFactory} factory\r\n */\r\n goog.setDependencyFactory = function(factory) {\r\n goog.debugLoader_.setDependencyFactory(factory);\r\n };\r\n\r\n\r\n if (!goog.global.CLOSURE_NO_DEPS) {\r\n goog.debugLoader_.loadClosureDeps();\r\n }\r\n\r\n\r\n /**\r\n * Bootstraps the given namespaces and calls the callback once they are\r\n * available either via goog.require. This is a replacement for using\r\n * `goog.require` to bootstrap Closure JavaScript. Previously a `goog.require`\r\n * in an HTML file would guarantee that the require'd namespace was available\r\n * in the next immediate script tag. With ES6 modules this no longer a\r\n * guarantee.\r\n *\r\n * @param {!Array<string>} namespaces\r\n * @param {function(): ?} callback Function to call once all the namespaces\r\n * have loaded. Always called asynchronously.\r\n */\r\n goog.bootstrap = function(namespaces, callback) {\r\n goog.debugLoader_.bootstrap(namespaces, callback);\r\n };\r\n}\r\n\r\n\r\n/**\r\n * @define {string} Trusted Types policy name. If non-empty then Closure will\r\n * use Trusted Types.\r\n */\r\ngoog.TRUSTED_TYPES_POLICY_NAME =\r\n goog.define('goog.TRUSTED_TYPES_POLICY_NAME', '');\r\n\r\n\r\n/**\r\n * Returns the parameter.\r\n * @param {string} s\r\n * @return {string}\r\n * @private\r\n */\r\ngoog.identity_ = function(s) {\r\n return s;\r\n};\r\n\r\n\r\n/**\r\n * Creates Trusted Types policy if Trusted Types are supported by the browser.\r\n * The policy just blesses any string as a Trusted Type. It is not visibility\r\n * restricted because anyone can also call TrustedTypes.createPolicy directly.\r\n * However, the allowed names should be restricted by a HTTP header and the\r\n * reference to the created policy should be visibility restricted.\r\n * @param {string} name\r\n * @return {?TrustedTypePolicy}\r\n * @throws {!TypeError} If called with a name which is already registered.\r\n */\r\ngoog.createTrustedTypesPolicy = function(name) {\r\n if (typeof TrustedTypes === 'undefined' || !TrustedTypes.createPolicy) {\r\n return null;\r\n }\r\n return TrustedTypes.createPolicy(name, {\r\n createHTML: goog.identity_,\r\n createScript: goog.identity_,\r\n createScriptURL: goog.identity_,\r\n createURL: goog.identity_\r\n });\r\n};\r\n\r\n\r\n/** @private @const {?TrustedTypePolicy} */\r\ngoog.TRUSTED_TYPES_POLICY_ = goog.TRUSTED_TYPES_POLICY_NAME ?\r\n goog.createTrustedTypesPolicy(goog.TRUSTED_TYPES_POLICY_NAME + '#base') :\r\n null;\r\n","// Copyright 2005 The Closure Library Authors. All Rights Reserved.\r\n//\r\n// Licensed under the Apache License, Version 2.0 (the \"License\");\r\n// you may not use this file except in compliance with the License.\r\n// You may obtain a copy of the License at\r\n//\r\n// http://www.apache.org/licenses/LICENSE-2.0\r\n//\r\n// Unless required by applicable law or agreed to in writing, software\r\n// distributed under the License is distributed on an \"AS-IS\" BASIS,\r\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n// See the License for the specific language governing permissions and\r\n// limitations under the License.\r\n\r\n/**\r\n * @fileoverview Implements the disposable interface. The dispose method is used\r\n * to clean up references and resources.\r\n * @author arv@google.com (Erik Arvidsson)\r\n */\r\n\r\n\r\ngoog.provide('goog.Disposable');\r\ngoog.provide('goog.dispose');\r\ngoog.provide('goog.disposeAll');\r\n\r\ngoog.require('goog.disposable.IDisposable');\r\n\r\n\r\n\r\n/**\r\n * Class that provides the basic implementation for disposable objects. If your\r\n * class holds one or more references to COM objects, DOM nodes, or other\r\n * disposable objects, it should extend this class or implement the disposable\r\n * interface (defined in goog.disposable.IDisposable).\r\n * @constructor\r\n * @implements {goog.disposable.IDisposable}\r\n */\r\ngoog.Disposable = function() {\r\n /**\r\n * If monitoring the goog.Disposable instances is enabled, stores the creation\r\n * stack trace of the Disposable instance.\r\n * @type {string|undefined}\r\n */\r\n this.creationStack;\r\n\r\n if (goog.Disposable.MONITORING_MODE != goog.Disposable.MonitoringMode.OFF) {\r\n if (goog.Disposable.INCLUDE_STACK_ON_CREATION) {\r\n this.creationStack = new Error().stack;\r\n }\r\n goog.Disposable.instances_[goog.getUid(this)] = this;\r\n }\r\n // Support sealing\r\n this.disposed_ = this.disposed_;\r\n this.onDisposeCallbacks_ = this.onDisposeCallbacks_;\r\n};\r\n\r\n\r\n/**\r\n * @enum {number} Different monitoring modes for Disposable.\r\n */\r\ngoog.Disposable.MonitoringMode = {\r\n /**\r\n * No monitoring.\r\n */\r\n OFF: 0,\r\n /**\r\n * Creating and disposing the goog.Disposable instances is monitored. All\r\n * disposable objects need to call the `goog.Disposable` base\r\n * constructor. The PERMANENT mode must be switched on before creating any\r\n * goog.Disposable instances.\r\n */\r\n PERMANENT: 1,\r\n /**\r\n * INTERACTIVE mode can be switched on and off on the fly without producing\r\n * errors. It also doesn't warn if the disposable objects don't call the\r\n * `goog.Disposable` base constructor.\r\n */\r\n INTERACTIVE: 2\r\n};\r\n\r\n\r\n/**\r\n * @define {number} The monitoring mode of the goog.Disposable\r\n * instances. Default is OFF. Switching on the monitoring is only\r\n * recommended for debugging because it has a significant impact on\r\n * performance and memory usage. If switched off, the monitoring code\r\n * compiles down to 0 bytes.\r\n */\r\ngoog.Disposable.MONITORING_MODE =\r\n goog.define('goog.Disposable.MONITORING_MODE', 0);\r\n\r\n\r\n/**\r\n * @define {boolean} Whether to attach creation stack to each created disposable\r\n * instance; This is only relevant for when MonitoringMode != OFF.\r\n */\r\ngoog.Disposable.INCLUDE_STACK_ON_CREATION =\r\n goog.define('goog.Disposable.INCLUDE_STACK_ON_CREATION', true);\r\n\r\n\r\n/**\r\n * Maps the unique ID of every undisposed `goog.Disposable` object to\r\n * the object itself.\r\n * @type {!Object<number, !goog.Disposable>}\r\n * @private\r\n */\r\ngoog.Disposable.instances_ = {};\r\n\r\n\r\n/**\r\n * @return {!Array<!goog.Disposable>} All `goog.Disposable` objects that\r\n * haven't been disposed of.\r\n */\r\ngoog.Disposable.getUndisposedObjects = function() {\r\n var ret = [];\r\n for (var id in goog.Disposable.instances_) {\r\n if (goog.Disposable.instances_.hasOwnProperty(id)) {\r\n ret.push(goog.Disposable.instances_[Number(id)]);\r\n }\r\n }\r\n return ret;\r\n};\r\n\r\n\r\n/**\r\n * Clears the registry of undisposed objects but doesn't dispose of them.\r\n */\r\ngoog.Disposable.clearUndisposedObjects = function() {\r\n goog.Disposable.instances_ = {};\r\n};\r\n\r\n\r\n/**\r\n * Whether the object has been disposed of.\r\n * @type {boolean}\r\n * @private\r\n */\r\ngoog.Disposable.prototype.disposed_ = false;\r\n\r\n\r\n/**\r\n * Callbacks to invoke when this object is disposed.\r\n * @type {Array<!Function>}\r\n * @private\r\n */\r\ngoog.Disposable.prototype.onDisposeCallbacks_;\r\n\r\n\r\n/**\r\n * @return {boolean} Whether the object has been disposed of.\r\n * @override\r\n */\r\ngoog.Disposable.prototype.isDisposed = function() {\r\n return this.disposed_;\r\n};\r\n\r\n\r\n/**\r\n * @return {boolean} Whether the object has been disposed of.\r\n * @deprecated Use {@link #isDisposed} instead.\r\n */\r\ngoog.Disposable.prototype.getDisposed = goog.Disposable.prototype.isDisposed;\r\n\r\n\r\n/**\r\n * Disposes of the object. If the object hasn't already been disposed of, calls\r\n * {@link #disposeInternal}. Classes that extend `goog.Disposable` should\r\n * override {@link #disposeInternal} in order to delete references to COM\r\n * objects, DOM nodes, and other disposable objects. Reentrant.\r\n *\r\n * @return {void} Nothing.\r\n * @override\r\n */\r\ngoog.Disposable.prototype.dispose = function() {\r\n if (!this.disposed_) {\r\n // Set disposed_ to true first, in case during the chain of disposal this\r\n // gets disposed recursively.\r\n this.disposed_ = true;\r\n this.disposeInternal();\r\n if (goog.Disposable.MONITORING_MODE != goog.Disposable.MonitoringMode.OFF) {\r\n var uid = goog.getUid(this);\r\n if (goog.Disposable.MONITORING_MODE ==\r\n goog.Disposable.MonitoringMode.PERMANENT &&\r\n !goog.Disposable.instances_.hasOwnProperty(uid)) {\r\n throw new Error(\r\n this + ' did not call the goog.Disposable base ' +\r\n 'constructor or was disposed of after a clearUndisposedObjects ' +\r\n 'call');\r\n }\r\n if (goog.Disposable.MONITORING_MODE !=\r\n goog.Disposable.MonitoringMode.OFF &&\r\n this.onDisposeCallbacks_ && this.onDisposeCallbacks_.length > 0) {\r\n throw new Error(\r\n this + ' did not empty its onDisposeCallbacks queue. This ' +\r\n 'probably means it overrode dispose() or disposeInternal() ' +\r\n 'without calling the superclass\\' method.');\r\n }\r\n delete goog.Disposable.instances_[uid];\r\n }\r\n }\r\n};\r\n\r\n\r\n/**\r\n * Associates a disposable object with this object so that they will be disposed\r\n * together.\r\n * @param {goog.disposable.IDisposable} disposable that will be disposed when\r\n * this object is disposed.\r\n */\r\ngoog.Disposable.prototype.registerDisposable = function(disposable) {\r\n this.addOnDisposeCallback(goog.partial(goog.dispose, disposable));\r\n};\r\n\r\n\r\n/**\r\n * Invokes a callback function when this object is disposed. Callbacks are\r\n * invoked in the order in which they were added. If a callback is added to\r\n * an already disposed Disposable, it will be called immediately.\r\n * @param {function(this:T):?} callback The callback function.\r\n * @param {T=} opt_scope An optional scope to call the callback in.\r\n * @template T\r\n */\r\ngoog.Disposable.prototype.addOnDisposeCallback = function(callback, opt_scope) {\r\n if (this.disposed_) {\r\n goog.isDef(opt_scope) ? callback.call(opt_scope) : callback();\r\n return;\r\n }\r\n if (!this.onDisposeCallbacks_) {\r\n this.onDisposeCallbacks_ = [];\r\n }\r\n\r\n this.onDisposeCallbacks_.push(\r\n goog.isDef(opt_scope) ? goog.bind(callback, opt_scope) : callback);\r\n};\r\n\r\n\r\n/**\r\n * Deletes or nulls out any references to COM objects, DOM nodes, or other\r\n * disposable objects. Classes that extend `goog.Disposable` should\r\n * override this method.\r\n * Not reentrant. To avoid calling it twice, it must only be called from the\r\n * subclass' `disposeInternal` method. Everywhere else the public\r\n * `dispose` method must be used.\r\n * For example:\r\n * <pre>\r\n * mypackage.MyClass = function() {\r\n * mypackage.MyClass.base(this, 'constructor');\r\n * // Constructor logic specific to MyClass.\r\n * ...\r\n * };\r\n * goog.inherits(mypackage.MyClass, goog.Disposable);\r\n *\r\n * mypackage.MyClass.prototype.disposeInternal = function() {\r\n * // Dispose logic specific to MyClass.\r\n * ...\r\n * // Call superclass's disposeInternal at the end of the subclass's, like\r\n * // in C++, to avoid hard-to-catch issues.\r\n * mypackage.MyClass.base(this, 'disposeInternal');\r\n * };\r\n * </pre>\r\n * @protected\r\n */\r\ngoog.Disposable.prototype.disposeInternal = function() {\r\n if (this.onDisposeCallbacks_) {\r\n while (this.onDisposeCallbacks_.length) {\r\n this.onDisposeCallbacks_.shift()();\r\n }\r\n }\r\n};\r\n\r\n\r\n/**\r\n * Returns True if we can verify the object is disposed.\r\n * Calls `isDisposed` on the argument if it supports it. If obj\r\n * is not an object with an isDisposed() method, return false.\r\n * @param {*} obj The object to investigate.\r\n * @return {boolean} True if we can verify the object is disposed.\r\n */\r\ngoog.Disposable.isDisposed = function(obj) {\r\n if (obj && typeof obj.isDisposed == 'function') {\r\n return obj.isDisposed();\r\n }\r\n return false;\r\n};\r\n\r\n\r\n/**\r\n * Calls `dispose` on the argument if it supports it. If obj is not an\r\n * object with a dispose() method, this is a no-op.\r\n * @param {*} obj The object to dispose of.\r\n */\r\ngoog.dispose = function(obj) {\r\n if (obj && typeof obj.dispose == 'function') {\r\n obj.dispose();\r\n }\r\n};\r\n\r\n\r\n/**\r\n * Calls `dispose` on each member of the list that supports it. (If the\r\n * member is an ArrayLike, then `goog.disposeAll()` will be called\r\n * recursively on each of its members.) If the member is not an object with a\r\n * `dispose()` method, then it is ignored.\r\n * @param {...*} var_args The list.\r\n */\r\ngoog.disposeAll = function(var_args) {\r\n for (var i = 0, len = arguments.length; i < len; ++i) {\r\n var disposable = arguments[i];\r\n if (goog.isArrayLike(disposable)) {\r\n goog.disposeAll.apply(null, disposable);\r\n } else {\r\n goog.dispose(disposable);\r\n }\r\n }\r\n};\r\n","// Copyright 2006 The Closure Library Authors. All Rights Reserved.\r\n//\r\n// Licensed under the Apache License, Version 2.0 (the \"License\");\r\n// you may not use this file except in compliance with the License.\r\n// You may obtain a copy of the License at\r\n//\r\n// http://www.apache.org/licenses/LICENSE-2.0\r\n//\r\n// Unless required by applicable law or agreed to in writing, software\r\n// distributed under the License is distributed on an \"AS-IS\" BASIS,\r\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n// See the License for the specific language governing permissions and\r\n// limitations under the License.\r\n\r\n/**\r\n * @fileoverview Utilities for manipulating arrays.\r\n *\r\n * @author arv@google.com (Erik Arvidsson)\r\n */\r\n\r\n\r\ngoog.provide('goog.array');\r\n\r\ngoog.require('goog.asserts');\r\n\r\n\r\n/**\r\n * @define {boolean} NATIVE_ARRAY_PROTOTYPES indicates whether the code should\r\n * rely on Array.prototype functions, if available.\r\n *\r\n * The Array.prototype functions can be defined by external libraries like\r\n * Prototype and setting this flag to false forces closure to use its own\r\n * goog.array implementation.\r\n *\r\n * If your javascript can be loaded by a third party site and you are wary about\r\n * relying on the prototype functions, specify\r\n * \"--define goog.NATIVE_ARRAY_PROTOTYPES=false\" to the JSCompiler.\r\n *\r\n * Setting goog.TRUSTED_SITE to false will automatically set\r\n * NATIVE_ARRAY_PROTOTYPES to false.\r\n */\r\ngoog.NATIVE_ARRAY_PROTOTYPES =\r\n goog.define('goog.NATIVE_ARRAY_PROTOTYPES', goog.TRUSTED_SITE);\r\n\r\n\r\n/**\r\n * @define {boolean} If true, JSCompiler will use the native implementation of\r\n * array functions where appropriate (e.g., `Array#filter`) and remove the\r\n * unused pure JS implementation.\r\n */\r\ngoog.array.ASSUME_NATIVE_FUNCTIONS =\r\n goog.define('goog.array.ASSUME_NATIVE_FUNCTIONS', false);\r\n\r\n\r\n/**\r\n * Returns the last element in an array without removing it.\r\n * Same as goog.array.last.\r\n * @param {IArrayLike<T>|string} array The array.\r\n * @return {T} Last item in array.\r\n * @template T\r\n */\r\ngoog.array.peek = function(array) {\r\n return array[array.length - 1];\r\n};\r\n\r\n\r\n/**\r\n * Returns the last element in an array without removing it.\r\n * Same as goog.array.peek.\r\n * @param {IArrayLike<T>|string} array The array.\r\n * @return {T} Last item in array.\r\n * @template T\r\n */\r\ngoog.array.last = goog.array.peek;\r\n\r\n// NOTE(arv): Since most of the array functions are generic it allows you to\r\n// pass an array-like object. Strings have a length and are considered array-\r\n// like. However, the 'in' operator does not work on strings so we cannot just\r\n// use the array path even if the browser supports indexing into strings. We\r\n// therefore end up splitting the string.\r\n\r\n\r\n/**\r\n * Returns the index of the first element of an array with a specified value, or\r\n * -1 if the element is not present in the array.\r\n *\r\n * See {@link http://tinyurl.com/developer-mozilla-org-array-indexof}\r\n *\r\n * @param {IArrayLike<T>|string} arr The array to be searched.\r\n * @param {T} obj The object for which we are searching.\r\n * @param {number=} opt_fromIndex The index at which to start the search. If\r\n * omitted the search starts at index 0.\r\n * @return {number} The index of the first matching array element.\r\n * @template T\r\n */\r\ngoog.array.indexOf = goog.NATIVE_ARRAY_PROTOTYPES &&\r\n (goog.array.ASSUME_NATIVE_FUNCTIONS || Array.prototype.indexOf) ?\r\n function(arr, obj, opt_fromIndex) {\r\n goog.asserts.assert(arr.length != null);\r\n\r\n return Array.prototype.indexOf.call(arr, obj, opt_fromIndex);\r\n } :\r\n function(arr, obj, opt_fromIndex) {\r\n var fromIndex = opt_fromIndex == null ?\r\n 0 :\r\n (opt_fromIndex < 0 ? Math.max(0, arr.length + opt_fromIndex) :\r\n opt_fromIndex);\r\n\r\n if (goog.isString(arr)) {\r\n // Array.prototype.indexOf uses === so only strings should be found.\r\n if (!goog.isString(obj) || obj.length != 1) {\r\n return -1;\r\n }\r\n return arr.indexOf(obj, fromIndex);\r\n }\r\n\r\n for (var i = fromIndex; i < arr.length; i++) {\r\n if (i in arr && arr[i] === obj) return i;\r\n }\r\n return -1;\r\n };\r\n\r\n\r\n/**\r\n * Returns the index of the last element of an array with a specified value, or\r\n * -1 if the element is not present in the array.\r\n *\r\n * See {@link http://tinyurl.com/developer-mozilla-org-array-lastindexof}\r\n *\r\n * @param {!IArrayLike<T>|string} arr The array to be searched.\r\n * @param {T} obj The object for which we are searching.\r\n * @param {?number=} opt_fromIndex The index at which to start the search. If\r\n * omitted the search starts at the end of the array.\r\n * @return {number} The index of the last matching array element.\r\n * @template T\r\n */\r\ngoog.array.lastIndexOf = goog.NATIVE_ARRAY_PROTOTYPES &&\r\n (goog.array.ASSUME_NATIVE_FUNCTIONS || Array.prototype.lastIndexOf) ?\r\n function(arr, obj, opt_fromIndex) {\r\n goog.asserts.assert(arr.length != null);\r\n\r\n // Firefox treats undefined and null as 0 in the fromIndex argument which\r\n // leads it to always return -1\r\n var fromIndex = opt_fromIndex == null ? arr.length - 1 : opt_fromIndex;\r\n return Array.prototype.lastIndexOf.call(arr, obj, fromIndex);\r\n } :\r\n function(arr, obj, opt_fromIndex) {\r\n var fromIndex = opt_fromIndex == null ? arr.length - 1 : opt_fromIndex;\r\n\r\n if (fromIndex < 0) {\r\n fromIndex = Math.max(0, arr.length + fromIndex);\r\n }\r\n\r\n if (goog.isString(arr)) {\r\n // Array.prototype.lastIndexOf uses === so only strings should be found.\r\n if (!goog.isString(obj) || obj.length != 1) {\r\n return -1;\r\n }\r\n return arr.lastIndexOf(obj, fromIndex);\r\n }\r\n\r\n for (var i = fromIndex; i >= 0; i--) {\r\n if (i in arr && arr[i] === obj) return i;\r\n }\r\n return -1;\r\n };\r\n\r\n\r\n/**\r\n * Calls a function for each element in an array. Skips holes in the array.\r\n * See {@link http://tinyurl.com/developer-mozilla-org-array-foreach}\r\n *\r\n * @param {IArrayLike<T>|string} arr Array or array like object over\r\n * which to iterate.\r\n * @param {?function(this: S, T, number, ?): ?} f The function to call for every\r\n * element. This function takes 3 arguments (the element, the index and the\r\n * array). The return value is ignored.\r\n * @param {S=} opt_obj The object to be used as the value of 'this' within f.\r\n * @template T,S\r\n */\r\ngoog.array.forEach = goog.NATIVE_ARRAY_PROTOTYPES &&\r\n (goog.array.ASSUME_NATIVE_FUNCTIONS || Array.prototype.forEach) ?\r\n function(arr, f, opt_obj) {\r\n goog.asserts.assert(arr.length != null);\r\n\r\n Array.prototype.forEach.call(arr, f, opt_obj);\r\n } :\r\n function(arr, f, opt_obj) {\r\n var l = arr.length; // must be fixed during loop... see docs\r\n var arr2 = goog.isString(arr) ? arr.split('') : arr;\r\n for (var i = 0; i < l; i++) {\r\n if (i in arr2) {\r\n f.call(/** @type {?} */ (opt_obj), arr2[i], i, arr);\r\n }\r\n }\r\n };\r\n\r\n\r\n/**\r\n * Calls a function for each element in an array, starting from the last\r\n * element rather than the first.\r\n *\r\n * @param {IArrayLike<T>|string} arr Array or array\r\n * like object over which to iterate.\r\n * @param {?function(this: S, T, number, ?): ?} f The function to call for every\r\n * element. This function\r\n * takes 3 arguments (the element, the index and the array). The return\r\n * value is ignored.\r\n * @param {S=} opt_obj The object to be used as the value of 'this'\r\n * within f.\r\n * @template T,S\r\n */\r\ngoog.array.forEachRight = function(arr, f, opt_obj) {\r\n var l = arr.length; // must be fixed during loop... see docs\r\n var arr2 = goog.isString(arr) ? arr.split('') : arr;\r\n for (var i = l - 1; i >= 0; --i) {\r\n if (i in arr2) {\r\n f.call(/** @type {?} */ (opt_obj), arr2[i], i, arr);\r\n }\r\n }\r\n};\r\n\r\n\r\n/**\r\n * Calls a function for each element in an array, and if the function returns\r\n * true adds the element to a new array.\r\n *\r\n * See {@link http://tinyurl.com/developer-mozilla-org-array-filter}\r\n *\r\n * @param {IArrayLike<T>|string} arr Array or array\r\n * like object over which to iterate.\r\n * @param {?function(this:S, T, number, ?):boolean} f The function to call for\r\n * every element. This function\r\n * takes 3 arguments (the element, the index and the array) and must\r\n * return a Boolean. If the return value is true the element is added to the\r\n * result array. If it is false the element is not included.\r\n * @param {S=} opt_obj The object to be used as the value of 'this'\r\n * within f.\r\n * @return {!Array<T>} a new array in which only elements that passed the test\r\n * are present.\r\n * @template T,S\r\n */\r\ngoog.array.filter = goog.NATIVE_ARRAY_PROTOTYPES &&\r\n (goog.array.ASSUME_NATIVE_FUNCTIONS || Array.prototype.filter) ?\r\n function(arr, f, opt_obj) {\r\n goog.asserts.assert(arr.length != null);\r\n\r\n return Array.prototype.filter.call(arr, f, opt_obj);\r\n } :\r\n function(arr, f, opt_obj) {\r\n var l = arr.length; // must be fixed during loop... see docs\r\n var res = [];\r\n var resLength = 0;\r\n var arr2 = goog.isString(arr) ? arr.split('') : arr;\r\n for (var i = 0; i < l; i++) {\r\n if (i in arr2) {\r\n var val = arr2[i]; // in case f mutates arr2\r\n if (f.call(/** @type {?} */ (opt_obj), val, i, arr)) {\r\n res[resLength++] = val;\r\n }\r\n }\r\n }\r\n return res;\r\n };\r\n\r\n\r\n/**\r\n * Calls a function for each element in an array and inserts the result into a\r\n * new array.\r\n *\r\n * See {@link http://tinyurl.com/developer-mozilla-org-array-map}\r\n *\r\n * @param {IArrayLike<VALUE>|string} arr Array or array like object\r\n * over which to iterate.\r\n * @param {function(this:THIS, VALUE, number, ?): RESULT} f The function to call\r\n * for every element. This function takes 3 arguments (the element,\r\n * the index and the array) and should return something. The result will be\r\n * inserted into a new array.\r\n * @param {THIS=} opt_obj The object to be used as the value of 'this' within f.\r\n * @return {!Array<RESULT>} a new array with the results from f.\r\n * @template THIS, VALUE, RESULT\r\n */\r\ngoog.array.map = goog.NATIVE_ARRAY_PROTOTYPES &&\r\n (goog.array.ASSUME_NATIVE_FUNCTIONS || Array.prototype.map) ?\r\n function(arr, f, opt_obj) {\r\n goog.asserts.assert(arr.length != null);\r\n\r\n return Array.prototype.map.call(arr, f, opt_obj);\r\n } :\r\n function(arr, f, opt_obj) {\r\n var l = arr.length; // must be fixed during loop... see docs\r\n var res = new Array(l);\r\n var arr2 = goog.isString(arr) ? arr.split('') : arr;\r\n for (var i = 0; i < l; i++) {\r\n if (i in arr2) {\r\n res[i] = f.call(/** @type {?} */ (opt_obj), arr2[i], i, arr);\r\n }\r\n }\r\n return res;\r\n };\r\n\r\n\r\n/**\r\n * Passes every element of an array into a function and accumulates the result.\r\n *\r\n * See {@link http://tinyurl.com/developer-mozilla-org-array-reduce}\r\n *\r\n * For example:\r\n * var a = [1, 2, 3, 4];\r\n * goog.array.reduce(a, function(r, v, i, arr) {return r + v;}, 0);\r\n * returns 10\r\n *\r\n * @param {IArrayLike<T>|string} arr Array or array\r\n * like object over which to iterate.\r\n * @param {function(this:S, R, T, number, ?) : R} f The function to call for\r\n * every element. This function\r\n * takes 4 arguments (the function's previous result or the initial value,\r\n * the value of the current array element, the current array index, and the\r\n * array itself)\r\n * function(previousValue, currentValue, index, array).\r\n * @param {?} val The initial value to pass into the function on the first call.\r\n * @param {S=} opt_obj The object to be used as the value of 'this'\r\n * within f.\r\n * @return {R} Result of evaluating f repeatedly across the values of the array.\r\n * @template T,S,R\r\n */\r\ngoog.array.reduce = goog.NATIVE_ARRAY_PROTOTYPES &&\r\n (goog.array.ASSUME_NATIVE_FUNCTIONS || Array.prototype.reduce) ?\r\n function(arr, f, val, opt_obj) {\r\n goog.asserts.assert(arr.length != null);\r\n if (opt_obj) {\r\n f = goog.bind(f, opt_obj);\r\n }\r\n return Array.prototype.reduce.call(arr, f, val);\r\n } :\r\n function(arr, f, val, opt_obj) {\r\n var rval = val;\r\n goog.array.forEach(arr, function(val, index) {\r\n rval = f.call(/** @type {?} */ (opt_obj), rval, val, index, arr);\r\n });\r\n return rval;\r\n };\r\n\r\n\r\n/**\r\n * Passes every element of an array into a function and accumulates the result,\r\n * starting from the last element and working towards the first.\r\n *\r\n * See {@link http://tinyurl.com/developer-mozilla-org-array-reduceright}\r\n *\r\n * For example:\r\n * var a = ['a', 'b', 'c'];\r\n * goog.array.reduceRight(a, function(r, v, i, arr) {return r + v;}, '');\r\n * returns 'cba'\r\n *\r\n * @param {IArrayLike<T>|string} arr Array or array\r\n * like object over which to iterate.\r\n * @param {?function(this:S, R, T, number, ?) : R} f The function to call for\r\n * every element. This function\r\n * takes 4 arguments (the function's previous result or the initial value,\r\n * the value of the current array element, the current array index, and the\r\n * array itself)\r\n * function(previousValue, currentValue, index, array).\r\n * @param {?} val The initial value to pass into the function on the first call.\r\n * @param {S=} opt_obj The object to be used as the value of 'this'\r\n * within f.\r\n * @return {R} Object returned as a result of evaluating f repeatedly across the\r\n * values of the array.\r\n * @template T,S,R\r\n */\r\ngoog.array.reduceRight = goog.NATIVE_ARRAY_PROTOTYPES &&\r\n (goog.array.ASSUME_NATIVE_FUNCTIONS || Array.prototype.reduceRight) ?\r\n function(arr, f, val, opt_obj) {\r\n goog.asserts.assert(arr.length != null);\r\n goog.asserts.assert(f != null);\r\n if (opt_obj) {\r\n f = goog.bind(f, opt_obj);\r\n }\r\n return Array.prototype.reduceRight.call(arr, f, val);\r\n } :\r\n function(arr, f, val, opt_obj) {\r\n var rval = val;\r\n goog.array.forEachRight(arr, function(val, index) {\r\n rval = f.call(/** @type {?} */ (opt_obj), rval, val, index, arr);\r\n });\r\n return rval;\r\n };\r\n\r\n\r\n/**\r\n * Calls f for each element of an array. If any call returns true, some()\r\n * returns true (without checking the remaining elements). If all calls\r\n * return false, some() returns false.\r\n *\r\n * See {@link http://tinyurl.com/developer-mozilla-org-array-some}\r\n *\r\n * @param {IArrayLike<T>|string} arr Array or array\r\n * like object over which to iterate.\r\n * @param {?function(this:S, T, number, ?) : boolean} f The function to call for\r\n * for every element. This function takes 3 arguments (the element, the\r\n * index and the array) and should return a boolean.\r\n * @param {S=} opt_obj The object to be used as the value of 'this'\r\n * within f.\r\n * @return {boolean} true if any element passes the test.\r\n * @template T,S\r\n */\r\ngoog.array.some = goog.NATIVE_ARRAY_PROTOTYPES &&\r\n (goog.array.ASSUME_NATIVE_FUNCTIONS || Array.prototype.some) ?\r\n function(arr, f, opt_obj) {\r\n goog.asserts.assert(arr.length != null);\r\n\r\n return Array.prototype.some.call(arr, f, opt_obj);\r\n } :\r\n function(arr, f, opt_obj) {\r\n var l = arr.length; // must be fixed during loop... see docs\r\n var arr2 = goog.isString(arr) ? arr.split('') : arr;\r\n for (var i = 0; i < l; i++) {\r\n if (i in arr2 && f.call(/** @type {?} */ (opt_obj), arr2[i], i, arr)) {\r\n return true;\r\n }\r\n }\r\n return false;\r\n };\r\n\r\n\r\n/**\r\n * Call f for each element of an array. If all calls return true, every()\r\n * returns true. If any call returns false, every() returns false and\r\n * does not continue to check the remaining elements.\r\n *\r\n * See {@link http://tinyurl.com/developer-mozilla-org-array-every}\r\n *\r\n * @param {IArrayLike<T>|string} arr Array or array\r\n * like object over which to iterate.\r\n * @param {?function(this:S, T, number, ?) : boolean} f The function to call for\r\n * for every element. This function takes 3 arguments (the element, the\r\n * index and the array) and should return a boolean.\r\n * @param {S=} opt_obj The object to be used as the value of 'this'\r\n * within f.\r\n * @return {boolean} false if any element fails the test.\r\n * @template T,S\r\n */\r\ngoog.array.every = goog.NATIVE_ARRAY_PROTOTYPES &&\r\n (goog.array.ASSUME_NATIVE_FUNCTIONS || Array.prototype.every) ?\r\n function(arr, f, opt_obj) {\r\n goog.asserts.assert(arr.length != null);\r\n\r\n return Array.prototype.every.call(arr, f, opt_obj);\r\n } :\r\n function(arr, f, opt_obj) {\r\n var l = arr.length; // must be fixed during loop... see docs\r\n var arr2 = goog.isString(arr) ? arr.split('') : arr;\r\n for (var i = 0; i < l; i++) {\r\n if (i in arr2 && !f.call(/** @type {?} */ (opt_obj), arr2[i], i, arr)) {\r\n return false;\r\n }\r\n }\r\n return true;\r\n };\r\n\r\n\r\n/**\r\n * Counts the array elements that fulfill the predicate, i.e. for which the\r\n * callback function returns true. Skips holes in the array.\r\n *\r\n * @param {!IArrayLike<T>|string} arr Array or array like object\r\n * over which to iterate.\r\n * @param {function(this: S, T, number, ?): boolean} f The function to call for\r\n * every element. Takes 3 arguments (the element, the index and the array).\r\n * @param {S=} opt_obj The object to be used as the value of 'this' within f.\r\n * @return {number} The number of the matching elements.\r\n * @template T,S\r\n */\r\ngoog.array.count = function(arr, f, opt_obj) {\r\n var count = 0;\r\n goog.array.forEach(arr, function(element, index, arr) {\r\n if (f.call(/** @type {?} */ (opt_obj), element, index, arr)) {\r\n ++count;\r\n }\r\n }, opt_obj);\r\n return count;\r\n};\r\n\r\n\r\n/**\r\n * Search an array for the first element that satisfies a given condition and\r\n * return that element.\r\n * @param {IArrayLike<T>|string} arr Array or array\r\n * like object over which to iterate.\r\n * @param {?function(this:S, T, number, ?) : boolean} f The function to call\r\n * for every element. This function takes 3 arguments (the element, the\r\n * index and the array) and should return a boolean.\r\n * @param {S=} opt_obj An optional \"this\" context for the function.\r\n * @return {T|null} The first array element that passes the test, or null if no\r\n * element is found.\r\n * @template T,S\r\n */\r\ngoog.array.find = function(arr, f, opt_obj) {\r\n var i = goog.array.findIndex(arr, f, opt_obj);\r\n return i < 0 ? null : goog.isString(arr) ? arr.charAt(i) : arr[i];\r\n};\r\n\r\n\r\n/**\r\n * Search an array for the first element that satisfies a given condition and\r\n * return its index.\r\n * @param {IArrayLike<T>|string} arr Array or array\r\n * like object over which to iterate.\r\n * @param {?function(this:S, T, number, ?) : boolean} f The function to call for\r\n * every element. This function\r\n * takes 3 arguments (the element, the index and the array) and should\r\n * return a boolean.\r\n * @param {S=} opt_obj An optional \"this\" context for the function.\r\n * @return {number} The index of the first array element that passes the test,\r\n * or -1 if no element is found.\r\n * @template T,S\r\n */\r\ngoog.array.findIndex = function(arr, f, opt_obj) {\r\n var l = arr.length; // must be fixed during loop... see docs\r\n var arr2 = goog.isString(arr) ? arr.split('') : arr;\r\n for (var i = 0; i < l; i++) {\r\n if (i in arr2 && f.call(/** @type {?} */ (opt_obj), arr2[i], i, arr)) {\r\n return i;\r\n }\r\n }\r\n return -1;\r\n};\r\n\r\n\r\n/**\r\n * Search an array (in reverse order) for the last element that satisfies a\r\n * given condition and return that element.\r\n * @param {IArrayLike<T>|string} arr Array or array\r\n * like object over which to iterate.\r\n * @param {?function(this:S, T, number, ?) : boolean} f The function to call\r\n * for every element. This function\r\n * takes 3 arguments (the element, the index and the array) and should\r\n * return a boolean.\r\n * @param {S=} opt_obj An optional \"this\" context for the function.\r\n * @return {T|null} The last array element that passes the test, or null if no\r\n * element is found.\r\n * @template T,S\r\n */\r\ngoog.array.findRight = function(arr, f, opt_obj) {\r\n var i = goog.array.findIndexRight(arr, f, opt_obj);\r\n return i < 0 ? null : goog.isString(arr) ? arr.charAt(i) : arr[i];\r\n};\r\n\r\n\r\n/**\r\n * Search an array (in reverse order) for the last element that satisfies a\r\n * given condition and return its index.\r\n * @param {IArrayLike<T>|string} arr Array or array\r\n * like object over which to iterate.\r\n * @param {?function(this:S, T, number, ?) : boolean} f The function to call\r\n * for every element. This function\r\n * takes 3 arguments (the element, the index and the array) and should\r\n * return a boolean.\r\n * @param {S=} opt_obj An optional \"this\" context for the function.\r\n * @return {number} The index of the last array element that passes the test,\r\n * or -1 if no element is found.\r\n * @template T,S\r\n */\r\ngoog.array.findIndexRight = function(arr, f, opt_obj) {\r\n var l = arr.length; // must be fixed during loop... see docs\r\n var arr2 = goog.isString(arr) ? arr.split('') : arr;\r\n for (var i = l - 1; i >= 0; i--) {\r\n if (i in arr2 && f.call(/** @type {?} */ (opt_obj), arr2[i], i, arr)) {\r\n return i;\r\n }\r\n }\r\n return -1;\r\n};\r\n\r\n\r\n/**\r\n * Whether the array contains the given object.\r\n * @param {IArrayLike<?>|string} arr The array to test for the presence of the\r\n * element.\r\n * @param {*} obj The object for which to test.\r\n * @return {boolean} true if obj is present.\r\n */\r\ngoog.array.contains = function(arr, obj) {\r\n return goog.array.indexOf(arr, obj) >= 0;\r\n};\r\n\r\n\r\n/**\r\n * Whether the array is empty.\r\n * @param {IArrayLike<?>|string} arr The array to test.\r\n * @return {boolean} true if empty.\r\n */\r\ngoog.array.isEmpty = function(arr) {\r\n return arr.length == 0;\r\n};\r\n\r\n\r\n/**\r\n * Clears the array.\r\n * @param {IArrayLike<?>} arr Array or array like object to clear.\r\n */\r\ngoog.array.clear = function(arr) {\r\n // For non real arrays we don't have the magic length so we delete the\r\n // indices.\r\n if (!goog.isArray(arr)) {\r\n for (var i = arr.length - 1; i >= 0; i--) {\r\n delete arr[i];\r\n }\r\n }\r\n arr.length = 0;\r\n};\r\n\r\n\r\n/**\r\n * Pushes an item into an array, if it's not already in the array.\r\n * @param {Array<T>} arr Array into which to insert the item.\r\n * @param {T} obj Value to add.\r\n * @template T\r\n */\r\ngoog.array.insert = function(arr, obj) {\r\n if (!goog.array.contains(arr, obj)) {\r\n arr.push(obj);\r\n }\r\n};\r\n\r\n\r\n/**\r\n * Inserts an object at the given index of the array.\r\n * @param {IArrayLike<?>} arr The array to modify.\r\n * @param {*} obj The object to insert.\r\n * @param {number=} opt_i The index at which to insert the object. If omitted,\r\n * treated as 0. A negative index is counted from the end of the array.\r\n */\r\ngoog.array.insertAt = function(arr, obj, opt_i) {\r\n goog.array.splice(arr, opt_i, 0, obj);\r\n};\r\n\r\n\r\n/**\r\n * Inserts at the given index of the array, all elements of another array.\r\n * @param {IArrayLike<?>} arr The array to modify.\r\n * @param {IArrayLike<?>} elementsToAdd The array of elements to add.\r\n * @param {number=} opt_i The index at which to insert the object. If omitted,\r\n * treated as 0. A negative index is counted from the end of the array.\r\n */\r\ngoog.array.insertArrayAt = function(arr, elementsToAdd, opt_i) {\r\n goog.partial(goog.array.splice, arr, opt_i, 0).apply(null, elementsToAdd);\r\n};\r\n\r\n\r\n/**\r\n * Inserts an object into an array before a specified object.\r\n * @param {Array<T>} arr The array to modify.\r\n * @param {T} obj The object to insert.\r\n * @param {T=} opt_obj2 The object before which obj should be inserted. If obj2\r\n * is omitted or not found, obj is inserted at the end of the array.\r\n * @template T\r\n */\r\ngoog.array.insertBefore = function(arr, obj, opt_obj2) {\r\n var i;\r\n if (arguments.length == 2 || (i = goog.array.indexOf(arr, opt_obj2)) < 0) {\r\n arr.push(obj);\r\n } else {\r\n goog.array.insertAt(arr, obj, i);\r\n }\r\n};\r\n\r\n\r\n/**\r\n * Removes the first occurrence of a particular value from an array.\r\n * @param {IArrayLike<T>} arr Array from which to remove\r\n * value.\r\n * @param {T} obj Object to remove.\r\n * @return {boolean} True if an element was removed.\r\n * @template T\r\n */\r\ngoog.array.remove = function(arr, obj) {\r\n var i = goog.array.indexOf(arr, obj);\r\n var rv;\r\n if ((rv = i >= 0)) {\r\n goog.array.removeAt(arr, i);\r\n }\r\n return rv;\r\n};\r\n\r\n\r\n/**\r\n * Removes the last occurrence of a particular value from an array.\r\n * @param {!IArrayLike<T>} arr Array from which to remove value.\r\n * @param {T} obj Object to remove.\r\n * @return {boolean} True if an element was removed.\r\n * @template T\r\n */\r\ngoog.array.removeLast = function(arr, obj) {\r\n var i = goog.array.lastIndexOf(arr, obj);\r\n if (i >= 0) {\r\n goog.array.removeAt(arr, i);\r\n return true;\r\n }\r\n return false;\r\n};\r\n\r\n\r\n/**\r\n * Removes from an array the element at index i\r\n * @param {IArrayLike<?>} arr Array or array like object from which to\r\n * remove value.\r\n * @param {number} i The index to remove.\r\n * @return {boolean} True if an element was removed.\r\n */\r\ngoog.array.removeAt = function(arr, i) {\r\n goog.asserts.assert(arr.length != null);\r\n\r\n // use generic form of splice\r\n // splice returns the removed items and if successful the length of that\r\n // will be 1\r\n return Array.prototype.splice.call(arr, i, 1).length == 1;\r\n};\r\n\r\n\r\n/**\r\n * Removes the first value that satisfies the given condition.\r\n * @param {IArrayLike<T>} arr Array or array\r\n * like object over which to iterate.\r\n * @param {?function(this:S, T, number, ?) : boolean} f The function to call\r\n * for every element. This function\r\n * takes 3 arguments (the element, the index and the array) and should\r\n * return a boolean.\r\n * @param {S=} opt_obj An optional \"this\" context for the function.\r\n * @return {boolean} True if an element was removed.\r\n * @template T,S\r\n */\r\ngoog.array.removeIf = function(arr, f, opt_obj) {\r\n var i = goog.array.findIndex(arr, f, opt_obj);\r\n if (i >= 0) {\r\n goog.array.removeAt(arr, i);\r\n return true;\r\n }\r\n return false;\r\n};\r\n\r\n\r\n/**\r\n * Removes all values that satisfy the given condition.\r\n * @param {IArrayLike<T>} arr Array or array\r\n * like object over which to iterate.\r\n * @param {?function(this:S, T, number, ?) : boolean} f The function to call\r\n * for every element. This function\r\n * takes 3 arguments (the element, the index and the array) and should\r\n * return a boolean.\r\n * @param {S=} opt_obj An optional \"this\" context for the function.\r\n * @return {number} The number of items removed\r\n * @template T,S\r\n */\r\ngoog.array.removeAllIf = function(arr, f, opt_obj) {\r\n var removedCount = 0;\r\n goog.array.forEachRight(arr, function(val, index) {\r\n if (f.call(/** @type {?} */ (opt_obj), val, index, arr)) {\r\n if (goog.array.removeAt(arr, index)) {\r\n removedCount++;\r\n }\r\n }\r\n });\r\n return removedCount;\r\n};\r\n\r\n\r\n/**\r\n * Returns a new array that is the result of joining the arguments. If arrays\r\n * are passed then their items are added, however, if non-arrays are passed they\r\n * will be added to the return array as is.\r\n *\r\n * Note that ArrayLike objects will be added as is, rather than having their\r\n * items added.\r\n *\r\n * goog.array.concat([1, 2], [3, 4]) -> [1, 2, 3, 4]\r\n * goog.array.concat(0, [1, 2]) -> [0, 1, 2]\r\n * goog.array.concat([1, 2], null) -> [1, 2, null]\r\n *\r\n * There is bug in all current versions of IE (6, 7 and 8) where arrays created\r\n * in an iframe become corrupted soon (not immediately) after the iframe is\r\n * destroyed. This is common if loading data via goog.net.IframeIo, for example.\r\n * This corruption only affects the concat method which will start throwing\r\n * Catastrophic Errors (#-2147418113).\r\n *\r\n * See http://endoflow.com/scratch/corrupted-arrays.html for a test case.\r\n *\r\n * Internally goog.array should use this, so that all methods will continue to\r\n * work on these broken array objects.\r\n *\r\n * @param {...*} var_args Items to concatenate. Arrays will have each item\r\n * added, while primitives and objects will be added as is.\r\n * @return {!Array<?>} The new resultant array.\r\n */\r\ngoog.array.concat = function(var_args) {\r\n return Array.prototype.concat.apply([], arguments);\r\n};\r\n\r\n\r\n/**\r\n * Returns a new array that contains the contents of all the arrays passed.\r\n * @param {...!Array<T>} var_args\r\n * @return {!Array<T>}\r\n * @template T\r\n */\r\ngoog.array.join = function(var_args) {\r\n return Array.prototype.concat.apply([], arguments);\r\n};\r\n\r\n\r\n/**\r\n * Converts an object to an array.\r\n * @param {IArrayLike<T>|string} object The object to convert to an\r\n * array.\r\n * @return {!Array<T>} The object converted into an array. If object has a\r\n * length property, every property indexed with a non-negative number\r\n * less than length will be included in the result. If object does not\r\n * have a length property, an empty array will be returned.\r\n * @template T\r\n */\r\ngoog.array.toArray = function(object) {\r\n var length = object.length;\r\n\r\n // If length is not a number the following is false. This case is kept for\r\n // backwards compatibility since there are callers that pass objects that are\r\n // not array like.\r\n if (length > 0) {\r\n var rv = new Array(length);\r\n for (var i = 0; i < length; i++) {\r\n rv[i] = object[i];\r\n }\r\n return rv;\r\n }\r\n return [];\r\n};\r\n\r\n\r\n/**\r\n * Does a shallow copy of an array.\r\n * @param {IArrayLike<T>|string} arr Array or array-like object to\r\n * clone.\r\n * @return {!Array<T>} Clone of the input array.\r\n * @template T\r\n */\r\ngoog.array.clone = goog.array.toArray;\r\n\r\n\r\n/**\r\n * Extends an array with another array, element, or \"array like\" object.\r\n * This function operates 'in-place', it does not create a new Array.\r\n *\r\n * Example:\r\n * var a = [];\r\n * goog.array.extend(a, [0, 1]);\r\n * a; // [0, 1]\r\n * goog.array.extend(a, 2);\r\n * a; // [0, 1, 2]\r\n *\r\n * @param {Array<VALUE>} arr1 The array to modify.\r\n * @param {...(IArrayLike<VALUE>|VALUE)} var_args The elements or arrays of\r\n * elements to add to arr1.\r\n * @template VALUE\r\n */\r\ngoog.array.extend = function(arr1, var_args) {\r\n for (var i = 1; i < arguments.length; i++) {\r\n var arr2 = arguments[i];\r\n if (goog.isArrayLike(arr2)) {\r\n var len1 = arr1.length || 0;\r\n var len2 = arr2.length || 0;\r\n arr1.length = len1 + len2;\r\n for (var j = 0; j < len2; j++) {\r\n arr1[len1 + j] = arr2[j];\r\n }\r\n } else {\r\n arr1.push(arr2);\r\n }\r\n }\r\n};\r\n\r\n\r\n/**\r\n * Adds or removes elements from an array. This is a generic version of Array\r\n * splice. This means that it might work on other objects similar to arrays,\r\n * such as the arguments object.\r\n *\r\n * @param {IArrayLike<T>} arr The array to modify.\r\n * @param {number|undefined} index The index at which to start changing the\r\n * array. If not defined, treated as 0.\r\n * @param {number} howMany How many elements to remove (0 means no removal. A\r\n * value below 0 is treated as zero and so is any other non number. Numbers\r\n * are floored).\r\n * @param {...T} var_args Optional, additional elements to insert into the\r\n * array.\r\n * @return {!Array<T>} the removed elements.\r\n * @template T\r\n */\r\ngoog.array.splice = function(arr, index, howMany, var_args) {\r\n goog.asserts.assert(arr.length != null);\r\n\r\n return Array.prototype.splice.apply(arr, goog.array.slice(arguments, 1));\r\n};\r\n\r\n\r\n/**\r\n * Returns a new array from a segment of an array. This is a generic version of\r\n * Array slice. This means that it might work on other objects similar to\r\n * arrays, such as the arguments object.\r\n *\r\n * @param {IArrayLike<T>|string} arr The array from\r\n * which to copy a segment.\r\n * @param {number} start The index of the first element to copy.\r\n * @param {number=} opt_end The index after the last element to copy.\r\n * @return {!Array<T>} A new array containing the specified segment of the\r\n * original array.\r\n * @template T\r\n */\r\ngoog.array.slice = function(arr, start, opt_end) {\r\n goog.asserts.assert(arr.length != null);\r\n\r\n // passing 1 arg to slice is not the same as passing 2 where the second is\r\n // null or undefined (in that case the second argument is treated as 0).\r\n // we could use slice on the arguments object and then use apply instead of\r\n // testing the length\r\n if (arguments.length <= 2) {\r\n return Array.prototype.slice.call(arr, start);\r\n } else {\r\n return Array.prototype.slice.call(arr, start, opt_end);\r\n }\r\n};\r\n\r\n\r\n/**\r\n * Removes all duplicates from an array (retaining only the first\r\n * occurrence of each array element). This function modifies the\r\n * array in place and doesn't change the order of the non-duplicate items.\r\n *\r\n * For objects, duplicates are identified as having the same unique ID as\r\n * defined by {@link goog.getUid}.\r\n *\r\n * Alternatively you can specify a custom hash function that returns a unique\r\n * value for each item in the array it should consider unique.\r\n *\r\n * Runtime: N,\r\n * Worstcase space: 2N (no dupes)\r\n *\r\n * @param {IArrayLike<T>} arr The array from which to remove\r\n * duplicates.\r\n * @param {Array=} opt_rv An optional array in which to return the results,\r\n * instead of performing the removal inplace. If specified, the original\r\n * array will remain unchanged.\r\n * @param {function(T):string=} opt_hashFn An optional function to use to\r\n * apply to every item in the array. This function should return a unique\r\n * value for each item in the array it should consider unique.\r\n * @template T\r\n */\r\ngoog.array.removeDuplicates = function(arr, opt_rv, opt_hashFn) {\r\n var returnArray = opt_rv || arr;\r\n var defaultHashFn = function(item) {\r\n // Prefix each type with a single character representing the type to\r\n // prevent conflicting keys (e.g. true and 'true').\r\n return goog.isObject(item) ? 'o' + goog.getUid(item) :\r\n (typeof item).charAt(0) + item;\r\n };\r\n var hashFn = opt_hashFn || defaultHashFn;\r\n\r\n var seen = {}, cursorInsert = 0, cursorRead = 0;\r\n while (cursorRead < arr.length) {\r\n var current = arr[cursorRead++];\r\n var key = hashFn(current);\r\n if (!Object.prototype.hasOwnProperty.call(seen, key)) {\r\n seen[key] = true;\r\n returnArray[cursorInsert++] = current;\r\n }\r\n }\r\n returnArray.length = cursorInsert;\r\n};\r\n\r\n\r\n/**\r\n * Searches the specified array for the specified target using the binary\r\n * search algorithm. If no opt_compareFn is specified, elements are compared\r\n * using <code>goog.array.defaultCompare</code>, which compares the elements\r\n * using the built in < and > operators. This will produce the expected\r\n * behavior for homogeneous arrays of String(s) and Number(s). The array\r\n * specified <b>must</b> be sorted in ascending order (as defined by the\r\n * comparison function). If the array is not sorted, results are undefined.\r\n * If the array contains multiple instances of the specified target value, any\r\n * of these instances may be found.\r\n *\r\n * Runtime: O(log n)\r\n *\r\n * @param {IArrayLike<VALUE>} arr The array to be searched.\r\n * @param {TARGET} target The sought value.\r\n * @param {function(TARGET, VALUE): number=} opt_compareFn Optional comparison\r\n * function by which the array is ordered. Should take 2 arguments to\r\n * compare, the target value and an element from your array, and return a\r\n * negative number, zero, or a positive number depending on whether the\r\n * first argument is less than, equal to, or greater than the second.\r\n * @return {number} Lowest index of the target value if found, otherwise\r\n * (-(insertion point) - 1). The insertion point is where the value should\r\n * be inserted into arr to preserve the sorted property. Return value >= 0\r\n * iff target is found.\r\n * @template TARGET, VALUE\r\n */\r\ngoog.array.binarySearch = function(arr, target, opt_compareFn) {\r\n return goog.array.binarySearch_(\r\n arr, opt_compareFn || goog.array.defaultCompare, false /* isEvaluator */,\r\n target);\r\n};\r\n\r\n\r\n/**\r\n * Selects an index in the specified array using the binary search algorithm.\r\n * The evaluator receives an element and determines whether the desired index\r\n * is before, at, or after it. The evaluator must be consistent (formally,\r\n * goog.array.map(goog.array.map(arr, evaluator, opt_obj), goog.math.sign)\r\n * must be monotonically non-increasing).\r\n *\r\n * Runtime: O(log n)\r\n *\r\n * @param {IArrayLike<VALUE>} arr The array to be searched.\r\n * @param {function(this:THIS, VALUE, number, ?): number} evaluator\r\n * Evaluator function that receives 3 arguments (the element, the index and\r\n * the array). Should return a negative number, zero, or a positive number\r\n * depending on whether the desired index is before, at, or after the\r\n * element passed to it.\r\n * @param {THIS=} opt_obj The object to be used as the value of 'this'\r\n * within evaluator.\r\n * @return {number} Index of the leftmost element matched by the evaluator, if\r\n * such exists; otherwise (-(insertion point) - 1). The insertion point is\r\n * the index of the first element for which the evaluator returns negative,\r\n * or arr.length if no such element exists. The return value is non-negative\r\n * iff a match is found.\r\n * @template THIS, VALUE\r\n */\r\ngoog.array.binarySelect = function(arr, evaluator, opt_obj) {\r\n return goog.array.binarySearch_(\r\n arr, evaluator, true /* isEvaluator */, undefined /* opt_target */,\r\n opt_obj);\r\n};\r\n\r\n\r\n/**\r\n * Implementation of a binary search algorithm which knows how to use both\r\n * comparison functions and evaluators. If an evaluator is provided, will call\r\n * the evaluator with the given optional data object, conforming to the\r\n * interface defined in binarySelect. Otherwise, if a comparison function is\r\n * provided, will call the comparison function against the given data object.\r\n *\r\n * This implementation purposefully does not use goog.bind or goog.partial for\r\n * performance reasons.\r\n *\r\n * Runtime: O(log n)\r\n *\r\n * @param {IArrayLike<?>} arr The array to be searched.\r\n * @param {function(?, ?, ?): number | function(?, ?): number} compareFn\r\n * Either an evaluator or a comparison function, as defined by binarySearch\r\n * and binarySelect above.\r\n * @param {boolean} isEvaluator Whether the function is an evaluator or a\r\n * comparison function.\r\n * @param {?=} opt_target If the function is a comparison function, then\r\n * this is the target to binary search for.\r\n * @param {Object=} opt_selfObj If the function is an evaluator, this is an\r\n * optional this object for the evaluator.\r\n * @return {number} Lowest index of the target value if found, otherwise\r\n * (-(insertion point) - 1). The insertion point is where the value should\r\n * be inserted into arr to preserve the sorted property. Return value >= 0\r\n * iff target is found.\r\n * @private\r\n */\r\ngoog.array.binarySearch_ = function(\r\n arr, compareFn, isEvaluator, opt_target, opt_selfObj) {\r\n var left = 0; // inclusive\r\n var right = arr.length; // exclusive\r\n var found;\r\n while (left < right) {\r\n var middle = (left + right) >> 1;\r\n var compareResult;\r\n if (isEvaluator) {\r\n compareResult = compareFn.call(opt_selfObj, arr[middle], middle, arr);\r\n } else {\r\n // NOTE(dimvar): To avoid this cast, we'd have to use function overloading\r\n // for the type of binarySearch_, which the type system can't express yet.\r\n compareResult = /** @type {function(?, ?): number} */ (compareFn)(\r\n opt_target, arr[middle]);\r\n }\r\n if (compareResult > 0) {\r\n left = middle + 1;\r\n } else {\r\n right = middle;\r\n // We are looking for the lowest index so we can't return immediately.\r\n found = !compareResult;\r\n }\r\n }\r\n // left is the index if found, or the insertion point otherwise.\r\n // ~left is a shorthand for -left - 1.\r\n return found ? left : ~left;\r\n};\r\n\r\n\r\n/**\r\n * Sorts the specified array into ascending order. If no opt_compareFn is\r\n * specified, elements are compared using\r\n * <code>goog.array.defaultCompare</code>, which compares the elements using\r\n * the built in < and > operators. This will produce the expected behavior\r\n * for homogeneous arrays of String(s) and Number(s), unlike the native sort,\r\n * but will give unpredictable results for heterogeneous lists of strings and\r\n * numbers with different numbers of digits.\r\n *\r\n * This sort is not guaranteed to be stable.\r\n *\r\n * Runtime: Same as <code>Array.prototype.sort</code>\r\n *\r\n * @param {Array<T>} arr The array to be sorted.\r\n * @param {?function(T,T):number=} opt_compareFn Optional comparison\r\n * function by which the\r\n * array is to be ordered. Should take 2 arguments to compare, and return a\r\n * negative number, zero, or a positive number depending on whether the\r\n * first argument is less than, equal to, or greater than the second.\r\n * @template T\r\n */\r\ngoog.array.sort = function(arr, opt_compareFn) {\r\n // TODO(arv): Update type annotation since null is not accepted.\r\n arr.sort(opt_compareFn || goog.array.defaultCompare);\r\n};\r\n\r\n\r\n/**\r\n * Sorts the specified array into ascending order in a stable way. If no\r\n * opt_compareFn is specified, elements are compared using\r\n * <code>goog.array.defaultCompare</code>, which compares the elements using\r\n * the built in < and > operators. This will produce the expected behavior\r\n * for homogeneous arrays of String(s) and Number(s).\r\n *\r\n * Runtime: Same as <code>Array.prototype.sort</code>, plus an additional\r\n * O(n) overhead of copying the array twice.\r\n *\r\n * @param {Array<T>} arr The array to be sorted.\r\n * @param {?function(T, T): number=} opt_compareFn Optional comparison function\r\n * by which the array is to be ordered. Should take 2 arguments to compare,\r\n * and return a negative number, zero, or a positive number depending on\r\n * whether the first argument is less than, equal to, or greater than the\r\n * second.\r\n * @template T\r\n */\r\ngoog.array.stableSort = function(arr, opt_compareFn) {\r\n var compArr = new Array(arr.length);\r\n for (var i = 0; i < arr.length; i++) {\r\n compArr[i] = {index: i, value: arr[i]};\r\n }\r\n var valueCompareFn = opt_compareFn || goog.array.defaultCompare;\r\n function stableCompareFn(obj1, obj2) {\r\n return valueCompareFn(obj1.value, obj2.value) || obj1.index - obj2.index;\r\n }\r\n goog.array.sort(compArr, stableCompareFn);\r\n for (var i = 0; i < arr.length; i++) {\r\n arr[i] = compArr[i].value;\r\n }\r\n};\r\n\r\n\r\n/**\r\n * Sort the specified array into ascending order based on item keys\r\n * returned by the specified key function.\r\n * If no opt_compareFn is specified, the keys are compared in ascending order\r\n * using <code>goog.array.defaultCompare</code>.\r\n *\r\n * Runtime: O(S(f(n)), where S is runtime of <code>goog.array.sort</code>\r\n * and f(n) is runtime of the key function.\r\n *\r\n * @param {Array<T>} arr The array to be sorted.\r\n * @param {function(T): K} keyFn Function taking array element and returning\r\n * a key used for sorting this element.\r\n * @param {?function(K, K): number=} opt_compareFn Optional comparison function\r\n * by which the keys are to be ordered. Should take 2 arguments to compare,\r\n * and return a negative number, zero, or a positive number depending on\r\n * whether the first argument is less than, equal to, or greater than the\r\n * second.\r\n * @template T,K\r\n */\r\ngoog.array.sortByKey = function(arr, keyFn, opt_compareFn) {\r\n var keyCompareFn = opt_compareFn || goog.array.defaultCompare;\r\n goog.array.sort(\r\n arr, function(a, b) { return keyCompareFn(keyFn(a), keyFn(b)); });\r\n};\r\n\r\n\r\n/**\r\n * Sorts an array of objects by the specified object key and compare\r\n * function. If no compare function is provided, the key values are\r\n * compared in ascending order using <code>goog.array.defaultCompare</code>.\r\n * This won't work for keys that get renamed by the compiler. So use\r\n * {'foo': 1, 'bar': 2} rather than {foo: 1, bar: 2}.\r\n * @param {Array<Object>} arr An array of objects to sort.\r\n * @param {string} key The object key to sort by.\r\n * @param {Function=} opt_compareFn The function to use to compare key\r\n * values.\r\n */\r\ngoog.array.sortObjectsByKey = function(arr, key, opt_compareFn) {\r\n goog.array.sortByKey(arr, function(obj) { return obj[key]; }, opt_compareFn);\r\n};\r\n\r\n\r\n/**\r\n * Tells if the array is sorted.\r\n * @param {!IArrayLike<T>} arr The array.\r\n * @param {?function(T,T):number=} opt_compareFn Function to compare the\r\n * array elements.\r\n * Should take 2 arguments to compare, and return a negative number, zero,\r\n * or a positive number depending on whether the first argument is less\r\n * than, equal to, or greater than the second.\r\n * @param {boolean=} opt_strict If true no equal elements are allowed.\r\n * @return {boolean} Whether the array is sorted.\r\n * @template T\r\n */\r\ngoog.array.isSorted = function(arr, opt_compareFn, opt_strict) {\r\n var compare = opt_compareFn || goog.array.defaultCompare;\r\n for (var i = 1; i < arr.length; i++) {\r\n var compareResult = compare(arr[i - 1], arr[i]);\r\n if (compareResult > 0 || compareResult == 0 && opt_strict) {\r\n return false;\r\n }\r\n }\r\n return true;\r\n};\r\n\r\n\r\n/**\r\n * Compares two arrays for equality. Two arrays are considered equal if they\r\n * have the same length and their corresponding elements are equal according to\r\n * the comparison function.\r\n *\r\n * @param {IArrayLike<?>} arr1 The first array to compare.\r\n * @param {IArrayLike<?>} arr2 The second array to compare.\r\n * @param {Function=} opt_equalsFn Optional comparison function.\r\n * Should take 2 arguments to compare, and return true if the arguments\r\n * are equal. Defaults to {@link goog.array.defaultCompareEquality} which\r\n * compares the elements using the built-in '===' operator.\r\n * @return {boolean} Whether the two arrays are equal.\r\n */\r\ngoog.array.equals = function(arr1, arr2, opt_equalsFn) {\r\n if (!goog.isArrayLike(arr1) || !goog.isArrayLike(arr2) ||\r\n arr1.length != arr2.length) {\r\n return false;\r\n }\r\n var l = arr1.length;\r\n var equalsFn = opt_equalsFn || goog.array.defaultCompareEquality;\r\n for (var i = 0; i < l; i++) {\r\n if (!equalsFn(arr1[i], arr2[i])) {\r\n return false;\r\n }\r\n }\r\n return true;\r\n};\r\n\r\n\r\n/**\r\n * 3-way array compare function.\r\n * @param {!IArrayLike<VALUE>} arr1 The first array to\r\n * compare.\r\n * @param {!IArrayLike<VALUE>} arr2 The second array to\r\n * compare.\r\n * @param {function(VALUE, VALUE): number=} opt_compareFn Optional comparison\r\n * function by which the array is to be ordered. Should take 2 arguments to\r\n * compare, and return a negative number, zero, or a positive number\r\n * depending on whether the first argument is less than, equal to, or\r\n * greater than the second.\r\n * @return {number} Negative number, zero, or a positive number depending on\r\n * whether the first argument is less than, equal to, or greater than the\r\n * second.\r\n * @template VALUE\r\n */\r\ngoog.array.compare3 = function(arr1, arr2, opt_compareFn) {\r\n var compare = opt_compareFn || goog.array.defaultCompare;\r\n var l = Math.min(arr1.length, arr2.length);\r\n for (var i = 0; i < l; i++) {\r\n var result = compare(arr1[i], arr2[i]);\r\n if (result != 0) {\r\n return result;\r\n }\r\n }\r\n return goog.array.defaultCompare(arr1.length, arr2.length);\r\n};\r\n\r\n\r\n/**\r\n * Compares its two arguments for order, using the built in < and >\r\n * operators.\r\n * @param {VALUE} a The first object to be compared.\r\n * @param {VALUE} b The second object to be compared.\r\n * @return {number} A negative number, zero, or a positive number as the first\r\n * argument is less than, equal to, or greater than the second,\r\n * respectively.\r\n * @template VALUE\r\n */\r\ngoog.array.defaultCompare = function(a, b) {\r\n return a > b ? 1 : a < b ? -1 : 0;\r\n};\r\n\r\n\r\n/**\r\n * Compares its two arguments for inverse order, using the built in < and >\r\n * operators.\r\n * @param {VALUE} a The first object to be compared.\r\n * @param {VALUE} b The second object to be compared.\r\n * @return {number} A negative number, zero, or a positive number as the first\r\n * argument is greater than, equal to, or less than the second,\r\n * respectively.\r\n * @template VALUE\r\n */\r\ngoog.array.inverseDefaultCompare = function(a, b) {\r\n return -goog.array.defaultCompare(a, b);\r\n};\r\n\r\n\r\n/**\r\n * Compares its two arguments for equality, using the built in === operator.\r\n * @param {*} a The first object to compare.\r\n * @param {*} b The second object to compare.\r\n * @return {boolean} True if the two arguments are equal, false otherwise.\r\n */\r\ngoog.array.defaultCompareEquality = function(a, b) {\r\n return a === b;\r\n};\r\n\r\n\r\n/**\r\n * Inserts a value into a sorted array. The array is not modified if the\r\n * value is already present.\r\n * @param {IArrayLike<VALUE>} array The array to modify.\r\n * @param {VALUE} value The object to insert.\r\n * @param {function(VALUE, VALUE): number=} opt_compareFn Optional comparison\r\n * function by which the array is ordered. Should take 2 arguments to\r\n * compare, and return a negative number, zero, or a positive number\r\n * depending on whether the first argument is less than, equal to, or\r\n * greater than the second.\r\n * @return {boolean} True if an element was inserted.\r\n * @template VALUE\r\n */\r\ngoog.array.binaryInsert = function(array, value, opt_compareFn) {\r\n var index = goog.array.binarySearch(array, value, opt_compareFn);\r\n if (index < 0) {\r\n goog.array.insertAt(array, value, -(index + 1));\r\n return true;\r\n }\r\n return false;\r\n};\r\n\r\n\r\n/**\r\n * Removes a value from a sorted array.\r\n * @param {!IArrayLike<VALUE>} array The array to modify.\r\n * @param {VALUE} value The object to remove.\r\n * @param {function(VALUE, VALUE): number=} opt_compareFn Optional comparison\r\n * function by which the array is ordered. Should take 2 arguments to\r\n * compare, and return a negative number, zero, or a positive number\r\n * depending on whether the first argument is less than, equal to, or\r\n * greater than the second.\r\n * @return {boolean} True if an element was removed.\r\n * @template VALUE\r\n */\r\ngoog.array.binaryRemove = function(array, value, opt_compareFn) {\r\n var index = goog.array.binarySearch(array, value, opt_compareFn);\r\n return (index >= 0) ? goog.array.removeAt(array, index) : false;\r\n};\r\n\r\n\r\n/**\r\n * Splits an array into disjoint buckets according to a splitting function.\r\n * @param {IArrayLike<T>} array The array.\r\n * @param {function(this:S, T, number, !IArrayLike<T>):?} sorter Function to\r\n * call for every element. This takes 3 arguments (the element, the index\r\n * and the array) and must return a valid object key (a string, number,\r\n * etc), or undefined, if that object should not be placed in a bucket.\r\n * @param {S=} opt_obj The object to be used as the value of 'this' within\r\n * sorter.\r\n * @return {!Object<!Array<T>>} An object, with keys being all of the unique\r\n * return values of sorter, and values being arrays containing the items for\r\n * which the splitter returned that key.\r\n * @template T,S\r\n */\r\ngoog.array.bucket = function(array, sorter, opt_obj) {\r\n var buckets = {};\r\n\r\n for (var i = 0; i < array.length; i++) {\r\n var value = array[i];\r\n var key = sorter.call(/** @type {?} */ (opt_obj), value, i, array);\r\n if (goog.isDef(key)) {\r\n // Push the value to the right bucket, creating it if necessary.\r\n var bucket = buckets[key] || (buckets[key] = []);\r\n bucket.push(value);\r\n }\r\n }\r\n\r\n return buckets;\r\n};\r\n\r\n\r\n/**\r\n * Creates a new object built from the provided array and the key-generation\r\n * function.\r\n * @param {IArrayLike<T>} arr Array or array like object over\r\n * which to iterate whose elements will be the values in the new object.\r\n * @param {?function(this:S, T, number, ?) : string} keyFunc The function to\r\n * call for every element. This function takes 3 arguments (the element, the\r\n * index and the array) and should return a string that will be used as the\r\n * key for the element in the new object. If the function returns the same\r\n * key for more than one element, the value for that key is\r\n * implementation-defined.\r\n * @param {S=} opt_obj The object to be used as the value of 'this'\r\n * within keyFunc.\r\n * @return {!Object<T>} The new object.\r\n * @template T,S\r\n */\r\ngoog.array.toObject = function(arr, keyFunc, opt_obj) {\r\n var ret = {};\r\n goog.array.forEach(arr, function(element, index) {\r\n ret[keyFunc.call(/** @type {?} */ (opt_obj), element, index, arr)] =\r\n element;\r\n });\r\n return ret;\r\n};\r\n\r\n\r\n/**\r\n * Creates a range of numbers in an arithmetic progression.\r\n *\r\n * Range takes 1, 2, or 3 arguments:\r\n * <pre>\r\n * range(5) is the same as range(0, 5, 1) and produces [0, 1, 2, 3, 4]\r\n * range(2, 5) is the same as range(2, 5, 1) and produces [2, 3, 4]\r\n * range(-2, -5, -1) produces [-2, -3, -4]\r\n * range(-2, -5, 1) produces [], since stepping by 1 wouldn't ever reach -5.\r\n * </pre>\r\n *\r\n * @param {number} startOrEnd The starting value of the range if an end argument\r\n * is provided. Otherwise, the start value is 0, and this is the end value.\r\n * @param {number=} opt_end The optional end value of the range.\r\n * @param {number=} opt_step The step size between range values. Defaults to 1\r\n * if opt_step is undefined or 0.\r\n * @return {!Array<number>} An array of numbers for the requested range. May be\r\n * an empty array if adding the step would not converge toward the end\r\n * value.\r\n */\r\ngoog.array.range = function(startOrEnd, opt_end, opt_step) {\r\n var array = [];\r\n var start = 0;\r\n var end = startOrEnd;\r\n var step = opt_step || 1;\r\n if (opt_end !== undefined) {\r\n start = startOrEnd;\r\n end = opt_end;\r\n }\r\n\r\n if (step * (end - start) < 0) {\r\n // Sign mismatch: start + step will never reach the end value.\r\n return [];\r\n }\r\n\r\n if (step > 0) {\r\n for (var i = start; i < end; i += step) {\r\n array.push(i);\r\n }\r\n } else {\r\n for (var i = start; i > end; i += step) {\r\n array.push(i);\r\n }\r\n }\r\n return array;\r\n};\r\n\r\n\r\n/**\r\n * Returns an array consisting of the given value repeated N times.\r\n *\r\n * @param {VALUE} value The value to repeat.\r\n * @param {number} n The repeat count.\r\n * @return {!Array<VALUE>} An array with the repeated value.\r\n * @template VALUE\r\n */\r\ngoog.array.repeat = function(value, n) {\r\n var array = [];\r\n for (var i = 0; i < n; i++) {\r\n array[i] = value;\r\n }\r\n return array;\r\n};\r\n\r\n\r\n/**\r\n * Returns an array consisting of every argument with all arrays\r\n * expanded in-place recursively.\r\n *\r\n * @param {...*} var_args The values to flatten.\r\n * @return {!Array<?>} An array containing the flattened values.\r\n */\r\ngoog.array.flatten = function(var_args) {\r\n var CHUNK_SIZE = 8192;\r\n\r\n var result = [];\r\n for (var i = 0; i < arguments.length; i++) {\r\n var element = arguments[i];\r\n if (goog.isArray(element)) {\r\n for (var c = 0; c < element.length; c += CHUNK_SIZE) {\r\n var chunk = goog.array.slice(element, c, c + CHUNK_SIZE);\r\n var recurseResult = goog.array.flatten.apply(null, chunk);\r\n for (var r = 0; r < recurseResult.length; r++) {\r\n result.push(recurseResult[r]);\r\n }\r\n }\r\n } else {\r\n result.push(element);\r\n }\r\n }\r\n return result;\r\n};\r\n\r\n\r\n/**\r\n * Rotates an array in-place. After calling this method, the element at\r\n * index i will be the element previously at index (i - n) %\r\n * array.length, for all values of i between 0 and array.length - 1,\r\n * inclusive.\r\n *\r\n * For example, suppose list comprises [t, a, n, k, s]. After invoking\r\n * rotate(array, 1) (or rotate(array, -4)), array will comprise [s, t, a, n, k].\r\n *\r\n * @param {!Array<T>} array The array to rotate.\r\n * @param {number} n The amount to rotate.\r\n * @return {!Array<T>} The array.\r\n * @template T\r\n */\r\ngoog.array.rotate = function(array, n) {\r\n goog.asserts.assert(array.length != null);\r\n\r\n if (array.length) {\r\n n %= array.length;\r\n if (n > 0) {\r\n Array.prototype.unshift.apply(array, array.splice(-n, n));\r\n } else if (n < 0) {\r\n Array.prototype.push.apply(array, array.splice(0, -n));\r\n }\r\n }\r\n return array;\r\n};\r\n\r\n\r\n/**\r\n * Moves one item of an array to a new position keeping the order of the rest\r\n * of the items. Example use case: keeping a list of JavaScript objects\r\n * synchronized with the corresponding list of DOM elements after one of the\r\n * elements has been dragged to a new position.\r\n * @param {!IArrayLike<?>} arr The array to modify.\r\n * @param {number} fromIndex Index of the item to move between 0 and\r\n * {@code arr.length - 1}.\r\n * @param {number} toIndex Target index between 0 and {@code arr.length - 1}.\r\n */\r\ngoog.array.moveItem = function(arr, fromIndex, toIndex) {\r\n goog.asserts.assert(fromIndex >= 0 && fromIndex < arr.length);\r\n goog.asserts.assert(toIndex >= 0 && toIndex < arr.length);\r\n // Remove 1 item at fromIndex.\r\n var removedItems = Array.prototype.splice.call(arr, fromIndex, 1);\r\n // Insert the removed item at toIndex.\r\n Array.prototype.splice.call(arr, toIndex, 0, removedItems[0]);\r\n // We don't use goog.array.insertAt and goog.array.removeAt, because they're\r\n // significantly slower than splice.\r\n};\r\n\r\n\r\n/**\r\n * Creates a new array for which the element at position i is an array of the\r\n * ith element of the provided arrays. The returned array will only be as long\r\n * as the shortest array provided; additional values are ignored. For example,\r\n * the result of zipping [1, 2] and [3, 4, 5] is [[1,3], [2, 4]].\r\n *\r\n * This is similar to the zip() function in Python. See {@link\r\n * http://docs.python.org/library/functions.html#zip}\r\n *\r\n * @param {...!IArrayLike<?>} var_args Arrays to be combined.\r\n * @return {!Array<!Array<?>>} A new array of arrays created from\r\n * provided arrays.\r\n */\r\ngoog.array.zip = function(var_args) {\r\n if (!arguments.length) {\r\n return [];\r\n }\r\n var result = [];\r\n var minLen = arguments[0].length;\r\n for (var i = 1; i < arguments.length; i++) {\r\n if (arguments[i].length < minLen) {\r\n minLen = arguments[i].length;\r\n }\r\n }\r\n for (var i = 0; i < minLen; i++) {\r\n var value = [];\r\n for (var j = 0; j < arguments.length; j++) {\r\n value.push(arguments[j][i]);\r\n }\r\n result.push(value);\r\n }\r\n return result;\r\n};\r\n\r\n\r\n/**\r\n * Shuffles the values in the specified array using the Fisher-Yates in-place\r\n * shuffle (also known as the Knuth Shuffle). By default, calls Math.random()\r\n * and so resets the state of that random number generator. Similarly, may reset\r\n * the state of any other specified random number generator.\r\n *\r\n * Runtime: O(n)\r\n *\r\n * @param {!Array<?>} arr The array to be shuffled.\r\n * @param {function():number=} opt_randFn Optional random function to use for\r\n * shuffling.\r\n * Takes no arguments, and returns a random number on the interval [0, 1).\r\n * Defaults to Math.random() using JavaScript's built-in Math library.\r\n */\r\ngoog.array.shuffle = function(arr, opt_randFn) {\r\n var randFn = opt_randFn || Math.random;\r\n\r\n for (var i = arr.length - 1; i > 0; i--) {\r\n // Choose a random array index in [0, i] (inclusive with i).\r\n var j = Math.floor(randFn() * (i + 1));\r\n\r\n var tmp = arr[i];\r\n arr[i] = arr[j];\r\n arr[j] = tmp;\r\n }\r\n};\r\n\r\n\r\n/**\r\n * Returns a new array of elements from arr, based on the indexes of elements\r\n * provided by index_arr. For example, the result of index copying\r\n * ['a', 'b', 'c'] with index_arr [1,0,0,2] is ['b', 'a', 'a', 'c'].\r\n *\r\n * @param {!IArrayLike<T>} arr The array to get a indexed copy from.\r\n * @param {!IArrayLike<number>} index_arr An array of indexes to get from arr.\r\n * @return {!Array<T>} A new array of elements from arr in index_arr order.\r\n * @template T\r\n */\r\ngoog.array.copyByIndex = function(arr, index_arr) {\r\n var result = [];\r\n goog.array.forEach(index_arr, function(index) { result.push(arr[index]); });\r\n return result;\r\n};\r\n\r\n\r\n/**\r\n * Maps each element of the input array into zero or more elements of the output\r\n * array.\r\n *\r\n * @param {!IArrayLike<VALUE>|string} arr Array or array like object\r\n * over which to iterate.\r\n * @param {function(this:THIS, VALUE, number, ?): !Array<RESULT>} f The function\r\n * to call for every element. This function takes 3 arguments (the element,\r\n * the index and the array) and should return an array. The result will be\r\n * used to extend a new array.\r\n * @param {THIS=} opt_obj The object to be used as the value of 'this' within f.\r\n * @return {!Array<RESULT>} a new array with the concatenation of all arrays\r\n * returned from f.\r\n * @template THIS, VALUE, RESULT\r\n */\r\ngoog.array.concatMap = function(arr, f, opt_obj) {\r\n return goog.array.concat.apply([], goog.array.map(arr, f, opt_obj));\r\n};\r\n","// Copyright 2006 The Closure Library Authors. All Rights Reserved.\r\n//\r\n// Licensed under the Apache License, Version 2.0 (the \"License\");\r\n// you may not use this file except in compliance with the License.\r\n// You may obtain a copy of the License at\r\n//\r\n// http://www.apache.org/licenses/LICENSE-2.0\r\n//\r\n// Unless required by applicable law or agreed to in writing, software\r\n// distributed under the License is distributed on an \"AS-IS\" BASIS,\r\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n// See the License for the specific language governing permissions and\r\n// limitations under the License.\r\n\r\n/**\r\n * @fileoverview Wrapper class for handling XmlHttpRequests.\r\n *\r\n * One off requests can be sent through goog.net.XhrIo.send() or an\r\n * instance can be created to send multiple requests. Each request uses its\r\n * own XmlHttpRequest object and handles clearing of the event callback to\r\n * ensure no leaks.\r\n *\r\n * XhrIo is event based, it dispatches events on success, failure, finishing,\r\n * ready-state change, or progress (download and upload).\r\n *\r\n * The ready-state or timeout event fires first, followed by\r\n * a generic completed event. Then the abort, error, or success event\r\n * is fired as appropriate. Progress events are fired as they are\r\n * received. Lastly, the ready event will fire to indicate that the\r\n * object may be used to make another request.\r\n *\r\n * The error event may also be called before completed and\r\n * ready-state-change if the XmlHttpRequest.open() or .send() methods throw.\r\n *\r\n * This class does not support multiple requests, queuing, or prioritization.\r\n *\r\n * When progress events are supported by the browser, and progress is\r\n * enabled via .setProgressEventsEnabled(true), the\r\n * goog.net.EventType.PROGRESS event will be the re-dispatched browser\r\n * progress event. Additionally, a DOWNLOAD_PROGRESS or UPLOAD_PROGRESS event\r\n * will be fired for download and upload progress respectively.\r\n *\r\n */\r\n\r\n\r\ngoog.provide('goog.net.XhrIo');\r\ngoog.provide('goog.net.XhrIo.ResponseType');\r\n\r\ngoog.require('goog.Timer');\r\ngoog.require('goog.array');\r\ngoog.require('goog.asserts');\r\ngoog.require('goog.debug.entryPointRegistry');\r\ngoog.require('goog.events.EventTarget');\r\ngoog.require('goog.json.hybrid');\r\ngoog.require('goog.log');\r\ngoog.require('goog.net.ErrorCode');\r\ngoog.require('goog.net.EventType');\r\ngoog.require('goog.net.HttpStatus');\r\ngoog.require('goog.net.XmlHttp');\r\ngoog.require('goog.object');\r\ngoog.require('goog.string');\r\ngoog.require('goog.structs');\r\ngoog.require('goog.structs.Map');\r\ngoog.require('goog.uri.utils');\r\ngoog.require('goog.userAgent');\r\n\r\ngoog.forwardDeclare('goog.Uri');\r\n\r\ngoog.scope(function() {\r\n\r\n/**\r\n * Basic class for handling XMLHttpRequests.\r\n * @param {goog.net.XmlHttpFactory=} opt_xmlHttpFactory Factory to use when\r\n * creating XMLHttpRequest objects.\r\n * @constructor\r\n * @extends {goog.events.EventTarget}\r\n */\r\ngoog.net.XhrIo = function(opt_xmlHttpFactory) {\r\n XhrIo.base(this, 'constructor');\r\n\r\n /**\r\n * Map of default headers to add to every request, use:\r\n * XhrIo.headers.set(name, value)\r\n * @type {!goog.structs.Map}\r\n */\r\n this.headers = new goog.structs.Map();\r\n\r\n /**\r\n * Optional XmlHttpFactory\r\n * @private {goog.net.XmlHttpFactory}\r\n */\r\n this.xmlHttpFactory_ = opt_xmlHttpFactory || null;\r\n\r\n /**\r\n * Whether XMLHttpRequest is active. A request is active from the time send()\r\n * is called until onReadyStateChange() is complete, or error() or abort()\r\n * is called.\r\n * @private {boolean}\r\n */\r\n this.active_ = false;\r\n\r\n /**\r\n * The XMLHttpRequest object that is being used for the transfer.\r\n * @private {?goog.net.XhrLike.OrNative}\r\n */\r\n this.xhr_ = null;\r\n\r\n /**\r\n * The options to use with the current XMLHttpRequest object.\r\n * @private {?Object}\r\n */\r\n this.xhrOptions_ = null;\r\n\r\n /**\r\n * Last URL that was requested.\r\n * @private {string|goog.Uri}\r\n */\r\n this.lastUri_ = '';\r\n\r\n /**\r\n * Method for the last request.\r\n * @private {string}\r\n */\r\n this.lastMethod_ = '';\r\n\r\n /**\r\n * Last error code.\r\n * @private {!goog.net.ErrorCode}\r\n */\r\n this.lastErrorCode_ = goog.net.ErrorCode.NO_ERROR;\r\n\r\n /**\r\n * Last error message.\r\n * @private {Error|string}\r\n */\r\n this.lastError_ = '';\r\n\r\n /**\r\n * Used to ensure that we don't dispatch an multiple ERROR events. This can\r\n * happen in IE when it does a synchronous load and one error is handled in\r\n * the ready statte change and one is handled due to send() throwing an\r\n * exception.\r\n * @private {boolean}\r\n */\r\n this.errorDispatched_ = false;\r\n\r\n /**\r\n * Used to make sure we don't fire the complete event from inside a send call.\r\n * @private {boolean}\r\n */\r\n this.inSend_ = false;\r\n\r\n /**\r\n * Used in determining if a call to {@link #onReadyStateChange_} is from\r\n * within a call to this.xhr_.open.\r\n * @private {boolean}\r\n */\r\n this.inOpen_ = false;\r\n\r\n /**\r\n * Used in determining if a call to {@link #onReadyStateChange_} is from\r\n * within a call to this.xhr_.abort.\r\n * @private {boolean}\r\n */\r\n this.inAbort_ = false;\r\n\r\n /**\r\n * Number of milliseconds after which an incomplete request will be aborted\r\n * and a {@link goog.net.EventType.TIMEOUT} event raised; 0 means no timeout\r\n * is set.\r\n * @private {number}\r\n */\r\n this.timeoutInterval_ = 0;\r\n\r\n /**\r\n * Timer to track request timeout.\r\n * @private {?number}\r\n */\r\n this.timeoutId_ = null;\r\n\r\n /**\r\n * The requested type for the response. The empty string means use the default\r\n * XHR behavior.\r\n * @private {goog.net.XhrIo.ResponseType}\r\n */\r\n this.responseType_ = ResponseType.DEFAULT;\r\n\r\n /**\r\n * Whether a \"credentialed\" request is to be sent (one that is aware of\r\n * cookies and authentication). This is applicable only for cross-domain\r\n * requests and more recent browsers that support this part of the HTTP Access\r\n * Control standard.\r\n *\r\n * @see http://www.w3.org/TR/XMLHttpRequest/#the-withcredentials-attribute\r\n *\r\n * @private {boolean}\r\n */\r\n this.withCredentials_ = false;\r\n\r\n /**\r\n * Whether progress events are enabled for this request. This is\r\n * disabled by default because setting a progress event handler\r\n * causes pre-flight OPTIONS requests to be sent for CORS requests,\r\n * even in cases where a pre-flight request would not otherwise be\r\n * sent.\r\n *\r\n * @see http://xhr.spec.whatwg.org/#security-considerations\r\n *\r\n * Note that this can cause problems for Firefox 22 and below, as an\r\n * older \"LSProgressEvent\" will be dispatched by the browser. That\r\n * progress event is no longer supported, and can lead to failures,\r\n * including throwing exceptions.\r\n *\r\n * @see http://bugzilla.mozilla.org/show_bug.cgi?id=845631\r\n * @see b/23469793\r\n *\r\n * @private {boolean}\r\n */\r\n this.progressEventsEnabled_ = false;\r\n\r\n /**\r\n * True if we can use XMLHttpRequest's timeout directly.\r\n * @private {boolean}\r\n */\r\n this.useXhr2Timeout_ = false;\r\n};\r\ngoog.inherits(goog.net.XhrIo, goog.events.EventTarget);\r\n\r\nvar XhrIo = goog.net.XhrIo;\r\n\r\n/**\r\n * Response types that may be requested for XMLHttpRequests.\r\n * @enum {string}\r\n * @see http://www.w3.org/TR/XMLHttpRequest/#the-responsetype-attribute\r\n */\r\ngoog.net.XhrIo.ResponseType = {\r\n DEFAULT: '',\r\n TEXT: 'text',\r\n DOCUMENT: 'document',\r\n // Not supported as of Chrome 10.0.612.1 dev\r\n BLOB: 'blob',\r\n ARRAY_BUFFER: 'arraybuffer'\r\n};\r\n\r\nvar ResponseType = goog.net.XhrIo.ResponseType;\r\n\r\n\r\n/**\r\n * A reference to the XhrIo logger\r\n * @private {?goog.log.Logger}\r\n * @const\r\n */\r\ngoog.net.XhrIo.prototype.logger_ = goog.log.getLogger('goog.net.XhrIo');\r\n\r\n\r\n/**\r\n * The Content-Type HTTP header name\r\n * @type {string}\r\n */\r\ngoog.net.XhrIo.CONTENT_TYPE_HEADER = 'Content-Type';\r\n\r\n\r\n/**\r\n * The Content-Transfer-Encoding HTTP header name\r\n * @type {string}\r\n */\r\ngoog.net.XhrIo.CONTENT_TRANSFER_ENCODING = 'Content-Transfer-Encoding';\r\n\r\n\r\n/**\r\n * The pattern matching the 'http' and 'https' URI schemes\r\n * @type {!RegExp}\r\n */\r\ngoog.net.XhrIo.HTTP_SCHEME_PATTERN = /^https?$/i;\r\n\r\n\r\n/**\r\n * The methods that typically come along with form data. We set different\r\n * headers depending on whether the HTTP action is one of these.\r\n * @type {!Array<string>}\r\n */\r\ngoog.net.XhrIo.METHODS_WITH_FORM_DATA = ['POST', 'PUT'];\r\n\r\n\r\n/**\r\n * The Content-Type HTTP header value for a url-encoded form\r\n * @type {string}\r\n */\r\ngoog.net.XhrIo.FORM_CONTENT_TYPE =\r\n 'application/x-www-form-urlencoded;charset=utf-8';\r\n\r\n\r\n/**\r\n * The XMLHttpRequest Level two timeout delay ms property name.\r\n *\r\n * @see http://www.w3.org/TR/XMLHttpRequest/#the-timeout-attribute\r\n *\r\n * @private {string}\r\n * @const\r\n */\r\ngoog.net.XhrIo.XHR2_TIMEOUT_ = 'timeout';\r\n\r\n\r\n/**\r\n * The XMLHttpRequest Level two ontimeout handler property name.\r\n *\r\n * @see http://www.w3.org/TR/XMLHttpRequest/#the-timeout-attribute\r\n *\r\n * @private {string}\r\n * @const\r\n */\r\ngoog.net.XhrIo.XHR2_ON_TIMEOUT_ = 'ontimeout';\r\n\r\n\r\n/**\r\n * All non-disposed instances of goog.net.XhrIo created\r\n * by {@link goog.net.XhrIo.send} are in this Array.\r\n * @see goog.net.XhrIo.cleanup\r\n * @private {!Array<!goog.net.XhrIo>}\r\n */\r\ngoog.net.XhrIo.sendInstances_ = [];\r\n\r\n\r\n/**\r\n * Static send that creates a short lived instance of XhrIo to send the\r\n * request.\r\n * @see goog.net.XhrIo.cleanup\r\n * @param {string|goog.Uri} url Uri to make request to.\r\n * @param {?function(this:goog.net.XhrIo, ?)=} opt_callback Callback function\r\n * for when request is complete.\r\n * @param {string=} opt_method Send method, default: GET.\r\n * @param {ArrayBuffer|ArrayBufferView|Blob|Document|FormData|string=}\r\n * opt_content Body data.\r\n * @param {Object|goog.structs.Map=} opt_headers Map of headers to add to the\r\n * request.\r\n * @param {number=} opt_timeoutInterval Number of milliseconds after which an\r\n * incomplete request will be aborted; 0 means no timeout is set.\r\n * @param {boolean=} opt_withCredentials Whether to send credentials with the\r\n * request. Default to false. See {@link goog.net.XhrIo#setWithCredentials}.\r\n * @return {!goog.net.XhrIo} The sent XhrIo.\r\n */\r\ngoog.net.XhrIo.send = function(\r\n url, opt_callback, opt_method, opt_content, opt_headers,\r\n opt_timeoutInterval, opt_withCredentials) {\r\n var x = new goog.net.XhrIo();\r\n goog.net.XhrIo.sendInstances_.push(x);\r\n if (opt_callback) {\r\n x.listen(goog.net.EventType.COMPLETE, opt_callback);\r\n }\r\n x.listenOnce(goog.net.EventType.READY, x.cleanupSend_);\r\n if (opt_timeoutInterval) {\r\n x.setTimeoutInterval(opt_timeoutInterval);\r\n }\r\n if (opt_withCredentials) {\r\n x.setWithCredentials(opt_withCredentials);\r\n }\r\n x.send(url, opt_method, opt_content, opt_headers);\r\n return x;\r\n};\r\n\r\n\r\n/**\r\n * Disposes all non-disposed instances of goog.net.XhrIo created by\r\n * {@link goog.net.XhrIo.send}.\r\n * {@link goog.net.XhrIo.send} cleans up the goog.net.XhrIo instance\r\n * it creates when the request completes or fails. However, if\r\n * the request never completes, then the goog.net.XhrIo is not disposed.\r\n * This can occur if the window is unloaded before the request completes.\r\n * We could have {@link goog.net.XhrIo.send} return the goog.net.XhrIo\r\n * it creates and make the client of {@link goog.net.XhrIo.send} be\r\n * responsible for disposing it in this case. However, this makes things\r\n * significantly more complicated for the client, and the whole point\r\n * of {@link goog.net.XhrIo.send} is that it's simple and easy to use.\r\n * Clients of {@link goog.net.XhrIo.send} should call\r\n * {@link goog.net.XhrIo.cleanup} when doing final\r\n * cleanup on window unload.\r\n */\r\ngoog.net.XhrIo.cleanup = function() {\r\n var instances = goog.net.XhrIo.sendInstances_;\r\n while (instances.length) {\r\n instances.pop().dispose();\r\n }\r\n};\r\n\r\n\r\n/**\r\n * Installs exception protection for all entry point introduced by\r\n * goog.net.XhrIo instances which are not protected by\r\n * {@link goog.debug.ErrorHandler#protectWindowSetTimeout},\r\n * {@link goog.debug.ErrorHandler#protectWindowSetInterval}, or\r\n * {@link goog.events.protectBrowserEventEntryPoint}.\r\n *\r\n * @param {goog.debug.ErrorHandler} errorHandler Error handler with which to\r\n * protect the entry point(s).\r\n */\r\ngoog.net.XhrIo.protectEntryPoints = function(errorHandler) {\r\n goog.net.XhrIo.prototype.onReadyStateChangeEntryPoint_ =\r\n errorHandler.protectEntryPoint(\r\n goog.net.XhrIo.prototype.onReadyStateChangeEntryPoint_);\r\n};\r\n\r\n\r\n/**\r\n * Disposes of the specified goog.net.XhrIo created by\r\n * {@link goog.net.XhrIo.send} and removes it from\r\n * {@link goog.net.XhrIo.pendingStaticSendInstances_}.\r\n * @private\r\n */\r\ngoog.net.XhrIo.prototype.cleanupSend_ = function() {\r\n this.dispose();\r\n goog.array.remove(goog.net.XhrIo.sendInstances_, this);\r\n};\r\n\r\n\r\n/**\r\n * Returns the number of milliseconds after which an incomplete request will be\r\n * aborted, or 0 if no timeout is set.\r\n * @return {number} Timeout interval in milliseconds.\r\n */\r\ngoog.net.XhrIo.prototype.getTimeoutInterval = function() {\r\n return this.timeoutInterval_;\r\n};\r\n\r\n\r\n/**\r\n * Sets the number of milliseconds after which an incomplete request will be\r\n * aborted and a {@link goog.net.EventType.TIMEOUT} event raised; 0 means no\r\n * timeout is set.\r\n * @param {number} ms Timeout interval in milliseconds; 0 means none.\r\n */\r\ngoog.net.XhrIo.prototype.setTimeoutInterval = function(ms) {\r\n this.timeoutInterval_ = Math.max(0, ms);\r\n};\r\n\r\n\r\n/**\r\n * Sets the desired type for the response. At time of writing, this is only\r\n * supported in very recent versions of WebKit (10.0.612.1 dev and later).\r\n *\r\n * If this is used, the response may only be accessed via {@link #getResponse}.\r\n *\r\n * @param {goog.net.XhrIo.ResponseType} type The desired type for the response.\r\n */\r\ngoog.net.XhrIo.prototype.setResponseType = function(type) {\r\n this.responseType_ = type;\r\n};\r\n\r\n\r\n/**\r\n * Gets the desired type for the response.\r\n * @return {goog.net.XhrIo.ResponseType} The desired type for the response.\r\n */\r\ngoog.net.XhrIo.prototype.getResponseType = function() {\r\n return this.responseType_;\r\n};\r\n\r\n\r\n/**\r\n * Sets whether a \"credentialed\" request that is aware of cookie and\r\n * authentication information should be made. This option is only supported by\r\n * browsers that support HTTP Access Control. As of this writing, this option\r\n * is not supported in IE.\r\n *\r\n * @param {boolean} withCredentials Whether this should be a \"credentialed\"\r\n * request.\r\n */\r\ngoog.net.XhrIo.prototype.setWithCredentials = function(withCredentials) {\r\n this.withCredentials_ = withCredentials;\r\n};\r\n\r\n\r\n/**\r\n * Gets whether a \"credentialed\" request is to be sent.\r\n * @return {boolean} The desired type for the response.\r\n */\r\ngoog.net.XhrIo.prototype.getWithCredentials = function() {\r\n return this.withCredentials_;\r\n};\r\n\r\n\r\n/**\r\n * Sets whether progress events are enabled for this request. Note\r\n * that progress events require pre-flight OPTIONS request handling\r\n * for CORS requests, and may cause trouble with older browsers. See\r\n * progressEventsEnabled_ for details.\r\n * @param {boolean} enabled Whether progress events should be enabled.\r\n */\r\ngoog.net.XhrIo.prototype.setProgressEventsEnabled = function(enabled) {\r\n this.progressEventsEnabled_ = enabled;\r\n};\r\n\r\n\r\n/**\r\n * Gets whether progress events are enabled.\r\n * @return {boolean} Whether progress events are enabled for this request.\r\n */\r\ngoog.net.XhrIo.prototype.getProgressEventsEnabled = function() {\r\n return this.progressEventsEnabled_;\r\n};\r\n\r\n\r\n/**\r\n * Instance send that actually uses XMLHttpRequest to make a server call.\r\n * @param {string|goog.Uri} url Uri to make request to.\r\n * @param {string=} opt_method Send method, default: GET.\r\n * @param {ArrayBuffer|ArrayBufferView|Blob|Document|FormData|string=}\r\n * opt_content Body data.\r\n * @param {Object|goog.structs.Map=} opt_headers Map of headers to add to the\r\n * request.\r\n * @suppress {deprecated} Use deprecated goog.structs.forEach to allow different\r\n * types of parameters for opt_headers.\r\n */\r\ngoog.net.XhrIo.prototype.send = function(\r\n url, opt_method, opt_content, opt_headers) {\r\n if (this.xhr_) {\r\n throw new Error(\r\n '[goog.net.XhrIo] Object is active with another request=' +\r\n this.lastUri_ + '; newUri=' + url);\r\n }\r\n\r\n var method = opt_method ? opt_method.toUpperCase() : 'GET';\r\n\r\n this.lastUri_ = url;\r\n this.lastError_ = '';\r\n this.lastErrorCode_ = goog.net.ErrorCode.NO_ERROR;\r\n this.lastMethod_ = method;\r\n this.errorDispatched_ = false;\r\n this.active_ = true;\r\n\r\n // Use the factory to create the XHR object and options\r\n this.xhr_ = this.createXhr();\r\n this.xhrOptions_ = this.xmlHttpFactory_ ? this.xmlHttpFactory_.getOptions() :\r\n goog.net.XmlHttp.getOptions();\r\n\r\n // Set up the onreadystatechange callback\r\n this.xhr_.onreadystatechange = goog.bind(this.onReadyStateChange_, this);\r\n\r\n // Set up upload/download progress events, if progress events are supported.\r\n if (this.getProgressEventsEnabled() && 'onprogress' in this.xhr_) {\r\n this.xhr_.onprogress =\r\n goog.bind(function(e) { this.onProgressHandler_(e, true); }, this);\r\n if (this.xhr_.upload) {\r\n this.xhr_.upload.onprogress = goog.bind(this.onProgressHandler_, this);\r\n }\r\n }\r\n\r\n /**\r\n * Try to open the XMLHttpRequest (always async), if an error occurs here it\r\n * is generally permission denied\r\n */\r\n try {\r\n goog.log.fine(this.logger_, this.formatMsg_('Opening Xhr'));\r\n this.inOpen_ = true;\r\n this.xhr_.open(method, String(url), true); // Always async!\r\n this.inOpen_ = false;\r\n } catch (err) {\r\n goog.log.fine(\r\n this.logger_, this.formatMsg_('Error opening Xhr: ' + err.message));\r\n this.error_(goog.net.ErrorCode.EXCEPTION, err);\r\n return;\r\n }\r\n\r\n // We can't use null since this won't allow requests with form data to have a\r\n // content length specified which will cause some proxies to return a 411\r\n // error.\r\n var content = opt_content || '';\r\n\r\n var headers = this.headers.clone();\r\n\r\n // Add headers specific to this request\r\n if (opt_headers) {\r\n goog.structs.forEach(\r\n opt_headers, function(value, key) { headers.set(key, value); });\r\n }\r\n\r\n // Find whether a content type header is set, ignoring case.\r\n // HTTP header names are case-insensitive. See:\r\n // http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2\r\n var contentTypeKey =\r\n goog.array.find(headers.getKeys(), goog.net.XhrIo.isContentTypeHeader_);\r\n\r\n var contentIsFormData =\r\n (goog.global['FormData'] && (content instanceof goog.global['FormData']));\r\n if (goog.array.contains(goog.net.XhrIo.METHODS_WITH_FORM_DATA, method) &&\r\n !contentTypeKey && !contentIsFormData) {\r\n // For requests typically with form data, default to the url-encoded form\r\n // content type unless this is a FormData request. For FormData,\r\n // the browser will automatically add a multipart/form-data content type\r\n // with an appropriate multipart boundary.\r\n headers.set(\r\n goog.net.XhrIo.CONTENT_TYPE_HEADER, goog.net.XhrIo.FORM_CONTENT_TYPE);\r\n }\r\n\r\n // Add the headers to the Xhr object\r\n headers.forEach(function(value, key) {\r\n this.xhr_.setRequestHeader(key, value);\r\n }, this);\r\n\r\n if (this.responseType_) {\r\n this.xhr_.responseType = this.responseType_;\r\n }\r\n // Set xhr_.withCredentials only when the value is different, or else in\r\n // synchronous XMLHtppRequest.open Firefox will throw an exception.\r\n // https://bugzilla.mozilla.org/show_bug.cgi?id=736340\r\n if ('withCredentials' in this.xhr_ &&\r\n this.xhr_.withCredentials !== this.withCredentials_) {\r\n this.xhr_.withCredentials = this.withCredentials_;\r\n }\r\n\r\n /**\r\n * Try to send the request, or other wise report an error (404 not found).\r\n */\r\n try {\r\n this.cleanUpTimeoutTimer_(); // Paranoid, should never be running.\r\n if (this.timeoutInterval_ > 0) {\r\n this.useXhr2Timeout_ = goog.net.XhrIo.shouldUseXhr2Timeout_(this.xhr_);\r\n goog.log.fine(\r\n this.logger_, this.formatMsg_(\r\n 'Will abort after ' + this.timeoutInterval_ +\r\n 'ms if incomplete, xhr2 ' + this.useXhr2Timeout_));\r\n if (this.useXhr2Timeout_) {\r\n this.xhr_[goog.net.XhrIo.XHR2_TIMEOUT_] = this.timeoutInterval_;\r\n this.xhr_[goog.net.XhrIo.XHR2_ON_TIMEOUT_] =\r\n goog.bind(this.timeout_, this);\r\n } else {\r\n this.timeoutId_ =\r\n goog.Timer.callOnce(this.timeout_, this.timeoutInterval_, this);\r\n }\r\n }\r\n goog.log.fine(this.logger_, this.formatMsg_('Sending request'));\r\n this.inSend_ = true;\r\n this.xhr_.send(content);\r\n this.inSend_ = false;\r\n\r\n } catch (err) {\r\n goog.log.fine(this.logger_, this.formatMsg_('Send error: ' + err.message));\r\n this.error_(goog.net.ErrorCode.EXCEPTION, err);\r\n }\r\n};\r\n\r\n\r\n/**\r\n * Determines if the argument is an XMLHttpRequest that supports the level 2\r\n * timeout value and event.\r\n *\r\n * Currently, FF 21.0 OS X has the fields but won't actually call the timeout\r\n * handler. Perhaps the confusion in the bug referenced below hasn't\r\n * entirely been resolved.\r\n *\r\n * @see http://www.w3.org/TR/XMLHttpRequest/#the-timeout-attribute\r\n * @see https://bugzilla.mozilla.org/show_bug.cgi?id=525816\r\n *\r\n * @param {!goog.net.XhrLike.OrNative} xhr The request.\r\n * @return {boolean} True if the request supports level 2 timeout.\r\n * @private\r\n */\r\ngoog.net.XhrIo.shouldUseXhr2Timeout_ = function(xhr) {\r\n return goog.userAgent.IE && goog.userAgent.isVersionOrHigher(9) &&\r\n goog.isNumber(xhr[goog.net.XhrIo.XHR2_TIMEOUT_]) &&\r\n goog.isDef(xhr[goog.net.XhrIo.XHR2_ON_TIMEOUT_]);\r\n};\r\n\r\n\r\n/**\r\n * @param {string} header An HTTP header key.\r\n * @return {boolean} Whether the key is a content type header (ignoring\r\n * case.\r\n * @private\r\n */\r\ngoog.net.XhrIo.isContentTypeHeader_ = function(header) {\r\n return goog.string.caseInsensitiveEquals(\r\n goog.net.XhrIo.CONTENT_TYPE_HEADER, header);\r\n};\r\n\r\n\r\n/**\r\n * Creates a new XHR object.\r\n * @return {!goog.net.XhrLike.OrNative} The newly created XHR object.\r\n * @protected\r\n */\r\ngoog.net.XhrIo.prototype.createXhr = function() {\r\n return this.xmlHttpFactory_ ? this.xmlHttpFactory_.createInstance() :\r\n goog.net.XmlHttp();\r\n};\r\n\r\n\r\n/**\r\n * The request didn't complete after {@link goog.net.XhrIo#timeoutInterval_}\r\n * milliseconds; raises a {@link goog.net.EventType.TIMEOUT} event and aborts\r\n * the request.\r\n * @private\r\n */\r\ngoog.net.XhrIo.prototype.timeout_ = function() {\r\n if (typeof goog == 'undefined') {\r\n // If goog is undefined then the callback has occurred as the application\r\n // is unloading and will error. Thus we let it silently fail.\r\n } else if (this.xhr_) {\r\n this.lastError_ =\r\n 'Timed out after ' + this.timeoutInterval_ + 'ms, aborting';\r\n this.lastErrorCode_ = goog.net.ErrorCode.TIMEOUT;\r\n goog.log.fine(this.logger_, this.formatMsg_(this.lastError_));\r\n this.dispatchEvent(goog.net.EventType.TIMEOUT);\r\n this.abort(goog.net.ErrorCode.TIMEOUT);\r\n }\r\n};\r\n\r\n\r\n/**\r\n * Something errorred, so inactivate, fire error callback and clean up\r\n * @param {goog.net.ErrorCode} errorCode The error code.\r\n * @param {Error} err The error object.\r\n * @private\r\n */\r\ngoog.net.XhrIo.prototype.error_ = function(errorCode, err) {\r\n this.active_ = false;\r\n if (this.xhr_) {\r\n this.inAbort_ = true;\r\n this.xhr_.abort(); // Ensures XHR isn't hung (FF)\r\n this.inAbort_ = false;\r\n }\r\n this.lastError_ = err;\r\n this.lastErrorCode_ = errorCode;\r\n this.dispatchErrors_();\r\n this.cleanUpXhr_();\r\n};\r\n\r\n\r\n/**\r\n * Dispatches COMPLETE and ERROR in case of an error. This ensures that we do\r\n * not dispatch multiple error events.\r\n * @private\r\n */\r\ngoog.net.XhrIo.prototype.dispatchErrors_ = function() {\r\n if (!this.errorDispatched_) {\r\n this.errorDispatched_ = true;\r\n this.dispatchEvent(goog.net.EventType.COMPLETE);\r\n this.dispatchEvent(goog.net.EventType.ERROR);\r\n }\r\n};\r\n\r\n\r\n/**\r\n * Abort the current XMLHttpRequest\r\n * @param {goog.net.ErrorCode=} opt_failureCode Optional error code to use -\r\n * defaults to ABORT.\r\n */\r\ngoog.net.XhrIo.prototype.abort = function(opt_failureCode) {\r\n if (this.xhr_ && this.active_) {\r\n goog.log.fine(this.logger_, this.formatMsg_('Aborting'));\r\n this.active_ = false;\r\n this.inAbort_ = true;\r\n this.xhr_.abort();\r\n this.inAbort_ = false;\r\n this.lastErrorCode_ = opt_failureCode || goog.net.ErrorCode.ABORT;\r\n this.dispatchEvent(goog.net.EventType.COMPLETE);\r\n this.dispatchEvent(goog.net.EventType.ABORT);\r\n this.cleanUpXhr_();\r\n }\r\n};\r\n\r\n\r\n/**\r\n * Nullifies all callbacks to reduce risks of leaks.\r\n * @override\r\n * @protected\r\n */\r\ngoog.net.XhrIo.prototype.disposeInternal = function() {\r\n if (this.xhr_) {\r\n // We explicitly do not call xhr_.abort() unless active_ is still true.\r\n // This is to avoid unnecessarily aborting a successful request when\r\n // dispose() is called in a callback triggered by a complete response, but\r\n // in which browser cleanup has not yet finished.\r\n // (See http://b/issue?id=1684217.)\r\n if (this.active_) {\r\n this.active_ = false;\r\n this.inAbort_ = true;\r\n this.xhr_.abort();\r\n this.inAbort_ = false;\r\n }\r\n this.cleanUpXhr_(true);\r\n }\r\n\r\n XhrIo.base(this, 'disposeInternal');\r\n};\r\n\r\n\r\n/**\r\n * Internal handler for the XHR object's readystatechange event. This method\r\n * checks the status and the readystate and fires the correct callbacks.\r\n * If the request has ended, the handlers are cleaned up and the XHR object is\r\n * nullified.\r\n * @private\r\n */\r\ngoog.net.XhrIo.prototype.onReadyStateChange_ = function() {\r\n if (this.isDisposed()) {\r\n // This method is the target of an untracked goog.Timer.callOnce().\r\n return;\r\n }\r\n if (!this.inOpen_ && !this.inSend_ && !this.inAbort_) {\r\n // Were not being called from within a call to this.xhr_.send\r\n // this.xhr_.abort, or this.xhr_.open, so this is an entry point\r\n this.onReadyStateChangeEntryPoint_();\r\n } else {\r\n this.onReadyStateChangeHelper_();\r\n }\r\n};\r\n\r\n\r\n/**\r\n * Used to protect the onreadystatechange handler entry point. Necessary\r\n * as {#onReadyStateChange_} maybe called from within send or abort, this\r\n * method is only called when {#onReadyStateChange_} is called as an\r\n * entry point.\r\n * {@see #protectEntryPoints}\r\n * @private\r\n */\r\ngoog.net.XhrIo.prototype.onReadyStateChangeEntryPoint_ = function() {\r\n this.onReadyStateChangeHelper_();\r\n};\r\n\r\n\r\n/**\r\n * Helper for {@link #onReadyStateChange_}. This is used so that\r\n * entry point calls to {@link #onReadyStateChange_} can be routed through\r\n * {@link #onReadyStateChangeEntryPoint_}.\r\n * @private\r\n */\r\ngoog.net.XhrIo.prototype.onReadyStateChangeHelper_ = function() {\r\n if (!this.active_) {\r\n // can get called inside abort call\r\n return;\r\n }\r\n\r\n if (typeof goog == 'undefined') {\r\n // NOTE(user): If goog is undefined then the callback has occurred as the\r\n // application is unloading and will error. Thus we let it silently fail.\r\n\r\n } else if (\r\n this.xhrOptions_[goog.net.XmlHttp.OptionType.LOCAL_REQUEST_ERROR] &&\r\n this.getReadyState() == goog.net.XmlHttp.ReadyState.COMPLETE &&\r\n this.getStatus() == 2) {\r\n // NOTE(user): In IE if send() errors on a *local* request the readystate\r\n // is still changed to COMPLETE. We need to ignore it and allow the\r\n // try/catch around send() to pick up the error.\r\n goog.log.fine(\r\n this.logger_,\r\n this.formatMsg_('Local request error detected and ignored'));\r\n\r\n } else {\r\n // In IE when the response has been cached we sometimes get the callback\r\n // from inside the send call and this usually breaks code that assumes that\r\n // XhrIo is asynchronous. If that is the case we delay the callback\r\n // using a timer.\r\n if (this.inSend_ &&\r\n this.getReadyState() == goog.net.XmlHttp.ReadyState.COMPLETE) {\r\n goog.Timer.callOnce(this.onReadyStateChange_, 0, this);\r\n return;\r\n }\r\n\r\n this.dispatchEvent(goog.net.EventType.READY_STATE_CHANGE);\r\n\r\n // readyState indicates the transfer has finished\r\n if (this.isComplete()) {\r\n goog.log.fine(this.logger_, this.formatMsg_('Request complete'));\r\n\r\n this.active_ = false;\r\n\r\n try {\r\n // Call the specific callbacks for success or failure. Only call the\r\n // success if the status is 200 (HTTP_OK) or 304 (HTTP_CACHED)\r\n if (this.isSuccess()) {\r\n this.dispatchEvent(goog.net.EventType.COMPLETE);\r\n this.dispatchEvent(goog.net.EventType.SUCCESS);\r\n } else {\r\n this.lastErrorCode_ = goog.net.ErrorCode.HTTP_ERROR;\r\n this.lastError_ =\r\n this.getStatusText() + ' [' + this.getStatus() + ']';\r\n this.dispatchErrors_();\r\n }\r\n } finally {\r\n this.cleanUpXhr_();\r\n }\r\n }\r\n }\r\n};\r\n\r\n\r\n/**\r\n * Internal handler for the XHR object's onprogress event. Fires both a generic\r\n * PROGRESS event and either a DOWNLOAD_PROGRESS or UPLOAD_PROGRESS event to\r\n * allow specific binding for each XHR progress event.\r\n * @param {!ProgressEvent} e XHR progress event.\r\n * @param {boolean=} opt_isDownload Whether the current progress event is from a\r\n * download. Used to determine whether DOWNLOAD_PROGRESS or UPLOAD_PROGRESS\r\n * event should be dispatched.\r\n * @private\r\n */\r\ngoog.net.XhrIo.prototype.onProgressHandler_ = function(e, opt_isDownload) {\r\n goog.asserts.assert(\r\n e.type === goog.net.EventType.PROGRESS,\r\n 'goog.net.EventType.PROGRESS is of the same type as raw XHR progress.');\r\n this.dispatchEvent(\r\n goog.net.XhrIo.buildProgressEvent_(e, goog.net.EventType.PROGRESS));\r\n this.dispatchEvent(\r\n goog.net.XhrIo.buildProgressEvent_(\r\n e, opt_isDownload ? goog.net.EventType.DOWNLOAD_PROGRESS :\r\n goog.net.EventType.UPLOAD_PROGRESS));\r\n};\r\n\r\n\r\n/**\r\n * Creates a representation of the native ProgressEvent. IE doesn't support\r\n * constructing ProgressEvent via \"new\", and the alternatives (e.g.,\r\n * ProgressEvent.initProgressEvent) are non-standard or deprecated.\r\n * @param {!ProgressEvent} e XHR progress event.\r\n * @param {!goog.net.EventType} eventType The type of the event.\r\n * @return {!ProgressEvent} The progress event.\r\n * @private\r\n */\r\ngoog.net.XhrIo.buildProgressEvent_ = function(e, eventType) {\r\n return /** @type {!ProgressEvent} */ ({\r\n type: eventType,\r\n lengthComputable: e.lengthComputable,\r\n loaded: e.loaded,\r\n total: e.total\r\n });\r\n};\r\n\r\n\r\n/**\r\n * Remove the listener to protect against leaks, and nullify the XMLHttpRequest\r\n * object.\r\n * @param {boolean=} opt_fromDispose If this is from the dispose (don't want to\r\n * fire any events).\r\n * @private\r\n */\r\ngoog.net.XhrIo.prototype.cleanUpXhr_ = function(opt_fromDispose) {\r\n if (this.xhr_) {\r\n // Cancel any pending timeout event handler.\r\n this.cleanUpTimeoutTimer_();\r\n\r\n // Save reference so we can mark it as closed after the READY event. The\r\n // READY event may trigger another request, thus we must nullify this.xhr_\r\n var xhr = this.xhr_;\r\n var clearedOnReadyStateChange =\r\n this.xhrOptions_[goog.net.XmlHttp.OptionType.USE_NULL_FUNCTION] ?\r\n goog.nullFunction :\r\n null;\r\n this.xhr_ = null;\r\n this.xhrOptions_ = null;\r\n\r\n if (!opt_fromDispose) {\r\n this.dispatchEvent(goog.net.EventType.READY);\r\n }\r\n\r\n try {\r\n // NOTE(user): Not nullifying in FireFox can still leak if the callbacks\r\n // are defined in the same scope as the instance of XhrIo. But, IE doesn't\r\n // allow you to set the onreadystatechange to NULL so nullFunction is\r\n // used.\r\n xhr.onreadystatechange = clearedOnReadyStateChange;\r\n } catch (e) {\r\n // This seems to occur with a Gears HTTP request. Delayed the setting of\r\n // this onreadystatechange until after READY is sent out and catching the\r\n // error to see if we can track down the problem.\r\n goog.log.error(\r\n this.logger_,\r\n 'Problem encountered resetting onreadystatechange: ' + e.message);\r\n }\r\n }\r\n};\r\n\r\n\r\n/**\r\n * Make sure the timeout timer isn't running.\r\n * @private\r\n */\r\ngoog.net.XhrIo.prototype.cleanUpTimeoutTimer_ = function() {\r\n if (this.xhr_ && this.useXhr2Timeout_) {\r\n this.xhr_[goog.net.XhrIo.XHR2_ON_TIMEOUT_] = null;\r\n }\r\n if (this.timeoutId_) {\r\n goog.Timer.clear(this.timeoutId_);\r\n this.timeoutId_ = null;\r\n }\r\n};\r\n\r\n\r\n/**\r\n * @return {boolean} Whether there is an active request.\r\n */\r\ngoog.net.XhrIo.prototype.isActive = function() {\r\n return !!this.xhr_;\r\n};\r\n\r\n\r\n/**\r\n * @return {boolean} Whether the request has completed.\r\n */\r\ngoog.net.XhrIo.prototype.isComplete = function() {\r\n return this.getReadyState() == goog.net.XmlHttp.ReadyState.COMPLETE;\r\n};\r\n\r\n\r\n/**\r\n * @return {boolean} Whether the request completed with a success.\r\n */\r\ngoog.net.XhrIo.prototype.isSuccess = function() {\r\n var status = this.getStatus();\r\n // A zero status code is considered successful for local files.\r\n return goog.net.HttpStatus.isSuccess(status) ||\r\n status === 0 && !this.isLastUriEffectiveSchemeHttp_();\r\n};\r\n\r\n\r\n/**\r\n * @return {boolean} whether the effective scheme of the last URI that was\r\n * fetched was 'http' or 'https'.\r\n * @private\r\n */\r\ngoog.net.XhrIo.prototype.isLastUriEffectiveSchemeHttp_ = function() {\r\n var scheme = goog.uri.utils.getEffectiveScheme(String(this.lastUri_));\r\n return goog.net.XhrIo.HTTP_SCHEME_PATTERN.test(scheme);\r\n};\r\n\r\n\r\n/**\r\n * Get the readystate from the Xhr object\r\n * Will only return correct result when called from the context of a callback\r\n * @return {goog.net.XmlHttp.ReadyState} goog.net.XmlHttp.ReadyState.*.\r\n */\r\ngoog.net.XhrIo.prototype.getReadyState = function() {\r\n return this.xhr_ ?\r\n /** @type {goog.net.XmlHttp.ReadyState} */ (this.xhr_.readyState) :\r\n goog.net.XmlHttp.ReadyState\r\n .UNINITIALIZED;\r\n};\r\n\r\n\r\n/**\r\n * Get the status from the Xhr object\r\n * Will only return correct result when called from the context of a callback\r\n * @return {number} Http status.\r\n */\r\ngoog.net.XhrIo.prototype.getStatus = function() {\r\n /**\r\n * IE doesn't like you checking status until the readystate is greater than 2\r\n * (i.e. it is receiving or complete). The try/catch is used for when the\r\n * page is unloading and an ERROR_NOT_AVAILABLE may occur when accessing xhr_.\r\n */\r\n try {\r\n return this.getReadyState() > goog.net.XmlHttp.ReadyState.LOADED ?\r\n this.xhr_.status :\r\n -1;\r\n } catch (e) {\r\n return -1;\r\n }\r\n};\r\n\r\n\r\n/**\r\n * Get the status text from the Xhr object\r\n * Will only return correct result when called from the context of a callback\r\n * @return {string} Status text.\r\n */\r\ngoog.net.XhrIo.prototype.getStatusText = function() {\r\n /**\r\n * IE doesn't like you checking status until the readystate is greater than 2\r\n * (i.e. it is receiving or complete). The try/catch is used for when the\r\n * page is unloading and an ERROR_NOT_AVAILABLE may occur when accessing xhr_.\r\n */\r\n try {\r\n return this.getReadyState() > goog.net.XmlHttp.ReadyState.LOADED ?\r\n this.xhr_.statusText :\r\n '';\r\n } catch (e) {\r\n goog.log.fine(this.logger_, 'Can not get status: ' + e.message);\r\n return '';\r\n }\r\n};\r\n\r\n\r\n/**\r\n * Get the last Uri that was requested\r\n * @return {string} Last Uri.\r\n */\r\ngoog.net.XhrIo.prototype.getLastUri = function() {\r\n return String(this.lastUri_);\r\n};\r\n\r\n\r\n/**\r\n * Get the response text from the Xhr object\r\n * Will only return correct result when called from the context of a callback.\r\n * @return {string} Result from the server, or '' if no result available.\r\n */\r\ngoog.net.XhrIo.prototype.getResponseText = function() {\r\n try {\r\n return this.xhr_ ? this.xhr_.responseText : '';\r\n } catch (e) {\r\n // http://www.w3.org/TR/XMLHttpRequest/#the-responsetext-attribute\r\n // states that responseText should return '' (and responseXML null)\r\n // when the state is not LOADING or DONE. Instead, IE can\r\n // throw unexpected exceptions, for example when a request is aborted\r\n // or no data is available yet.\r\n goog.log.fine(this.logger_, 'Can not get responseText: ' + e.message);\r\n return '';\r\n }\r\n};\r\n\r\n\r\n/**\r\n * Get the response body from the Xhr object. This property is only available\r\n * in IE since version 7 according to MSDN:\r\n * http://msdn.microsoft.com/en-us/library/ie/ms534368(v=vs.85).aspx\r\n * Will only return correct result when called from the context of a callback.\r\n *\r\n * One option is to construct a VBArray from the returned object and convert\r\n * it to a JavaScript array using the toArray method:\r\n * `(new window['VBArray'](xhrIo.getResponseBody())).toArray()`\r\n * This will result in an array of numbers in the range of [0..255]\r\n *\r\n * Another option is to use the VBScript CStr method to convert it into a\r\n * string as outlined in http://stackoverflow.com/questions/1919972\r\n *\r\n * @return {Object} Binary result from the server or null if not available.\r\n */\r\ngoog.net.XhrIo.prototype.getResponseBody = function() {\r\n try {\r\n if (this.xhr_ && 'responseBody' in this.xhr_) {\r\n return this.xhr_['responseBody'];\r\n }\r\n } catch (e) {\r\n // IE can throw unexpected exceptions, for example when a request is aborted\r\n // or no data is yet available.\r\n goog.log.fine(this.logger_, 'Can not get responseBody: ' + e.message);\r\n }\r\n return null;\r\n};\r\n\r\n\r\n/**\r\n * Get the response XML from the Xhr object\r\n * Will only return correct result when called from the context of a callback.\r\n * @return {Document} The DOM Document representing the XML file, or null\r\n * if no result available.\r\n */\r\ngoog.net.XhrIo.prototype.getResponseXml = function() {\r\n try {\r\n return this.xhr_ ? this.xhr_.responseXML : null;\r\n } catch (e) {\r\n goog.log.fine(this.logger_, 'Can not get responseXML: ' + e.message);\r\n return null;\r\n }\r\n};\r\n\r\n\r\n/**\r\n * Get the response and evaluates it as JSON from the Xhr object\r\n * Will only return correct result when called from the context of a callback\r\n * @param {string=} opt_xssiPrefix Optional XSSI prefix string to use for\r\n * stripping of the response before parsing. This needs to be set only if\r\n * your backend server prepends the same prefix string to the JSON response.\r\n * @throws Error if the response text is invalid JSON.\r\n * @return {Object|undefined} JavaScript object.\r\n */\r\ngoog.net.XhrIo.prototype.getResponseJson = function(opt_xssiPrefix) {\r\n if (!this.xhr_) {\r\n return undefined;\r\n }\r\n\r\n var responseText = this.xhr_.responseText;\r\n if (opt_xssiPrefix && responseText.indexOf(opt_xssiPrefix) == 0) {\r\n responseText = responseText.substring(opt_xssiPrefix.length);\r\n }\r\n\r\n return goog.json.hybrid.parse(responseText);\r\n};\r\n\r\n\r\n/**\r\n * Get the response as the type specificed by {@link #setResponseType}. At time\r\n * of writing, this is only directly supported in very recent versions of WebKit\r\n * (10.0.612.1 dev and later). If the field is not supported directly, we will\r\n * try to emulate it.\r\n *\r\n * Emulating the response means following the rules laid out at\r\n * http://www.w3.org/TR/XMLHttpRequest/#the-response-attribute\r\n *\r\n * On browsers with no support for this (Chrome < 10, Firefox < 4, etc), only\r\n * response types of DEFAULT or TEXT may be used, and the response returned will\r\n * be the text response.\r\n *\r\n * On browsers with Mozilla's draft support for array buffers (Firefox 4, 5),\r\n * only response types of DEFAULT, TEXT, and ARRAY_BUFFER may be used, and the\r\n * response returned will be either the text response or the Mozilla\r\n * implementation of the array buffer response.\r\n *\r\n * On browsers will full support, any valid response type supported by the\r\n * browser may be used, and the response provided by the browser will be\r\n * returned.\r\n *\r\n * @return {*} The response.\r\n */\r\ngoog.net.XhrIo.prototype.getResponse = function() {\r\n try {\r\n if (!this.xhr_) {\r\n return null;\r\n }\r\n if ('response' in this.xhr_) {\r\n return this.xhr_.response;\r\n }\r\n switch (this.responseType_) {\r\n case ResponseType.DEFAULT:\r\n case ResponseType.TEXT:\r\n return this.xhr_.responseText;\r\n // DOCUMENT and BLOB don't need to be handled here because they are\r\n // introduced in the same spec that adds the .response field, and would\r\n // have been caught above.\r\n // ARRAY_BUFFER needs an implementation for Firefox 4, where it was\r\n // implemented using a draft spec rather than the final spec.\r\n case ResponseType.ARRAY_BUFFER:\r\n if ('mozResponseArrayBuffer' in this.xhr_) {\r\n return this.xhr_.mozResponseArrayBuffer;\r\n }\r\n }\r\n // Fell through to a response type that is not supported on this browser.\r\n goog.log.error(\r\n this.logger_, 'Response type ' + this.responseType_ + ' is not ' +\r\n 'supported on this browser');\r\n return null;\r\n } catch (e) {\r\n goog.log.fine(this.logger_, 'Can not get response: ' + e.message);\r\n return null;\r\n }\r\n};\r\n\r\n\r\n/**\r\n * Get the value of the response-header with the given name from the Xhr object\r\n * Will only return correct result when called from the context of a callback\r\n * and the request has completed\r\n * @param {string} key The name of the response-header to retrieve.\r\n * @return {string|undefined} The value of the response-header named key.\r\n */\r\ngoog.net.XhrIo.prototype.getResponseHeader = function(key) {\r\n if (!this.xhr_ || !this.isComplete()) {\r\n return undefined;\r\n }\r\n\r\n var value = this.xhr_.getResponseHeader(key);\r\n return goog.isNull(value) ? undefined : value;\r\n};\r\n\r\n\r\n/**\r\n * Gets the text of all the headers in the response.\r\n * Will only return correct result when called from the context of a callback\r\n * and the request has completed.\r\n * @return {string} The value of the response headers or empty string.\r\n */\r\ngoog.net.XhrIo.prototype.getAllResponseHeaders = function() {\r\n // getAllResponseHeaders can return null if no response has been received,\r\n // ensure we always return an empty string.\r\n return this.xhr_ && this.isComplete() ?\r\n (this.xhr_.getAllResponseHeaders() || '') :\r\n '';\r\n};\r\n\r\n\r\n/**\r\n * Returns all response headers as a key-value map.\r\n * Multiple values for the same header key can be combined into one,\r\n * separated by a comma and a space.\r\n * Note that the native getResponseHeader method for retrieving a single header\r\n * does a case insensitive match on the header name. This method does not\r\n * include any case normalization logic, it will just return a key-value\r\n * representation of the headers.\r\n * See: http://www.w3.org/TR/XMLHttpRequest/#the-getresponseheader()-method\r\n * @return {!Object<string, string>} An object with the header keys as keys\r\n * and header values as values.\r\n */\r\ngoog.net.XhrIo.prototype.getResponseHeaders = function() {\r\n // TODO(b/120371595): Make this function parse headers as per the spec\r\n // (https://tools.ietf.org/html/rfc2616#section-4.2).\r\n\r\n var headersObject = {};\r\n var headersArray = this.getAllResponseHeaders().split('\\r\\n');\r\n for (var i = 0; i < headersArray.length; i++) {\r\n if (goog.string.isEmptyOrWhitespace(headersArray[i])) {\r\n continue;\r\n }\r\n var keyValue =\r\n goog.string.splitLimit(headersArray[i], ':', /* maxSplitCount= */ 1);\r\n var key = keyValue[0];\r\n var value = keyValue[1];\r\n\r\n if (!goog.isString(value)) {\r\n // There must be a value but it can be the empty string.\r\n continue;\r\n }\r\n\r\n // Whitespace at the start and end of the value is meaningless.\r\n value = value.trim();\r\n // The key should not contain whitespace but we currently ignore that.\r\n\r\n var values = headersObject[key] || [];\r\n headersObject[key] = values;\r\n values.push(value);\r\n }\r\n\r\n return goog.object.map(headersObject, function(values) {\r\n return values.join(', ');\r\n });\r\n};\r\n\r\n\r\n/**\r\n * Get the value of the response-header with the given name from the Xhr object.\r\n * As opposed to {@link #getResponseHeader}, this method does not require that\r\n * the request has completed.\r\n * @param {string} key The name of the response-header to retrieve.\r\n * @return {?string} The value of the response-header, or null if it is\r\n * unavailable.\r\n */\r\ngoog.net.XhrIo.prototype.getStreamingResponseHeader = function(key) {\r\n return this.xhr_ ? this.xhr_.getResponseHeader(key) : null;\r\n};\r\n\r\n\r\n/**\r\n * Gets the text of all the headers in the response. As opposed to\r\n * {@link #getAllResponseHeaders}, this method does not require that the request\r\n * has completed.\r\n * @return {string} The value of the response headers or empty string.\r\n */\r\ngoog.net.XhrIo.prototype.getAllStreamingResponseHeaders = function() {\r\n return this.xhr_ ? this.xhr_.getAllResponseHeaders() : '';\r\n};\r\n\r\n\r\n/**\r\n * Get the last error message\r\n * @return {!goog.net.ErrorCode} Last error code.\r\n */\r\ngoog.net.XhrIo.prototype.getLastErrorCode = function() {\r\n return this.lastErrorCode_;\r\n};\r\n\r\n\r\n/**\r\n * Get the last error message\r\n * @return {string} Last error message.\r\n */\r\ngoog.net.XhrIo.prototype.getLastError = function() {\r\n return goog.isString(this.lastError_) ? this.lastError_ :\r\n String(this.lastError_);\r\n};\r\n\r\n\r\n/**\r\n * Adds the last method, status and URI to the message. This is used to add\r\n * this information to the logging calls.\r\n * @param {string} msg The message text that we want to add the extra text to.\r\n * @return {string} The message with the extra text appended.\r\n * @private\r\n */\r\ngoog.net.XhrIo.prototype.formatMsg_ = function(msg) {\r\n return msg + ' [' + this.lastMethod_ + ' ' + this.lastUri_ + ' ' +\r\n this.getStatus() + ']';\r\n};\r\n\r\n\r\n// Register the xhr handler as an entry point, so that\r\n// it can be monitored for exception handling, etc.\r\ngoog.debug.entryPointRegistry.register(\r\n /**\r\n * @param {function(!Function): !Function} transformer The transforming\r\n * function.\r\n */\r\n function(transformer) {\r\n goog.net.XhrIo.prototype.onReadyStateChangeEntryPoint_ =\r\n transformer(goog.net.XhrIo.prototype.onReadyStateChangeEntryPoint_);\r\n });\r\n}); // goog.scope\r\n","// Copyright 2006 The Closure Library Authors. All Rights Reserved.\r\n//\r\n// Licensed under the Apache License, Version 2.0 (the \"License\");\r\n// you may not use this file except in compliance with the License.\r\n// You may obtain a copy of the License at\r\n//\r\n// http://www.apache.org/licenses/LICENSE-2.0\r\n//\r\n// Unless required by applicable law or agreed to in writing, software\r\n// distributed under the License is distributed on an \"AS-IS\" BASIS,\r\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n// See the License for the specific language governing permissions and\r\n// limitations under the License.\r\n\r\n/**\r\n * @fileoverview String functions called from Closure packages that couldn't\r\n * depend on each other. Outside Closure, use goog.string function which\r\n * delegate to these.\r\n */\r\n\r\n\r\ngoog.provide('goog.string.internal');\r\n\r\n\r\n/**\r\n * Fast prefix-checker.\r\n * @param {string} str The string to check.\r\n * @param {string} prefix A string to look for at the start of `str`.\r\n * @return {boolean} True if `str` begins with `prefix`.\r\n * @see goog.string.startsWith\r\n */\r\ngoog.string.internal.startsWith = function(str, prefix) {\r\n return str.lastIndexOf(prefix, 0) == 0;\r\n};\r\n\r\n\r\n/**\r\n * Fast suffix-checker.\r\n * @param {string} str The string to check.\r\n * @param {string} suffix A string to look for at the end of `str`.\r\n * @return {boolean} True if `str` ends with `suffix`.\r\n * @see goog.string.endsWith\r\n */\r\ngoog.string.internal.endsWith = function(str, suffix) {\r\n var l = str.length - suffix.length;\r\n return l >= 0 && str.indexOf(suffix, l) == l;\r\n};\r\n\r\n\r\n/**\r\n * Case-insensitive prefix-checker.\r\n * @param {string} str The string to check.\r\n * @param {string} prefix A string to look for at the end of `str`.\r\n * @return {boolean} True if `str` begins with `prefix` (ignoring\r\n * case).\r\n * @see goog.string.caseInsensitiveStartsWith\r\n */\r\ngoog.string.internal.caseInsensitiveStartsWith = function(str, prefix) {\r\n return goog.string.internal.caseInsensitiveCompare(\r\n prefix, str.substr(0, prefix.length)) == 0;\r\n};\r\n\r\n\r\n/**\r\n * Case-insensitive suffix-checker.\r\n * @param {string} str The string to check.\r\n * @param {string} suffix A string to look for at the end of `str`.\r\n * @return {boolean} True if `str` ends with `suffix` (ignoring\r\n * case).\r\n * @see goog.string.caseInsensitiveEndsWith\r\n */\r\ngoog.string.internal.caseInsensitiveEndsWith = function(str, suffix) {\r\n return (\r\n goog.string.internal.caseInsensitiveCompare(\r\n suffix, str.substr(str.length - suffix.length, suffix.length)) == 0);\r\n};\r\n\r\n\r\n/**\r\n * Case-insensitive equality checker.\r\n * @param {string} str1 First string to check.\r\n * @param {string} str2 Second string to check.\r\n * @return {boolean} True if `str1` and `str2` are the same string,\r\n * ignoring case.\r\n * @see goog.string.caseInsensitiveEquals\r\n */\r\ngoog.string.internal.caseInsensitiveEquals = function(str1, str2) {\r\n return str1.toLowerCase() == str2.toLowerCase();\r\n};\r\n\r\n\r\n/**\r\n * Checks if a string is empty or contains only whitespaces.\r\n * @param {string} str The string to check.\r\n * @return {boolean} Whether `str` is empty or whitespace only.\r\n * @see goog.string.isEmptyOrWhitespace\r\n */\r\ngoog.string.internal.isEmptyOrWhitespace = function(str) {\r\n // testing length == 0 first is actually slower in all browsers (about the\r\n // same in Opera).\r\n // Since IE doesn't include non-breaking-space (0xa0) in their \\s character\r\n // class (as required by section 7.2 of the ECMAScript spec), we explicitly\r\n // include it in the regexp to enforce consistent cross-browser behavior.\r\n return /^[\\s\\xa0]*$/.test(str);\r\n};\r\n\r\n\r\n/**\r\n * Trims white spaces to the left and right of a string.\r\n * @param {string} str The string to trim.\r\n * @return {string} A trimmed copy of `str`.\r\n */\r\ngoog.string.internal.trim =\r\n (goog.TRUSTED_SITE && String.prototype.trim) ? function(str) {\r\n return str.trim();\r\n } : function(str) {\r\n // Since IE doesn't include non-breaking-space (0xa0) in their \\s\r\n // character class (as required by section 7.2 of the ECMAScript spec),\r\n // we explicitly include it in the regexp to enforce consistent\r\n // cross-browser behavior.\r\n // NOTE: We don't use String#replace because it might have side effects\r\n // causing this function to not compile to 0 bytes.\r\n return /^[\\s\\xa0]*([\\s\\S]*?)[\\s\\xa0]*$/.exec(str)[1];\r\n };\r\n\r\n\r\n/**\r\n * A string comparator that ignores case.\r\n * -1 = str1 less than str2\r\n * 0 = str1 equals str2\r\n * 1 = str1 greater than str2\r\n *\r\n * @param {string} str1 The string to compare.\r\n * @param {string} str2 The string to compare `str1` to.\r\n * @return {number} The comparator result, as described above.\r\n * @see goog.string.caseInsensitiveCompare\r\n */\r\ngoog.string.internal.caseInsensitiveCompare = function(str1, str2) {\r\n var test1 = String(str1).toLowerCase();\r\n var test2 = String(str2).toLowerCase();\r\n\r\n if (test1 < test2) {\r\n return -1;\r\n } else if (test1 == test2) {\r\n return 0;\r\n } else {\r\n return 1;\r\n }\r\n};\r\n\r\n\r\n/**\r\n * Converts \\n to <br>s or <br />s.\r\n * @param {string} str The string in which to convert newlines.\r\n * @param {boolean=} opt_xml Whether to use XML compatible tags.\r\n * @return {string} A copy of `str` with converted newlines.\r\n * @see goog.string.newLineToBr\r\n */\r\ngoog.string.internal.newLineToBr = function(str, opt_xml) {\r\n return str.replace(/(\\r\\n|\\r|\\n)/g, opt_xml ? '<br />' : '<br>');\r\n};\r\n\r\n\r\n/**\r\n * Escapes double quote '\"' and single quote '\\'' characters in addition to\r\n * '&', '<', and '>' so that a string can be included in an HTML tag attribute\r\n * value within double or single quotes.\r\n * @param {string} str string to be escaped.\r\n * @param {boolean=} opt_isLikelyToContainHtmlChars\r\n * @return {string} An escaped copy of `str`.\r\n * @see goog.string.htmlEscape\r\n */\r\ngoog.string.internal.htmlEscape = function(\r\n str, opt_isLikelyToContainHtmlChars) {\r\n if (opt_isLikelyToContainHtmlChars) {\r\n str = str.replace(goog.string.internal.AMP_RE_, '&')\r\n .replace(goog.string.internal.LT_RE_, '<')\r\n .replace(goog.string.internal.GT_RE_, '>')\r\n .replace(goog.string.internal.QUOT_RE_, '"')\r\n .replace(goog.string.internal.SINGLE_QUOTE_RE_, ''')\r\n .replace(goog.string.internal.NULL_RE_, '�');\r\n return str;\r\n\r\n } else {\r\n // quick test helps in the case when there are no chars to replace, in\r\n // worst case this makes barely a difference to the time taken\r\n if (!goog.string.internal.ALL_RE_.test(str)) return str;\r\n\r\n // str.indexOf is faster than regex.test in this case\r\n if (str.indexOf('&') != -1) {\r\n str = str.replace(goog.string.internal.AMP_RE_, '&');\r\n }\r\n if (str.indexOf('<') != -1) {\r\n str = str.replace(goog.string.internal.LT_RE_, '<');\r\n }\r\n if (str.indexOf('>') != -1) {\r\n str = str.replace(goog.string.internal.GT_RE_, '>');\r\n }\r\n if (str.indexOf('\"') != -1) {\r\n str = str.replace(goog.string.internal.QUOT_RE_, '"');\r\n }\r\n if (str.indexOf('\\'') != -1) {\r\n str = str.replace(goog.string.internal.SINGLE_QUOTE_RE_, ''');\r\n }\r\n if (str.indexOf('\\x00') != -1) {\r\n str = str.replace(goog.string.internal.NULL_RE_, '�');\r\n }\r\n return str;\r\n }\r\n};\r\n\r\n\r\n/**\r\n * Regular expression that matches an ampersand, for use in escaping.\r\n * @const {!RegExp}\r\n * @private\r\n */\r\ngoog.string.internal.AMP_RE_ = /&/g;\r\n\r\n\r\n/**\r\n * Regular expression that matches a less than sign, for use in escaping.\r\n * @const {!RegExp}\r\n * @private\r\n */\r\ngoog.string.internal.LT_RE_ = /</g;\r\n\r\n\r\n/**\r\n * Regular expression that matches a greater than sign, for use in escaping.\r\n * @const {!RegExp}\r\n * @private\r\n */\r\ngoog.string.internal.GT_RE_ = />/g;\r\n\r\n\r\n/**\r\n * Regular expression that matches a double quote, for use in escaping.\r\n * @const {!RegExp}\r\n * @private\r\n */\r\ngoog.string.internal.QUOT_RE_ = /\"/g;\r\n\r\n\r\n/**\r\n * Regular expression that matches a single quote, for use in escaping.\r\n * @const {!RegExp}\r\n * @private\r\n */\r\ngoog.string.internal.SINGLE_QUOTE_RE_ = /'/g;\r\n\r\n\r\n/**\r\n * Regular expression that matches null character, for use in escaping.\r\n * @const {!RegExp}\r\n * @private\r\n */\r\ngoog.string.internal.NULL_RE_ = /\\x00/g;\r\n\r\n\r\n/**\r\n * Regular expression that matches any character that needs to be escaped.\r\n * @const {!RegExp}\r\n * @private\r\n */\r\ngoog.string.internal.ALL_RE_ = /[\\x00&<>\"']/;\r\n\r\n\r\n/**\r\n * Do escaping of whitespace to preserve spatial formatting. We use character\r\n * entity #160 to make it safer for xml.\r\n * @param {string} str The string in which to escape whitespace.\r\n * @param {boolean=} opt_xml Whether to use XML compatible tags.\r\n * @return {string} An escaped copy of `str`.\r\n * @see goog.string.whitespaceEscape\r\n */\r\ngoog.string.internal.whitespaceEscape = function(str, opt_xml) {\r\n // This doesn't use goog.string.preserveSpaces for backwards compatibility.\r\n return goog.string.internal.newLineToBr(\r\n str.replace(/ /g, '  '), opt_xml);\r\n};\r\n\r\n\r\n/**\r\n * Determines whether a string contains a substring.\r\n * @param {string} str The string to search.\r\n * @param {string} subString The substring to search for.\r\n * @return {boolean} Whether `str` contains `subString`.\r\n * @see goog.string.contains\r\n */\r\ngoog.string.internal.contains = function(str, subString) {\r\n return str.indexOf(subString) != -1;\r\n};\r\n\r\n\r\n/**\r\n * Determines whether a string contains a substring, ignoring case.\r\n * @param {string} str The string to search.\r\n * @param {string} subString The substring to search for.\r\n * @return {boolean} Whether `str` contains `subString`.\r\n * @see goog.string.caseInsensitiveContains\r\n */\r\ngoog.string.internal.caseInsensitiveContains = function(str, subString) {\r\n return goog.string.internal.contains(\r\n str.toLowerCase(), subString.toLowerCase());\r\n};\r\n\r\n\r\n/**\r\n * Compares two version numbers.\r\n *\r\n * @param {string|number} version1 Version of first item.\r\n * @param {string|number} version2 Version of second item.\r\n *\r\n * @return {number} 1 if `version1` is higher.\r\n * 0 if arguments are equal.\r\n * -1 if `version2` is higher.\r\n * @see goog.string.compareVersions\r\n */\r\ngoog.string.internal.compareVersions = function(version1, version2) {\r\n var order = 0;\r\n // Trim leading and trailing whitespace and split the versions into\r\n // subversions.\r\n var v1Subs = goog.string.internal.trim(String(version1)).split('.');\r\n var v2Subs = goog.string.internal.trim(String(version2)).split('.');\r\n var subCount = Math.max(v1Subs.length, v2Subs.length);\r\n\r\n // Iterate over the subversions, as long as they appear to be equivalent.\r\n for (var subIdx = 0; order == 0 && subIdx < subCount; subIdx++) {\r\n var v1Sub = v1Subs[subIdx] || '';\r\n var v2Sub = v2Subs[subIdx] || '';\r\n\r\n do {\r\n // Split the subversions into pairs of numbers and qualifiers (like 'b').\r\n // Two different RegExp objects are use to make it clear the code\r\n // is side-effect free\r\n var v1Comp = /(\\d*)(\\D*)(.*)/.exec(v1Sub) || ['', '', '', ''];\r\n var v2Comp = /(\\d*)(\\D*)(.*)/.exec(v2Sub) || ['', '', '', ''];\r\n // Break if there are no more matches.\r\n if (v1Comp[0].length == 0 && v2Comp[0].length == 0) {\r\n break;\r\n }\r\n\r\n // Parse the numeric part of the subversion. A missing number is\r\n // equivalent to 0.\r\n var v1CompNum = v1Comp[1].length == 0 ? 0 : parseInt(v1Comp[1], 10);\r\n var v2CompNum = v2Comp[1].length == 0 ? 0 : parseInt(v2Comp[1], 10);\r\n\r\n // Compare the subversion components. The number has the highest\r\n // precedence. Next, if the numbers are equal, a subversion without any\r\n // qualifier is always higher than a subversion with any qualifier. Next,\r\n // the qualifiers are compared as strings.\r\n order = goog.string.internal.compareElements_(v1CompNum, v2CompNum) ||\r\n goog.string.internal.compareElements_(\r\n v1Comp[2].length == 0, v2Comp[2].length == 0) ||\r\n goog.string.internal.compareElements_(v1Comp[2], v2Comp[2]);\r\n // Stop as soon as an inequality is discovered.\r\n\r\n v1Sub = v1Comp[3];\r\n v2Sub = v2Comp[3];\r\n } while (order == 0);\r\n }\r\n\r\n return order;\r\n};\r\n\r\n\r\n/**\r\n * Compares elements of a version number.\r\n *\r\n * @param {string|number|boolean} left An element from a version number.\r\n * @param {string|number|boolean} right An element from a version number.\r\n *\r\n * @return {number} 1 if `left` is higher.\r\n * 0 if arguments are equal.\r\n * -1 if `right` is higher.\r\n * @private\r\n */\r\ngoog.string.internal.compareElements_ = function(left, right) {\r\n if (left < right) {\r\n return -1;\r\n } else if (left > right) {\r\n return 1;\r\n }\r\n return 0;\r\n};\r\n","// Copyright 2013 The Closure Library Authors. All Rights Reserved.\r\n//\r\n// Licensed under the Apache License, Version 2.0 (the \"License\");\r\n// you may not use this file except in compliance with the License.\r\n// You may obtain a copy of the License at\r\n//\r\n// http://www.apache.org/licenses/LICENSE-2.0\r\n//\r\n// Unless required by applicable law or agreed to in writing, software\r\n// distributed under the License is distributed on an \"AS-IS\" BASIS,\r\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n// See the License for the specific language governing permissions and\r\n// limitations under the License.\r\n\r\n/**\r\n * @fileoverview Utilities used by goog.labs.userAgent tools. These functions\r\n * should not be used outside of goog.labs.userAgent.*.\r\n *\r\n * @author nnaze@google.com (Nathan Naze)\r\n */\r\n\r\ngoog.provide('goog.labs.userAgent.util');\r\n\r\ngoog.require('goog.string.internal');\r\n\r\n\r\n/**\r\n * Gets the native userAgent string from navigator if it exists.\r\n * If navigator or navigator.userAgent string is missing, returns an empty\r\n * string.\r\n * @return {string}\r\n * @private\r\n */\r\ngoog.labs.userAgent.util.getNativeUserAgentString_ = function() {\r\n var navigator = goog.labs.userAgent.util.getNavigator_();\r\n if (navigator) {\r\n var userAgent = navigator.userAgent;\r\n if (userAgent) {\r\n return userAgent;\r\n }\r\n }\r\n return '';\r\n};\r\n\r\n\r\n/**\r\n * Getter for the native navigator.\r\n * This is a separate function so it can be stubbed out in testing.\r\n * @return {Navigator}\r\n * @private\r\n */\r\ngoog.labs.userAgent.util.getNavigator_ = function() {\r\n return goog.global.navigator;\r\n};\r\n\r\n\r\n/**\r\n * A possible override for applications which wish to not check\r\n * navigator.userAgent but use a specified value for detection instead.\r\n * @private {string}\r\n */\r\ngoog.labs.userAgent.util.userAgent_ =\r\n goog.labs.userAgent.util.getNativeUserAgentString_();\r\n\r\n\r\n/**\r\n * Applications may override browser detection on the built in\r\n * navigator.userAgent object by setting this string. Set to null to use the\r\n * browser object instead.\r\n * @param {?string=} opt_userAgent The User-Agent override.\r\n */\r\ngoog.labs.userAgent.util.setUserAgent = function(opt_userAgent) {\r\n goog.labs.userAgent.util.userAgent_ =\r\n opt_userAgent || goog.labs.userAgent.util.getNativeUserAgentString_();\r\n};\r\n\r\n\r\n/**\r\n * @return {string} The user agent string.\r\n */\r\ngoog.labs.userAgent.util.getUserAgent = function() {\r\n return goog.labs.userAgent.util.userAgent_;\r\n};\r\n\r\n\r\n/**\r\n * @param {string} str\r\n * @return {boolean} Whether the user agent contains the given string.\r\n */\r\ngoog.labs.userAgent.util.matchUserAgent = function(str) {\r\n var userAgent = goog.labs.userAgent.util.getUserAgent();\r\n return goog.string.internal.contains(userAgent, str);\r\n};\r\n\r\n\r\n/**\r\n * @param {string} str\r\n * @return {boolean} Whether the user agent contains the given string, ignoring\r\n * case.\r\n */\r\ngoog.labs.userAgent.util.matchUserAgentIgnoreCase = function(str) {\r\n var userAgent = goog.labs.userAgent.util.getUserAgent();\r\n return goog.string.internal.caseInsensitiveContains(userAgent, str);\r\n};\r\n\r\n\r\n/**\r\n * Parses the user agent into tuples for each section.\r\n * @param {string} userAgent\r\n * @return {!Array<!Array<string>>} Tuples of key, version, and the contents\r\n * of the parenthetical.\r\n */\r\ngoog.labs.userAgent.util.extractVersionTuples = function(userAgent) {\r\n // Matches each section of a user agent string.\r\n // Example UA:\r\n // Mozilla/5.0 (iPad; U; CPU OS 3_2_1 like Mac OS X; en-us)\r\n // AppleWebKit/531.21.10 (KHTML, like Gecko) Mobile/7B405\r\n // This has three version tuples: Mozilla, AppleWebKit, and Mobile.\r\n\r\n var versionRegExp = new RegExp(\r\n // Key. Note that a key may have a space.\r\n // (i.e. 'Mobile Safari' in 'Mobile Safari/5.0')\r\n '(\\\\w[\\\\w ]+)' +\r\n\r\n '/' + // slash\r\n '([^\\\\s]+)' + // version (i.e. '5.0b')\r\n '\\\\s*' + // whitespace\r\n '(?:\\\\((.*?)\\\\))?', // parenthetical info. parentheses not matched.\r\n 'g');\r\n\r\n var data = [];\r\n var match;\r\n\r\n // Iterate and collect the version tuples. Each iteration will be the\r\n // next regex match.\r\n while (match = versionRegExp.exec(userAgent)) {\r\n data.push([\r\n match[1], // key\r\n match[2], // value\r\n // || undefined as this is not undefined in IE7 and IE8\r\n match[3] || undefined // info\r\n ]);\r\n }\r\n\r\n return data;\r\n};\r\n","// Copyright 2006 The Closure Library Authors. All Rights Reserved.\r\n//\r\n// Licensed under the Apache License, Version 2.0 (the \"License\");\r\n// you may not use this file except in compliance with the License.\r\n// You may obtain a copy of the License at\r\n//\r\n// http://www.apache.org/licenses/LICENSE-2.0\r\n//\r\n// Unless required by applicable law or agreed to in writing, software\r\n// distributed under the License is distributed on an \"AS-IS\" BASIS,\r\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n// See the License for the specific language governing permissions and\r\n// limitations under the License.\r\n\r\n/**\r\n * @fileoverview Utilities for manipulating objects/maps/hashes.\r\n * @author arv@google.com (Erik Arvidsson)\r\n */\r\n\r\ngoog.provide('goog.object');\r\n\r\n\r\n/**\r\n * Whether two values are not observably distinguishable. This\r\n * correctly detects that 0 is not the same as -0 and two NaNs are\r\n * practically equivalent.\r\n *\r\n * The implementation is as suggested by harmony:egal proposal.\r\n *\r\n * @param {*} v The first value to compare.\r\n * @param {*} v2 The second value to compare.\r\n * @return {boolean} Whether two values are not observably distinguishable.\r\n * @see http://wiki.ecmascript.org/doku.php?id=harmony:egal\r\n */\r\ngoog.object.is = function(v, v2) {\r\n if (v === v2) {\r\n // 0 === -0, but they are not identical.\r\n // We need the cast because the compiler requires that v2 is a\r\n // number (although 1/v2 works with non-number). We cast to ? to\r\n // stop the compiler from type-checking this statement.\r\n return v !== 0 || 1 / v === 1 / /** @type {?} */ (v2);\r\n }\r\n\r\n // NaN is non-reflexive: NaN !== NaN, although they are identical.\r\n return v !== v && v2 !== v2;\r\n};\r\n\r\n\r\n/**\r\n * Calls a function for each element in an object/map/hash.\r\n *\r\n * @param {Object<K,V>} obj The object over which to iterate.\r\n * @param {function(this:T,V,?,Object<K,V>):?} f The function to call\r\n * for every element. This function takes 3 arguments (the value, the\r\n * key and the object) and the return value is ignored.\r\n * @param {T=} opt_obj This is used as the 'this' object within f.\r\n * @template T,K,V\r\n */\r\ngoog.object.forEach = function(obj, f, opt_obj) {\r\n for (var key in obj) {\r\n f.call(/** @type {?} */ (opt_obj), obj[key], key, obj);\r\n }\r\n};\r\n\r\n\r\n/**\r\n * Calls a function for each element in an object/map/hash. If that call returns\r\n * true, adds the element to a new object.\r\n *\r\n * @param {Object<K,V>} obj The object over which to iterate.\r\n * @param {function(this:T,V,?,Object<K,V>):boolean} f The function to call\r\n * for every element. This\r\n * function takes 3 arguments (the value, the key and the object)\r\n * and should return a boolean. If the return value is true the\r\n * element is added to the result object. If it is false the\r\n * element is not included.\r\n * @param {T=} opt_obj This is used as the 'this' object within f.\r\n * @return {!Object<K,V>} a new object in which only elements that passed the\r\n * test are present.\r\n * @template T,K,V\r\n */\r\ngoog.object.filter = function(obj, f, opt_obj) {\r\n var res = {};\r\n for (var key in obj) {\r\n if (f.call(/** @type {?} */ (opt_obj), obj[key], key, obj)) {\r\n res[key] = obj[key];\r\n }\r\n }\r\n return res;\r\n};\r\n\r\n\r\n/**\r\n * For every element in an object/map/hash calls a function and inserts the\r\n * result into a new object.\r\n *\r\n * @param {Object<K,V>} obj The object over which to iterate.\r\n * @param {function(this:T,V,?,Object<K,V>):R} f The function to call\r\n * for every element. This function\r\n * takes 3 arguments (the value, the key and the object)\r\n * and should return something. The result will be inserted\r\n * into a new object.\r\n * @param {T=} opt_obj This is used as the 'this' object within f.\r\n * @return {!Object<K,R>} a new object with the results from f.\r\n * @template T,K,V,R\r\n */\r\ngoog.object.map = function(obj, f, opt_obj) {\r\n var res = {};\r\n for (var key in obj) {\r\n res[key] = f.call(/** @type {?} */ (opt_obj), obj[key], key, obj);\r\n }\r\n return res;\r\n};\r\n\r\n\r\n/**\r\n * Calls a function for each element in an object/map/hash. If any\r\n * call returns true, returns true (without checking the rest). If\r\n * all calls return false, returns false.\r\n *\r\n * @param {Object<K,V>} obj The object to check.\r\n * @param {function(this:T,V,?,Object<K,V>):boolean} f The function to\r\n * call for every element. This function\r\n * takes 3 arguments (the value, the key and the object) and should\r\n * return a boolean.\r\n * @param {T=} opt_obj This is used as the 'this' object within f.\r\n * @return {boolean} true if any element passes the test.\r\n * @template T,K,V\r\n */\r\ngoog.object.some = function(obj, f, opt_obj) {\r\n for (var key in obj) {\r\n if (f.call(/** @type {?} */ (opt_obj), obj[key], key, obj)) {\r\n return true;\r\n }\r\n }\r\n return false;\r\n};\r\n\r\n\r\n/**\r\n * Calls a function for each element in an object/map/hash. If\r\n * all calls return true, returns true. If any call returns false, returns\r\n * false at this point and does not continue to check the remaining elements.\r\n *\r\n * @param {Object<K,V>} obj The object to check.\r\n * @param {?function(this:T,V,?,Object<K,V>):boolean} f The function to\r\n * call for every element. This function\r\n * takes 3 arguments (the value, the key and the object) and should\r\n * return a boolean.\r\n * @param {T=} opt_obj This is used as the 'this' object within f.\r\n * @return {boolean} false if any element fails the test.\r\n * @template T,K,V\r\n */\r\ngoog.object.every = function(obj, f, opt_obj) {\r\n for (var key in obj) {\r\n if (!f.call(/** @type {?} */ (opt_obj), obj[key], key, obj)) {\r\n return false;\r\n }\r\n }\r\n return true;\r\n};\r\n\r\n\r\n/**\r\n * Returns the number of key-value pairs in the object map.\r\n *\r\n * @param {Object} obj The object for which to get the number of key-value\r\n * pairs.\r\n * @return {number} The number of key-value pairs in the object map.\r\n */\r\ngoog.object.getCount = function(obj) {\r\n var rv = 0;\r\n for (var key in obj) {\r\n rv++;\r\n }\r\n return rv;\r\n};\r\n\r\n\r\n/**\r\n * Returns one key from the object map, if any exists.\r\n * For map literals the returned key will be the first one in most of the\r\n * browsers (a know exception is Konqueror).\r\n *\r\n * @param {Object} obj The object to pick a key from.\r\n * @return {string|undefined} The key or undefined if the object is empty.\r\n */\r\ngoog.object.getAnyKey = function(obj) {\r\n for (var key in obj) {\r\n return key;\r\n }\r\n};\r\n\r\n\r\n/**\r\n * Returns one value from the object map, if any exists.\r\n * For map literals the returned value will be the first one in most of the\r\n * browsers (a know exception is Konqueror).\r\n *\r\n * @param {Object<K,V>} obj The object to pick a value from.\r\n * @return {V|undefined} The value or undefined if the object is empty.\r\n * @template K,V\r\n */\r\ngoog.object.getAnyValue = function(obj) {\r\n for (var key in obj) {\r\n return obj[key];\r\n }\r\n};\r\n\r\n\r\n/**\r\n * Whether the object/hash/map contains the given object as a value.\r\n * An alias for goog.object.containsValue(obj, val).\r\n *\r\n * @param {Object<K,V>} obj The object in which to look for val.\r\n * @param {V} val The object for which to check.\r\n * @return {boolean} true if val is present.\r\n * @template K,V\r\n */\r\ngoog.object.contains = function(obj, val) {\r\n return goog.object.containsValue(obj, val);\r\n};\r\n\r\n\r\n/**\r\n * Returns the values of the object/map/hash.\r\n *\r\n * @param {Object<K,V>} obj The object from which to get the values.\r\n * @return {!Array<V>} The values in the object/map/hash.\r\n * @template K,V\r\n */\r\ngoog.object.getValues = function(obj) {\r\n var res = [];\r\n var i = 0;\r\n for (var key in obj) {\r\n res[i++] = obj[key];\r\n }\r\n return res;\r\n};\r\n\r\n\r\n/**\r\n * Returns the keys of the object/map/hash.\r\n *\r\n * @param {Object} obj The object from which to get the keys.\r\n * @return {!Array<string>} Array of property keys.\r\n */\r\ngoog.object.getKeys = function(obj) {\r\n var res = [];\r\n var i = 0;\r\n for (var key in obj) {\r\n res[i++] = key;\r\n }\r\n return res;\r\n};\r\n\r\n\r\n/**\r\n * Get a value from an object multiple levels deep. This is useful for\r\n * pulling values from deeply nested objects, such as JSON responses.\r\n * Example usage: getValueByKeys(jsonObj, 'foo', 'entries', 3)\r\n *\r\n * @param {!Object} obj An object to get the value from. Can be array-like.\r\n * @param {...(string|number|!IArrayLike<number|string>)}\r\n * var_args A number of keys\r\n * (as strings, or numbers, for array-like objects). Can also be\r\n * specified as a single array of keys.\r\n * @return {*} The resulting value. If, at any point, the value for a key\r\n * in the current object is null or undefined, returns undefined.\r\n */\r\ngoog.object.getValueByKeys = function(obj, var_args) {\r\n var isArrayLike = goog.isArrayLike(var_args);\r\n var keys = isArrayLike ?\r\n /** @type {!IArrayLike<number|string>} */ (var_args) :\r\n arguments;\r\n\r\n // Start with the 2nd parameter for the variable parameters syntax.\r\n for (var i = isArrayLike ? 0 : 1; i < keys.length; i++) {\r\n if (obj == null) return undefined;\r\n obj = obj[keys[i]];\r\n }\r\n\r\n return obj;\r\n};\r\n\r\n\r\n/**\r\n * Whether the object/map/hash contains the given key.\r\n *\r\n * @param {Object} obj The object in which to look for key.\r\n * @param {?} key The key for which to check.\r\n * @return {boolean} true If the map contains the key.\r\n */\r\ngoog.object.containsKey = function(obj, key) {\r\n return obj !== null && key in obj;\r\n};\r\n\r\n\r\n/**\r\n * Whether the object/map/hash contains the given value. This is O(n).\r\n *\r\n * @param {Object<K,V>} obj The object in which to look for val.\r\n * @param {V} val The value for which to check.\r\n * @return {boolean} true If the map contains the value.\r\n * @template K,V\r\n */\r\ngoog.object.containsValue = function(obj, val) {\r\n for (var key in obj) {\r\n if (obj[key] == val) {\r\n return true;\r\n }\r\n }\r\n return false;\r\n};\r\n\r\n\r\n/**\r\n * Searches an object for an element that satisfies the given condition and\r\n * returns its key.\r\n * @param {Object<K,V>} obj The object to search in.\r\n * @param {function(this:T,V,string,Object<K,V>):boolean} f The\r\n * function to call for every element. Takes 3 arguments (the value,\r\n * the key and the object) and should return a boolean.\r\n * @param {T=} opt_this An optional \"this\" context for the function.\r\n * @return {string|undefined} The key of an element for which the function\r\n * returns true or undefined if no such element is found.\r\n * @template T,K,V\r\n */\r\ngoog.object.findKey = function(obj, f, opt_this) {\r\n for (var key in obj) {\r\n if (f.call(/** @type {?} */ (opt_this), obj[key], key, obj)) {\r\n return key;\r\n }\r\n }\r\n return undefined;\r\n};\r\n\r\n\r\n/**\r\n * Searches an object for an element that satisfies the given condition and\r\n * returns its value.\r\n * @param {Object<K,V>} obj The object to search in.\r\n * @param {function(this:T,V,string,Object<K,V>):boolean} f The function\r\n * to call for every element. Takes 3 arguments (the value, the key\r\n * and the object) and should return a boolean.\r\n * @param {T=} opt_this An optional \"this\" context for the function.\r\n * @return {V} The value of an element for which the function returns true or\r\n * undefined if no such element is found.\r\n * @template T,K,V\r\n */\r\ngoog.object.findValue = function(obj, f, opt_this) {\r\n var key = goog.object.findKey(obj, f, opt_this);\r\n return key && obj[key];\r\n};\r\n\r\n\r\n/**\r\n * Whether the object/map/hash is empty.\r\n *\r\n * @param {Object} obj The object to test.\r\n * @return {boolean} true if obj is empty.\r\n */\r\ngoog.object.isEmpty = function(obj) {\r\n for (var key in obj) {\r\n return false;\r\n }\r\n return true;\r\n};\r\n\r\n\r\n/**\r\n * Removes all key value pairs from the object/map/hash.\r\n *\r\n * @param {Object} obj The object to clear.\r\n */\r\ngoog.object.clear = function(obj) {\r\n for (var i in obj) {\r\n delete obj[i];\r\n }\r\n};\r\n\r\n\r\n/**\r\n * Removes a key-value pair based on the key.\r\n *\r\n * @param {Object} obj The object from which to remove the key.\r\n * @param {?} key The key to remove.\r\n * @return {boolean} Whether an element was removed.\r\n */\r\ngoog.object.remove = function(obj, key) {\r\n var rv;\r\n if (rv = key in /** @type {!Object} */ (obj)) {\r\n delete obj[key];\r\n }\r\n return rv;\r\n};\r\n\r\n\r\n/**\r\n * Adds a key-value pair to the object. Throws an exception if the key is\r\n * already in use. Use set if you want to change an existing pair.\r\n *\r\n * @param {Object<K,V>} obj The object to which to add the key-value pair.\r\n * @param {string} key The key to add.\r\n * @param {V} val The value to add.\r\n * @template K,V\r\n */\r\ngoog.object.add = function(obj, key, val) {\r\n if (obj !== null && key in obj) {\r\n throw new Error('The object already contains the key \"' + key + '\"');\r\n }\r\n goog.object.set(obj, key, val);\r\n};\r\n\r\n\r\n/**\r\n * Returns the value for the given key.\r\n *\r\n * @param {Object<K,V>} obj The object from which to get the value.\r\n * @param {string} key The key for which to get the value.\r\n * @param {R=} opt_val The value to return if no item is found for the given\r\n * key (default is undefined).\r\n * @return {V|R|undefined} The value for the given key.\r\n * @template K,V,R\r\n */\r\ngoog.object.get = function(obj, key, opt_val) {\r\n if (obj !== null && key in obj) {\r\n return obj[key];\r\n }\r\n return opt_val;\r\n};\r\n\r\n\r\n/**\r\n * Adds a key-value pair to the object/map/hash.\r\n *\r\n * @param {Object<K,V>} obj The object to which to add the key-value pair.\r\n * @param {string} key The key to add.\r\n * @param {V} value The value to add.\r\n * @template K,V\r\n */\r\ngoog.object.set = function(obj, key, value) {\r\n obj[key] = value;\r\n};\r\n\r\n\r\n/**\r\n * Adds a key-value pair to the object/map/hash if it doesn't exist yet.\r\n *\r\n * @param {Object<K,V>} obj The object to which to add the key-value pair.\r\n * @param {string} key The key to add.\r\n * @param {V} value The value to add if the key wasn't present.\r\n * @return {V} The value of the entry at the end of the function.\r\n * @template K,V\r\n */\r\ngoog.object.setIfUndefined = function(obj, key, value) {\r\n return key in /** @type {!Object} */ (obj) ? obj[key] : (obj[key] = value);\r\n};\r\n\r\n\r\n/**\r\n * Sets a key and value to an object if the key is not set. The value will be\r\n * the return value of the given function. If the key already exists, the\r\n * object will not be changed and the function will not be called (the function\r\n * will be lazily evaluated -- only called if necessary).\r\n *\r\n * This function is particularly useful when used with an `Object` which is\r\n * acting as a cache.\r\n *\r\n * @param {!Object<K,V>} obj The object to which to add the key-value pair.\r\n * @param {string} key The key to add.\r\n * @param {function():V} f The value to add if the key wasn't present.\r\n * @return {V} The value of the entry at the end of the function.\r\n * @template K,V\r\n */\r\ngoog.object.setWithReturnValueIfNotSet = function(obj, key, f) {\r\n if (key in obj) {\r\n return obj[key];\r\n }\r\n\r\n var val = f();\r\n obj[key] = val;\r\n return val;\r\n};\r\n\r\n\r\n/**\r\n * Compares two objects for equality using === on the values.\r\n *\r\n * @param {!Object<K,V>} a\r\n * @param {!Object<K,V>} b\r\n * @return {boolean}\r\n * @template K,V\r\n */\r\ngoog.object.equals = function(a, b) {\r\n for (var k in a) {\r\n if (!(k in b) || a[k] !== b[k]) {\r\n return false;\r\n }\r\n }\r\n for (var k in b) {\r\n if (!(k in a)) {\r\n return false;\r\n }\r\n }\r\n return true;\r\n};\r\n\r\n\r\n/**\r\n * Returns a shallow clone of the object.\r\n *\r\n * @param {Object<K,V>} obj Object to clone.\r\n * @return {!Object<K,V>} Clone of the input object.\r\n * @template K,V\r\n */\r\ngoog.object.clone = function(obj) {\r\n // We cannot use the prototype trick because a lot of methods depend on where\r\n // the actual key is set.\r\n\r\n var res = {};\r\n for (var key in obj) {\r\n res[key] = obj[key];\r\n }\r\n return res;\r\n // We could also use goog.mixin but I wanted this to be independent from that.\r\n};\r\n\r\n\r\n/**\r\n * Clones a value. The input may be an Object, Array, or basic type. Objects and\r\n * arrays will be cloned recursively.\r\n *\r\n * WARNINGS:\r\n * <code>goog.object.unsafeClone</code> does not detect reference loops. Objects\r\n * that refer to themselves will cause infinite recursion.\r\n *\r\n * <code>goog.object.unsafeClone</code> is unaware of unique identifiers, and\r\n * copies UIDs created by <code>getUid</code> into cloned results.\r\n *\r\n * @param {T} obj The value to clone.\r\n * @return {T} A clone of the input value.\r\n * @template T\r\n */\r\ngoog.object.unsafeClone = function(obj) {\r\n var type = goog.typeOf(obj);\r\n if (type == 'object' || type == 'array') {\r\n if (goog.isFunction(obj.clone)) {\r\n return obj.clone();\r\n }\r\n var clone = type == 'array' ? [] : {};\r\n for (var key in obj) {\r\n clone[key] = goog.object.unsafeClone(obj[key]);\r\n }\r\n return clone;\r\n }\r\n\r\n return obj;\r\n};\r\n\r\n\r\n/**\r\n * Returns a new object in which all the keys and values are interchanged\r\n * (keys become values and values become keys). If multiple keys map to the\r\n * same value, the chosen transposed value is implementation-dependent.\r\n *\r\n * @param {Object} obj The object to transpose.\r\n * @return {!Object} The transposed object.\r\n */\r\ngoog.object.transpose = function(obj) {\r\n var transposed = {};\r\n for (var key in obj) {\r\n transposed[obj[key]] = key;\r\n }\r\n return transposed;\r\n};\r\n\r\n\r\n/**\r\n * The names of the fields that are defined on Object.prototype.\r\n * @type {Array<string>}\r\n * @private\r\n */\r\ngoog.object.PROTOTYPE_FIELDS_ = [\r\n 'constructor', 'hasOwnProperty', 'isPrototypeOf', 'propertyIsEnumerable',\r\n 'toLocaleString', 'toString', 'valueOf'\r\n];\r\n\r\n\r\n/**\r\n * Extends an object with another object.\r\n * This operates 'in-place'; it does not create a new Object.\r\n *\r\n * Example:\r\n * var o = {};\r\n * goog.object.extend(o, {a: 0, b: 1});\r\n * o; // {a: 0, b: 1}\r\n * goog.object.extend(o, {b: 2, c: 3});\r\n * o; // {a: 0, b: 2, c: 3}\r\n *\r\n * @param {Object} target The object to modify. Existing properties will be\r\n * overwritten if they are also present in one of the objects in\r\n * `var_args`.\r\n * @param {...(Object|null|undefined)} var_args The objects from which values\r\n * will be copied.\r\n */\r\ngoog.object.extend = function(target, var_args) {\r\n var key, source;\r\n for (var i = 1; i < arguments.length; i++) {\r\n source = arguments[i];\r\n for (key in source) {\r\n target[key] = source[key];\r\n }\r\n\r\n // For IE the for-in-loop does not contain any properties that are not\r\n // enumerable on the prototype object (for example isPrototypeOf from\r\n // Object.prototype) and it will also not include 'replace' on objects that\r\n // extend String and change 'replace' (not that it is common for anyone to\r\n // extend anything except Object).\r\n\r\n for (var j = 0; j < goog.object.PROTOTYPE_FIELDS_.length; j++) {\r\n key = goog.object.PROTOTYPE_FIELDS_[j];\r\n if (Object.prototype.hasOwnProperty.call(source, key)) {\r\n target[key] = source[key];\r\n }\r\n }\r\n }\r\n};\r\n\r\n\r\n/**\r\n * Creates a new object built from the key-value pairs provided as arguments.\r\n * @param {...*} var_args If only one argument is provided and it is an array\r\n * then this is used as the arguments, otherwise even arguments are used as\r\n * the property names and odd arguments are used as the property values.\r\n * @return {!Object} The new object.\r\n * @throws {Error} If there are uneven number of arguments or there is only one\r\n * non array argument.\r\n */\r\ngoog.object.create = function(var_args) {\r\n var argLength = arguments.length;\r\n if (argLength == 1 && goog.isArray(arguments[0])) {\r\n return goog.object.create.apply(null, arguments[0]);\r\n }\r\n\r\n if (argLength % 2) {\r\n throw new Error('Uneven number of arguments');\r\n }\r\n\r\n var rv = {};\r\n for (var i = 0; i < argLength; i += 2) {\r\n rv[arguments[i]] = arguments[i + 1];\r\n }\r\n return rv;\r\n};\r\n\r\n\r\n/**\r\n * Creates a new object where the property names come from the arguments but\r\n * the value is always set to true\r\n * @param {...*} var_args If only one argument is provided and it is an array\r\n * then this is used as the arguments, otherwise the arguments are used\r\n * as the property names.\r\n * @return {!Object} The new object.\r\n */\r\ngoog.object.createSet = function(var_args) {\r\n var argLength = arguments.length;\r\n if (argLength == 1 && goog.isArray(arguments[0])) {\r\n return goog.object.createSet.apply(null, arguments[0]);\r\n }\r\n\r\n var rv = {};\r\n for (var i = 0; i < argLength; i++) {\r\n rv[arguments[i]] = true;\r\n }\r\n return rv;\r\n};\r\n\r\n\r\n/**\r\n * Creates an immutable view of the underlying object, if the browser\r\n * supports immutable objects.\r\n *\r\n * In default mode, writes to this view will fail silently. In strict mode,\r\n * they will throw an error.\r\n *\r\n * @param {!Object<K,V>} obj An object.\r\n * @return {!Object<K,V>} An immutable view of that object, or the\r\n * original object if this browser does not support immutables.\r\n * @template K,V\r\n */\r\ngoog.object.createImmutableView = function(obj) {\r\n var result = obj;\r\n if (Object.isFrozen && !Object.isFrozen(obj)) {\r\n result = Object.create(obj);\r\n Object.freeze(result);\r\n }\r\n return result;\r\n};\r\n\r\n\r\n/**\r\n * @param {!Object} obj An object.\r\n * @return {boolean} Whether this is an immutable view of the object.\r\n */\r\ngoog.object.isImmutableView = function(obj) {\r\n return !!Object.isFrozen && Object.isFrozen(obj);\r\n};\r\n\r\n\r\n/**\r\n * Get all properties names on a given Object regardless of enumerability.\r\n *\r\n * <p> If the browser does not support `Object.getOwnPropertyNames` nor\r\n * `Object.getPrototypeOf` then this is equivalent to using\r\n * `goog.object.getKeys`\r\n *\r\n * @param {?Object} obj The object to get the properties of.\r\n * @param {boolean=} opt_includeObjectPrototype Whether properties defined on\r\n * `Object.prototype` should be included in the result.\r\n * @param {boolean=} opt_includeFunctionPrototype Whether properties defined on\r\n * `Function.prototype` should be included in the result.\r\n * @return {!Array<string>}\r\n * @public\r\n */\r\ngoog.object.getAllPropertyNames = function(\r\n obj, opt_includeObjectPrototype, opt_includeFunctionPrototype) {\r\n if (!obj) {\r\n return [];\r\n }\r\n\r\n // Naively use a for..in loop to get the property names if the browser doesn't\r\n // support any other APIs for getting it.\r\n if (!Object.getOwnPropertyNames || !Object.getPrototypeOf) {\r\n return goog.object.getKeys(obj);\r\n }\r\n\r\n var visitedSet = {};\r\n\r\n // Traverse the prototype chain and add all properties to the visited set.\r\n var proto = obj;\r\n while (proto &&\r\n (proto !== Object.prototype || !!opt_includeObjectPrototype) &&\r\n (proto !== Function.prototype || !!opt_includeFunctionPrototype)) {\r\n var names = Object.getOwnPropertyNames(proto);\r\n for (var i = 0; i < names.length; i++) {\r\n visitedSet[names[i]] = true;\r\n }\r\n proto = Object.getPrototypeOf(proto);\r\n }\r\n\r\n return goog.object.getKeys(visitedSet);\r\n};\r\n","// Copyright 2009 The Closure Library Authors. All Rights Reserved.\r\n//\r\n// Licensed under the Apache License, Version 2.0 (the \"License\");\r\n// you may not use this file except in compliance with the License.\r\n// You may obtain a copy of the License at\r\n//\r\n// http://www.apache.org/licenses/LICENSE-2.0\r\n//\r\n// Unless required by applicable law or agreed to in writing, software\r\n// distributed under the License is distributed on an \"AS-IS\" BASIS,\r\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n// See the License for the specific language governing permissions and\r\n// limitations under the License.\r\n\r\n/**\r\n * @fileoverview Useful compiler idioms.\r\n *\r\n * @author johnlenz@google.com (John Lenz)\r\n */\r\n\r\ngoog.provide('goog.reflect');\r\n\r\n\r\n/**\r\n * Syntax for object literal casts.\r\n * @see http://go/jscompiler-renaming\r\n * @see https://goo.gl/CRs09P\r\n *\r\n * Use this if you have an object literal whose keys need to have the same names\r\n * as the properties of some class even after they are renamed by the compiler.\r\n *\r\n * @param {!Function} type Type to cast to.\r\n * @param {Object} object Object literal to cast.\r\n * @return {Object} The object literal.\r\n */\r\ngoog.reflect.object = function(type, object) {\r\n return object;\r\n};\r\n\r\n/**\r\n * Syntax for renaming property strings.\r\n * @see http://go/jscompiler-renaming\r\n * @see https://goo.gl/CRs09P\r\n *\r\n * Use this if you have an need to access a property as a string, but want\r\n * to also have the property renamed by the compiler. In contrast to\r\n * goog.reflect.object, this method takes an instance of an object.\r\n *\r\n * Properties must be simple names (not qualified names).\r\n *\r\n * @param {string} prop Name of the property\r\n * @param {!Object} object Instance of the object whose type will be used\r\n * for renaming\r\n * @return {string} The renamed property.\r\n */\r\ngoog.reflect.objectProperty = function(prop, object) {\r\n return prop;\r\n};\r\n\r\n/**\r\n * To assert to the compiler that an operation is needed when it would\r\n * otherwise be stripped. For example:\r\n * <code>\r\n * // Force a layout\r\n * goog.reflect.sinkValue(dialog.offsetHeight);\r\n * </code>\r\n * @param {T} x\r\n * @return {T}\r\n * @template T\r\n */\r\ngoog.reflect.sinkValue = function(x) {\r\n goog.reflect.sinkValue[' '](x);\r\n return x;\r\n};\r\n\r\n\r\n/**\r\n * The compiler should optimize this function away iff no one ever uses\r\n * goog.reflect.sinkValue.\r\n */\r\ngoog.reflect.sinkValue[' '] = goog.nullFunction;\r\n\r\n\r\n/**\r\n * Check if a property can be accessed without throwing an exception.\r\n * @param {Object} obj The owner of the property.\r\n * @param {string} prop The property name.\r\n * @return {boolean} Whether the property is accessible. Will also return true\r\n * if obj is null.\r\n */\r\ngoog.reflect.canAccessProperty = function(obj, prop) {\r\n\r\n try {\r\n goog.reflect.sinkValue(obj[prop]);\r\n return true;\r\n } catch (e) {\r\n }\r\n return false;\r\n};\r\n\r\n\r\n/**\r\n * Retrieves a value from a cache given a key. The compiler provides special\r\n * consideration for this call such that it is generally considered side-effect\r\n * free. However, if the `opt_keyFn` or `valueFn` have side-effects\r\n * then the entire call is considered to have side-effects.\r\n *\r\n * Conventionally storing the value on the cache would be considered a\r\n * side-effect and preclude unused calls from being pruned, ie. even if\r\n * the value was never used, it would still always be stored in the cache.\r\n *\r\n * Providing a side-effect free `valueFn` and `opt_keyFn`\r\n * allows unused calls to `goog.reflect.cache` to be pruned.\r\n *\r\n * @param {!Object<K, V>} cacheObj The object that contains the cached values.\r\n * @param {?} key The key to lookup in the cache. If it is not string or number\r\n * then a `opt_keyFn` should be provided. The key is also used as the\r\n * parameter to the `valueFn`.\r\n * @param {function(?):V} valueFn The value provider to use to calculate the\r\n * value to store in the cache. This function should be side-effect free\r\n * to take advantage of the optimization.\r\n * @param {function(?):K=} opt_keyFn The key provider to determine the cache\r\n * map key. This should be used if the given key is not a string or number.\r\n * If not provided then the given key is used. This function should be\r\n * side-effect free to take advantage of the optimization.\r\n * @return {V} The cached or calculated value.\r\n * @template K\r\n * @template V\r\n */\r\ngoog.reflect.cache = function(cacheObj, key, valueFn, opt_keyFn) {\r\n var storedKey = opt_keyFn ? opt_keyFn(key) : key;\r\n\r\n if (Object.prototype.hasOwnProperty.call(cacheObj, storedKey)) {\r\n return cacheObj[storedKey];\r\n }\r\n\r\n return (cacheObj[storedKey] = valueFn(key));\r\n};\r\n","// Copyright 2006 The Closure Library Authors. All Rights Reserved.\r\n//\r\n// Licensed under the Apache License, Version 2.0 (the \"License\");\r\n// you may not use this file except in compliance with the License.\r\n// You may obtain a copy of the License at\r\n//\r\n// http://www.apache.org/licenses/LICENSE-2.0\r\n//\r\n// Unless required by applicable law or agreed to in writing, software\r\n// distributed under the License is distributed on an \"AS-IS\" BASIS,\r\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n// See the License for the specific language governing permissions and\r\n// limitations under the License.\r\n\r\n/**\r\n * @fileoverview Rendering engine detection.\r\n * @see <a href=\"http://www.useragentstring.com/\">User agent strings</a>\r\n * For information on the browser brand (such as Safari versus Chrome), see\r\n * goog.userAgent.product.\r\n * @author arv@google.com (Erik Arvidsson)\r\n * @see ../demos/useragent.html\r\n */\r\n\r\ngoog.provide('goog.userAgent');\r\n\r\ngoog.require('goog.labs.userAgent.browser');\r\ngoog.require('goog.labs.userAgent.engine');\r\ngoog.require('goog.labs.userAgent.platform');\r\ngoog.require('goog.labs.userAgent.util');\r\ngoog.require('goog.reflect');\r\ngoog.require('goog.string');\r\n\r\n\r\n/**\r\n * @define {boolean} Whether we know at compile-time that the browser is IE.\r\n */\r\ngoog.userAgent.ASSUME_IE = goog.define('goog.userAgent.ASSUME_IE', false);\r\n\r\n\r\n/**\r\n * @define {boolean} Whether we know at compile-time that the browser is EDGE.\r\n */\r\ngoog.userAgent.ASSUME_EDGE = goog.define('goog.userAgent.ASSUME_EDGE', false);\r\n\r\n\r\n/**\r\n * @define {boolean} Whether we know at compile-time that the browser is GECKO.\r\n */\r\ngoog.userAgent.ASSUME_GECKO = goog.define('goog.userAgent.ASSUME_GECKO', false);\r\n\r\n\r\n/**\r\n * @define {boolean} Whether we know at compile-time that the browser is WEBKIT.\r\n */\r\ngoog.userAgent.ASSUME_WEBKIT =\r\n goog.define('goog.userAgent.ASSUME_WEBKIT', false);\r\n\r\n\r\n/**\r\n * @define {boolean} Whether we know at compile-time that the browser is a\r\n * mobile device running WebKit e.g. iPhone or Android.\r\n */\r\ngoog.userAgent.ASSUME_MOBILE_WEBKIT =\r\n goog.define('goog.userAgent.ASSUME_MOBILE_WEBKIT', false);\r\n\r\n\r\n/**\r\n * @define {boolean} Whether we know at compile-time that the browser is OPERA.\r\n */\r\ngoog.userAgent.ASSUME_OPERA = goog.define('goog.userAgent.ASSUME_OPERA', false);\r\n\r\n\r\n/**\r\n * @define {boolean} Whether the\r\n * `goog.userAgent.isVersionOrHigher`\r\n * function will return true for any version.\r\n */\r\ngoog.userAgent.ASSUME_ANY_VERSION =\r\n goog.define('goog.userAgent.ASSUME_ANY_VERSION', false);\r\n\r\n\r\n/**\r\n * Whether we know the browser engine at compile-time.\r\n * @type {boolean}\r\n * @private\r\n */\r\ngoog.userAgent.BROWSER_KNOWN_ = goog.userAgent.ASSUME_IE ||\r\n goog.userAgent.ASSUME_EDGE || goog.userAgent.ASSUME_GECKO ||\r\n goog.userAgent.ASSUME_MOBILE_WEBKIT || goog.userAgent.ASSUME_WEBKIT ||\r\n goog.userAgent.ASSUME_OPERA;\r\n\r\n\r\n/**\r\n * Returns the userAgent string for the current browser.\r\n *\r\n * @return {string} The userAgent string.\r\n */\r\ngoog.userAgent.getUserAgentString = function() {\r\n return goog.labs.userAgent.util.getUserAgent();\r\n};\r\n\r\n\r\n/**\r\n * @return {?Navigator} The native navigator object.\r\n */\r\ngoog.userAgent.getNavigatorTyped = function() {\r\n // Need a local navigator reference instead of using the global one,\r\n // to avoid the rare case where they reference different objects.\r\n // (in a WorkerPool, for example).\r\n return goog.global['navigator'] || null;\r\n};\r\n\r\n\r\n/**\r\n * TODO(nnaze): Change type to \"Navigator\" and update compilation targets.\r\n * @return {?Object} The native navigator object.\r\n */\r\ngoog.userAgent.getNavigator = function() {\r\n return goog.userAgent.getNavigatorTyped();\r\n};\r\n\r\n\r\n/**\r\n * Whether the user agent is Opera.\r\n * @type {boolean}\r\n */\r\ngoog.userAgent.OPERA = goog.userAgent.BROWSER_KNOWN_ ?\r\n goog.userAgent.ASSUME_OPERA :\r\n goog.labs.userAgent.browser.isOpera();\r\n\r\n\r\n/**\r\n * Whether the user agent is Internet Explorer.\r\n * @type {boolean}\r\n */\r\ngoog.userAgent.IE = goog.userAgent.BROWSER_KNOWN_ ?\r\n goog.userAgent.ASSUME_IE :\r\n goog.labs.userAgent.browser.isIE();\r\n\r\n\r\n/**\r\n * Whether the user agent is Microsoft Edge.\r\n * @type {boolean}\r\n */\r\ngoog.userAgent.EDGE = goog.userAgent.BROWSER_KNOWN_ ?\r\n goog.userAgent.ASSUME_EDGE :\r\n goog.labs.userAgent.engine.isEdge();\r\n\r\n\r\n/**\r\n * Whether the user agent is MS Internet Explorer or MS Edge.\r\n * @type {boolean}\r\n */\r\ngoog.userAgent.EDGE_OR_IE = goog.userAgent.EDGE || goog.userAgent.IE;\r\n\r\n\r\n/**\r\n * Whether the user agent is Gecko. Gecko is the rendering engine used by\r\n * Mozilla, Firefox, and others.\r\n * @type {boolean}\r\n */\r\ngoog.userAgent.GECKO = goog.userAgent.BROWSER_KNOWN_ ?\r\n goog.userAgent.ASSUME_GECKO :\r\n goog.labs.userAgent.engine.isGecko();\r\n\r\n\r\n/**\r\n * Whether the user agent is WebKit. WebKit is the rendering engine that\r\n * Safari, Android and others use.\r\n * @type {boolean}\r\n */\r\ngoog.userAgent.WEBKIT = goog.userAgent.BROWSER_KNOWN_ ?\r\n goog.userAgent.ASSUME_WEBKIT || goog.userAgent.ASSUME_MOBILE_WEBKIT :\r\n goog.labs.userAgent.engine.isWebKit();\r\n\r\n\r\n/**\r\n * Whether the user agent is running on a mobile device.\r\n *\r\n * This is a separate function so that the logic can be tested.\r\n *\r\n * TODO(nnaze): Investigate swapping in goog.labs.userAgent.device.isMobile().\r\n *\r\n * @return {boolean} Whether the user agent is running on a mobile device.\r\n * @private\r\n */\r\ngoog.userAgent.isMobile_ = function() {\r\n return goog.userAgent.WEBKIT &&\r\n goog.labs.userAgent.util.matchUserAgent('Mobile');\r\n};\r\n\r\n\r\n/**\r\n * Whether the user agent is running on a mobile device.\r\n *\r\n * TODO(nnaze): Consider deprecating MOBILE when labs.userAgent\r\n * is promoted as the gecko/webkit logic is likely inaccurate.\r\n *\r\n * @type {boolean}\r\n */\r\ngoog.userAgent.MOBILE =\r\n goog.userAgent.ASSUME_MOBILE_WEBKIT || goog.userAgent.isMobile_();\r\n\r\n\r\n/**\r\n * Used while transitioning code to use WEBKIT instead.\r\n * @type {boolean}\r\n * @deprecated Use {@link goog.userAgent.product.SAFARI} instead.\r\n * TODO(nicksantos): Delete this from goog.userAgent.\r\n */\r\ngoog.userAgent.SAFARI = goog.userAgent.WEBKIT;\r\n\r\n\r\n/**\r\n * @return {string} the platform (operating system) the user agent is running\r\n * on. Default to empty string because navigator.platform may not be defined\r\n * (on Rhino, for example).\r\n * @private\r\n */\r\ngoog.userAgent.determinePlatform_ = function() {\r\n var navigator = goog.userAgent.getNavigatorTyped();\r\n return navigator && navigator.platform || '';\r\n};\r\n\r\n\r\n/**\r\n * The platform (operating system) the user agent is running on. Default to\r\n * empty string because navigator.platform may not be defined (on Rhino, for\r\n * example).\r\n * @type {string}\r\n */\r\ngoog.userAgent.PLATFORM = goog.userAgent.determinePlatform_();\r\n\r\n\r\n/**\r\n * @define {boolean} Whether the user agent is running on a Macintosh operating\r\n * system.\r\n */\r\ngoog.userAgent.ASSUME_MAC = goog.define('goog.userAgent.ASSUME_MAC', false);\r\n\r\n\r\n/**\r\n * @define {boolean} Whether the user agent is running on a Windows operating\r\n * system.\r\n */\r\ngoog.userAgent.ASSUME_WINDOWS =\r\n goog.define('goog.userAgent.ASSUME_WINDOWS', false);\r\n\r\n\r\n/**\r\n * @define {boolean} Whether the user agent is running on a Linux operating\r\n * system.\r\n */\r\ngoog.userAgent.ASSUME_LINUX = goog.define('goog.userAgent.ASSUME_LINUX', false);\r\n\r\n\r\n/**\r\n * @define {boolean} Whether the user agent is running on a X11 windowing\r\n * system.\r\n */\r\ngoog.userAgent.ASSUME_X11 = goog.define('goog.userAgent.ASSUME_X11', false);\r\n\r\n\r\n/**\r\n * @define {boolean} Whether the user agent is running on Android.\r\n */\r\ngoog.userAgent.ASSUME_ANDROID =\r\n goog.define('goog.userAgent.ASSUME_ANDROID', false);\r\n\r\n\r\n/**\r\n * @define {boolean} Whether the user agent is running on an iPhone.\r\n */\r\ngoog.userAgent.ASSUME_IPHONE =\r\n goog.define('goog.userAgent.ASSUME_IPHONE', false);\r\n\r\n\r\n/**\r\n * @define {boolean} Whether the user agent is running on an iPad.\r\n */\r\ngoog.userAgent.ASSUME_IPAD = goog.define('goog.userAgent.ASSUME_IPAD', false);\r\n\r\n\r\n/**\r\n * @define {boolean} Whether the user agent is running on an iPod.\r\n */\r\ngoog.userAgent.ASSUME_IPOD = goog.define('goog.userAgent.ASSUME_IPOD', false);\r\n\r\n\r\n/**\r\n * @define {boolean} Whether the user agent is running on KaiOS.\r\n */\r\ngoog.userAgent.ASSUME_KAIOS = goog.define('goog.userAgent.ASSUME_KAIOS', false);\r\n\r\n/**\r\n * @define {boolean} Whether the user agent is running on Go2Phone.\r\n */\r\ngoog.userAgent.ASSUME_GO2PHONE =\r\n goog.define('goog.userAgent.ASSUME_GO2PHONE', false);\r\n\r\n\r\n/**\r\n * @type {boolean}\r\n * @private\r\n */\r\ngoog.userAgent.PLATFORM_KNOWN_ = goog.userAgent.ASSUME_MAC ||\r\n goog.userAgent.ASSUME_WINDOWS || goog.userAgent.ASSUME_LINUX ||\r\n goog.userAgent.ASSUME_X11 || goog.userAgent.ASSUME_ANDROID ||\r\n goog.userAgent.ASSUME_IPHONE || goog.userAgent.ASSUME_IPAD ||\r\n goog.userAgent.ASSUME_IPOD;\r\n\r\n\r\n/**\r\n * Whether the user agent is running on a Macintosh operating system.\r\n * @type {boolean}\r\n */\r\ngoog.userAgent.MAC = goog.userAgent.PLATFORM_KNOWN_ ?\r\n goog.userAgent.ASSUME_MAC :\r\n goog.labs.userAgent.platform.isMacintosh();\r\n\r\n\r\n/**\r\n * Whether the user agent is running on a Windows operating system.\r\n * @type {boolean}\r\n */\r\ngoog.userAgent.WINDOWS = goog.userAgent.PLATFORM_KNOWN_ ?\r\n goog.userAgent.ASSUME_WINDOWS :\r\n goog.labs.userAgent.platform.isWindows();\r\n\r\n\r\n/**\r\n * Whether the user agent is Linux per the legacy behavior of\r\n * goog.userAgent.LINUX, which considered ChromeOS to also be\r\n * Linux.\r\n * @return {boolean}\r\n * @private\r\n */\r\ngoog.userAgent.isLegacyLinux_ = function() {\r\n return goog.labs.userAgent.platform.isLinux() ||\r\n goog.labs.userAgent.platform.isChromeOS();\r\n};\r\n\r\n\r\n/**\r\n * Whether the user agent is running on a Linux operating system.\r\n *\r\n * Note that goog.userAgent.LINUX considers ChromeOS to be Linux,\r\n * while goog.labs.userAgent.platform considers ChromeOS and\r\n * Linux to be different OSes.\r\n *\r\n * @type {boolean}\r\n */\r\ngoog.userAgent.LINUX = goog.userAgent.PLATFORM_KNOWN_ ?\r\n goog.userAgent.ASSUME_LINUX :\r\n goog.userAgent.isLegacyLinux_();\r\n\r\n\r\n/**\r\n * @return {boolean} Whether the user agent is an X11 windowing system.\r\n * @private\r\n */\r\ngoog.userAgent.isX11_ = function() {\r\n var navigator = goog.userAgent.getNavigatorTyped();\r\n return !!navigator &&\r\n goog.string.contains(navigator['appVersion'] || '', 'X11');\r\n};\r\n\r\n\r\n/**\r\n * Whether the user agent is running on a X11 windowing system.\r\n * @type {boolean}\r\n */\r\ngoog.userAgent.X11 = goog.userAgent.PLATFORM_KNOWN_ ?\r\n goog.userAgent.ASSUME_X11 :\r\n goog.userAgent.isX11_();\r\n\r\n\r\n/**\r\n * Whether the user agent is running on Android.\r\n * @type {boolean}\r\n */\r\ngoog.userAgent.ANDROID = goog.userAgent.PLATFORM_KNOWN_ ?\r\n goog.userAgent.ASSUME_ANDROID :\r\n goog.labs.userAgent.platform.isAndroid();\r\n\r\n\r\n/**\r\n * Whether the user agent is running on an iPhone.\r\n * @type {boolean}\r\n */\r\ngoog.userAgent.IPHONE = goog.userAgent.PLATFORM_KNOWN_ ?\r\n goog.userAgent.ASSUME_IPHONE :\r\n goog.labs.userAgent.platform.isIphone();\r\n\r\n\r\n/**\r\n * Whether the user agent is running on an iPad.\r\n * @type {boolean}\r\n */\r\ngoog.userAgent.IPAD = goog.userAgent.PLATFORM_KNOWN_ ?\r\n goog.userAgent.ASSUME_IPAD :\r\n goog.labs.userAgent.platform.isIpad();\r\n\r\n\r\n/**\r\n * Whether the user agent is running on an iPod.\r\n * @type {boolean}\r\n */\r\ngoog.userAgent.IPOD = goog.userAgent.PLATFORM_KNOWN_ ?\r\n goog.userAgent.ASSUME_IPOD :\r\n goog.labs.userAgent.platform.isIpod();\r\n\r\n\r\n/**\r\n * Whether the user agent is running on iOS.\r\n * @type {boolean}\r\n */\r\ngoog.userAgent.IOS = goog.userAgent.PLATFORM_KNOWN_ ?\r\n (goog.userAgent.ASSUME_IPHONE || goog.userAgent.ASSUME_IPAD ||\r\n goog.userAgent.ASSUME_IPOD) :\r\n goog.labs.userAgent.platform.isIos();\r\n\r\n/**\r\n * Whether the user agent is running on KaiOS.\r\n */\r\ngoog.userAgent.KAIOS = goog.userAgent.PLATFORM_KNOWN_ ?\r\n goog.userAgent.ASSUME_KAIOS :\r\n goog.labs.userAgent.platform.isKaiOS();\r\n\r\n/**\r\n * Whether the user agent is running on Go2Phone.\r\n */\r\ngoog.userAgent.GO2PHONE = goog.userAgent.PLATFORM_KNOWN_ ?\r\n goog.userAgent.ASSUME_GO2PHONE :\r\n goog.labs.userAgent.platform.isGo2Phone();\r\n\r\n\r\n/**\r\n * @return {string} The string that describes the version number of the user\r\n * agent.\r\n * @private\r\n */\r\ngoog.userAgent.determineVersion_ = function() {\r\n // All browsers have different ways to detect the version and they all have\r\n // different naming schemes.\r\n // version is a string rather than a number because it may contain 'b', 'a',\r\n // and so on.\r\n var version = '';\r\n var arr = goog.userAgent.getVersionRegexResult_();\r\n if (arr) {\r\n version = arr ? arr[1] : '';\r\n }\r\n\r\n if (goog.userAgent.IE) {\r\n // IE9 can be in document mode 9 but be reporting an inconsistent user agent\r\n // version. If it is identifying as a version lower than 9 we take the\r\n // documentMode as the version instead. IE8 has similar behavior.\r\n // It is recommended to set the X-UA-Compatible header to ensure that IE9\r\n // uses documentMode 9.\r\n var docMode = goog.userAgent.getDocumentMode_();\r\n if (docMode != null && docMode > parseFloat(version)) {\r\n return String(docMode);\r\n }\r\n }\r\n\r\n return version;\r\n};\r\n\r\n\r\n/**\r\n * @return {?IArrayLike<string>|undefined} The version regex matches from\r\n * parsing the user\r\n * agent string. These regex statements must be executed inline so they can\r\n * be compiled out by the closure compiler with the rest of the useragent\r\n * detection logic when ASSUME_* is specified.\r\n * @private\r\n */\r\ngoog.userAgent.getVersionRegexResult_ = function() {\r\n var userAgent = goog.userAgent.getUserAgentString();\r\n if (goog.userAgent.GECKO) {\r\n return /rv\\:([^\\);]+)(\\)|;)/.exec(userAgent);\r\n }\r\n if (goog.userAgent.EDGE) {\r\n return /Edge\\/([\\d\\.]+)/.exec(userAgent);\r\n }\r\n if (goog.userAgent.IE) {\r\n return /\\b(?:MSIE|rv)[: ]([^\\);]+)(\\)|;)/.exec(userAgent);\r\n }\r\n if (goog.userAgent.WEBKIT) {\r\n // WebKit/125.4\r\n return /WebKit\\/(\\S+)/.exec(userAgent);\r\n }\r\n if (goog.userAgent.OPERA) {\r\n // If none of the above browsers were detected but the browser is Opera, the\r\n // only string that is of interest is 'Version/<number>'.\r\n return /(?:Version)[ \\/]?(\\S+)/.exec(userAgent);\r\n }\r\n return undefined;\r\n};\r\n\r\n\r\n/**\r\n * @return {number|undefined} Returns the document mode (for testing).\r\n * @private\r\n */\r\ngoog.userAgent.getDocumentMode_ = function() {\r\n // NOTE(user): goog.userAgent may be used in context where there is no DOM.\r\n var doc = goog.global['document'];\r\n return doc ? doc['documentMode'] : undefined;\r\n};\r\n\r\n\r\n/**\r\n * The version of the user agent. This is a string because it might contain\r\n * 'b' (as in beta) as well as multiple dots.\r\n * @type {string}\r\n */\r\ngoog.userAgent.VERSION = goog.userAgent.determineVersion_();\r\n\r\n\r\n/**\r\n * Compares two version numbers.\r\n *\r\n * @param {string} v1 Version of first item.\r\n * @param {string} v2 Version of second item.\r\n *\r\n * @return {number} 1 if first argument is higher\r\n * 0 if arguments are equal\r\n * -1 if second argument is higher.\r\n * @deprecated Use goog.string.compareVersions.\r\n */\r\ngoog.userAgent.compare = function(v1, v2) {\r\n return goog.string.compareVersions(v1, v2);\r\n};\r\n\r\n\r\n/**\r\n * Cache for {@link goog.userAgent.isVersionOrHigher}.\r\n * Calls to compareVersions are surprisingly expensive and, as a browser's\r\n * version number is unlikely to change during a session, we cache the results.\r\n * @const\r\n * @private\r\n */\r\ngoog.userAgent.isVersionOrHigherCache_ = {};\r\n\r\n\r\n/**\r\n * Whether the user agent version is higher or the same as the given version.\r\n * NOTE: When checking the version numbers for Firefox and Safari, be sure to\r\n * use the engine's version, not the browser's version number. For example,\r\n * Firefox 3.0 corresponds to Gecko 1.9 and Safari 3.0 to Webkit 522.11.\r\n * Opera and Internet Explorer versions match the product release number.<br>\r\n * @see <a href=\"http://en.wikipedia.org/wiki/Safari_version_history\">\r\n * Webkit</a>\r\n * @see <a href=\"http://en.wikipedia.org/wiki/Gecko_engine\">Gecko</a>\r\n *\r\n * @param {string|number} version The version to check.\r\n * @return {boolean} Whether the user agent version is higher or the same as\r\n * the given version.\r\n */\r\ngoog.userAgent.isVersionOrHigher = function(version) {\r\n return goog.userAgent.ASSUME_ANY_VERSION ||\r\n goog.reflect.cache(\r\n goog.userAgent.isVersionOrHigherCache_, version, function() {\r\n return goog.string.compareVersions(\r\n goog.userAgent.VERSION, version) >= 0;\r\n });\r\n};\r\n\r\n\r\n/**\r\n * Deprecated alias to `goog.userAgent.isVersionOrHigher`.\r\n * @param {string|number} version The version to check.\r\n * @return {boolean} Whether the user agent version is higher or the same as\r\n * the given version.\r\n * @deprecated Use goog.userAgent.isVersionOrHigher().\r\n */\r\ngoog.userAgent.isVersion = goog.userAgent.isVersionOrHigher;\r\n\r\n\r\n/**\r\n * Whether the IE effective document mode is higher or the same as the given\r\n * document mode version.\r\n * NOTE: Only for IE, return false for another browser.\r\n *\r\n * @param {number} documentMode The document mode version to check.\r\n * @return {boolean} Whether the IE effective document mode is higher or the\r\n * same as the given version.\r\n */\r\ngoog.userAgent.isDocumentModeOrHigher = function(documentMode) {\r\n return Number(goog.userAgent.DOCUMENT_MODE) >= documentMode;\r\n};\r\n\r\n\r\n/**\r\n * Deprecated alias to `goog.userAgent.isDocumentModeOrHigher`.\r\n * @param {number} version The version to check.\r\n * @return {boolean} Whether the IE effective document mode is higher or the\r\n * same as the given version.\r\n * @deprecated Use goog.userAgent.isDocumentModeOrHigher().\r\n */\r\ngoog.userAgent.isDocumentMode = goog.userAgent.isDocumentModeOrHigher;\r\n\r\n\r\n/**\r\n * For IE version < 7, documentMode is undefined, so attempt to use the\r\n * CSS1Compat property to see if we are in standards mode. If we are in\r\n * standards mode, treat the browser version as the document mode. Otherwise,\r\n * IE is emulating version 5.\r\n * @type {number|undefined}\r\n * @const\r\n */\r\ngoog.userAgent.DOCUMENT_MODE = (function() {\r\n var doc = goog.global['document'];\r\n var mode = goog.userAgent.getDocumentMode_();\r\n if (!doc || !goog.userAgent.IE) {\r\n return undefined;\r\n }\r\n return mode || (doc['compatMode'] == 'CSS1Compat' ?\r\n parseInt(goog.userAgent.VERSION, 10) :\r\n 5);\r\n})();\r\n","// Copyright 2013 The Closure Library Authors. All Rights Reserved.\r\n//\r\n// Licensed under the Apache License, Version 2.0 (the \"License\");\r\n// you may not use this file except in compliance with the License.\r\n// You may obtain a copy of the License at\r\n//\r\n// http://www.apache.org/licenses/LICENSE-2.0\r\n//\r\n// Unless required by applicable law or agreed to in writing, software\r\n// distributed under the License is distributed on an \"AS-IS\" BASIS,\r\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n// See the License for the specific language governing permissions and\r\n// limitations under the License.\r\n\r\n/**\r\n * @fileoverview Closure user agent detection (Browser).\r\n * @see <a href=\"http://www.useragentstring.com/\">User agent strings</a>\r\n * For more information on rendering engine, platform, or device see the other\r\n * sub-namespaces in goog.labs.userAgent, goog.labs.userAgent.platform,\r\n * goog.labs.userAgent.device respectively.)\r\n *\r\n * @author martone@google.com (Andy Martone)\r\n */\r\n\r\ngoog.provide('goog.labs.userAgent.browser');\r\n\r\ngoog.require('goog.array');\r\ngoog.require('goog.labs.userAgent.util');\r\ngoog.require('goog.object');\r\ngoog.require('goog.string.internal');\r\n\r\n\r\n// TODO(nnaze): Refactor to remove excessive exclusion logic in matching\r\n// functions.\r\n\r\n\r\n/**\r\n * @return {boolean} Whether the user's browser is Opera. Note: Chromium\r\n * based Opera (Opera 15+) is detected as Chrome to avoid unnecessary\r\n * special casing.\r\n * @private\r\n */\r\ngoog.labs.userAgent.browser.matchOpera_ = function() {\r\n return goog.labs.userAgent.util.matchUserAgent('Opera');\r\n};\r\n\r\n\r\n/**\r\n * @return {boolean} Whether the user's browser is IE.\r\n * @private\r\n */\r\ngoog.labs.userAgent.browser.matchIE_ = function() {\r\n return goog.labs.userAgent.util.matchUserAgent('Trident') ||\r\n goog.labs.userAgent.util.matchUserAgent('MSIE');\r\n};\r\n\r\n\r\n/**\r\n * @return {boolean} Whether the user's browser is Edge.\r\n * @private\r\n */\r\ngoog.labs.userAgent.browser.matchEdge_ = function() {\r\n return goog.labs.userAgent.util.matchUserAgent('Edge');\r\n};\r\n\r\n\r\n/**\r\n * @return {boolean} Whether the user's browser is Firefox.\r\n * @private\r\n */\r\ngoog.labs.userAgent.browser.matchFirefox_ = function() {\r\n return goog.labs.userAgent.util.matchUserAgent('Firefox') ||\r\n goog.labs.userAgent.util.matchUserAgent('FxiOS');\r\n};\r\n\r\n\r\n/**\r\n * @return {boolean} Whether the user's browser is Safari.\r\n * @private\r\n */\r\ngoog.labs.userAgent.browser.matchSafari_ = function() {\r\n return goog.labs.userAgent.util.matchUserAgent('Safari') &&\r\n !(goog.labs.userAgent.browser.matchChrome_() ||\r\n goog.labs.userAgent.browser.matchCoast_() ||\r\n goog.labs.userAgent.browser.matchOpera_() ||\r\n goog.labs.userAgent.browser.matchEdge_() ||\r\n goog.labs.userAgent.browser.matchFirefox_() ||\r\n goog.labs.userAgent.browser.isSilk() ||\r\n goog.labs.userAgent.util.matchUserAgent('Android'));\r\n};\r\n\r\n\r\n/**\r\n * @return {boolean} Whether the user's browser is Coast (Opera's Webkit-based\r\n * iOS browser).\r\n * @private\r\n */\r\ngoog.labs.userAgent.browser.matchCoast_ = function() {\r\n return goog.labs.userAgent.util.matchUserAgent('Coast');\r\n};\r\n\r\n\r\n/**\r\n * @return {boolean} Whether the user's browser is iOS Webview.\r\n * @private\r\n */\r\ngoog.labs.userAgent.browser.matchIosWebview_ = function() {\r\n // iOS Webview does not show up as Chrome or Safari. Also check for Opera's\r\n // WebKit-based iOS browser, Coast.\r\n return (goog.labs.userAgent.util.matchUserAgent('iPad') ||\r\n goog.labs.userAgent.util.matchUserAgent('iPhone')) &&\r\n !goog.labs.userAgent.browser.matchSafari_() &&\r\n !goog.labs.userAgent.browser.matchChrome_() &&\r\n !goog.labs.userAgent.browser.matchCoast_() &&\r\n !goog.labs.userAgent.browser.matchFirefox_() &&\r\n goog.labs.userAgent.util.matchUserAgent('AppleWebKit');\r\n};\r\n\r\n\r\n/**\r\n * @return {boolean} Whether the user's browser is Chrome.\r\n * @private\r\n */\r\ngoog.labs.userAgent.browser.matchChrome_ = function() {\r\n return (goog.labs.userAgent.util.matchUserAgent('Chrome') ||\r\n goog.labs.userAgent.util.matchUserAgent('CriOS')) &&\r\n !goog.labs.userAgent.browser.matchEdge_();\r\n};\r\n\r\n\r\n/**\r\n * @return {boolean} Whether the user's browser is the Android browser.\r\n * @private\r\n */\r\ngoog.labs.userAgent.browser.matchAndroidBrowser_ = function() {\r\n // Android can appear in the user agent string for Chrome on Android.\r\n // This is not the Android standalone browser if it does.\r\n return goog.labs.userAgent.util.matchUserAgent('Android') &&\r\n !(goog.labs.userAgent.browser.isChrome() ||\r\n goog.labs.userAgent.browser.isFirefox() ||\r\n goog.labs.userAgent.browser.isOpera() ||\r\n goog.labs.userAgent.browser.isSilk());\r\n};\r\n\r\n\r\n/**\r\n * @return {boolean} Whether the user's browser is Opera.\r\n */\r\ngoog.labs.userAgent.browser.isOpera = goog.labs.userAgent.browser.matchOpera_;\r\n\r\n\r\n/**\r\n * @return {boolean} Whether the user's browser is IE.\r\n */\r\ngoog.labs.userAgent.browser.isIE = goog.labs.userAgent.browser.matchIE_;\r\n\r\n\r\n/**\r\n * @return {boolean} Whether the user's browser is Edge.\r\n */\r\ngoog.labs.userAgent.browser.isEdge = goog.labs.userAgent.browser.matchEdge_;\r\n\r\n\r\n/**\r\n * @return {boolean} Whether the user's browser is Firefox.\r\n */\r\ngoog.labs.userAgent.browser.isFirefox =\r\n goog.labs.userAgent.browser.matchFirefox_;\r\n\r\n\r\n/**\r\n * @return {boolean} Whether the user's browser is Safari.\r\n */\r\ngoog.labs.userAgent.browser.isSafari = goog.labs.userAgent.browser.matchSafari_;\r\n\r\n\r\n/**\r\n * @return {boolean} Whether the user's browser is Coast (Opera's Webkit-based\r\n * iOS browser).\r\n */\r\ngoog.labs.userAgent.browser.isCoast = goog.labs.userAgent.browser.matchCoast_;\r\n\r\n\r\n/**\r\n * @return {boolean} Whether the user's browser is iOS Webview.\r\n */\r\ngoog.labs.userAgent.browser.isIosWebview =\r\n goog.labs.userAgent.browser.matchIosWebview_;\r\n\r\n\r\n/**\r\n * @return {boolean} Whether the user's browser is Chrome.\r\n */\r\ngoog.labs.userAgent.browser.isChrome = goog.labs.userAgent.browser.matchChrome_;\r\n\r\n\r\n/**\r\n * @return {boolean} Whether the user's browser is the Android browser.\r\n */\r\ngoog.labs.userAgent.browser.isAndroidBrowser =\r\n goog.labs.userAgent.browser.matchAndroidBrowser_;\r\n\r\n\r\n/**\r\n * For more information, see:\r\n * http://docs.aws.amazon.com/silk/latest/developerguide/user-agent.html\r\n * @return {boolean} Whether the user's browser is Silk.\r\n */\r\ngoog.labs.userAgent.browser.isSilk = function() {\r\n return goog.labs.userAgent.util.matchUserAgent('Silk');\r\n};\r\n\r\n\r\n/**\r\n * @return {string} The browser version or empty string if version cannot be\r\n * determined. Note that for Internet Explorer, this returns the version of\r\n * the browser, not the version of the rendering engine. (IE 8 in\r\n * compatibility mode will return 8.0 rather than 7.0. To determine the\r\n * rendering engine version, look at document.documentMode instead. See\r\n * http://msdn.microsoft.com/en-us/library/cc196988(v=vs.85).aspx for more\r\n * details.)\r\n */\r\ngoog.labs.userAgent.browser.getVersion = function() {\r\n var userAgentString = goog.labs.userAgent.util.getUserAgent();\r\n // Special case IE since IE's version is inside the parenthesis and\r\n // without the '/'.\r\n if (goog.labs.userAgent.browser.isIE()) {\r\n return goog.labs.userAgent.browser.getIEVersion_(userAgentString);\r\n }\r\n\r\n var versionTuples =\r\n goog.labs.userAgent.util.extractVersionTuples(userAgentString);\r\n\r\n // Construct a map for easy lookup.\r\n var versionMap = {};\r\n goog.array.forEach(versionTuples, function(tuple) {\r\n // Note that the tuple is of length three, but we only care about the\r\n // first two.\r\n var key = tuple[0];\r\n var value = tuple[1];\r\n versionMap[key] = value;\r\n });\r\n\r\n var versionMapHasKey = goog.partial(goog.object.containsKey, versionMap);\r\n\r\n // Gives the value with the first key it finds, otherwise empty string.\r\n function lookUpValueWithKeys(keys) {\r\n var key = goog.array.find(keys, versionMapHasKey);\r\n return versionMap[key] || '';\r\n }\r\n\r\n // Check Opera before Chrome since Opera 15+ has \"Chrome\" in the string.\r\n // See\r\n // http://my.opera.com/ODIN/blog/2013/07/15/opera-user-agent-strings-opera-15-and-beyond\r\n if (goog.labs.userAgent.browser.isOpera()) {\r\n // Opera 10 has Version/10.0 but Opera/9.8, so look for \"Version\" first.\r\n // Opera uses 'OPR' for more recent UAs.\r\n return lookUpValueWithKeys(['Version', 'Opera']);\r\n }\r\n\r\n // Check Edge before Chrome since it has Chrome in the string.\r\n if (goog.labs.userAgent.browser.isEdge()) {\r\n return lookUpValueWithKeys(['Edge']);\r\n }\r\n\r\n if (goog.labs.userAgent.browser.isChrome()) {\r\n return lookUpValueWithKeys(['Chrome', 'CriOS']);\r\n }\r\n\r\n // Usually products browser versions are in the third tuple after \"Mozilla\"\r\n // and the engine.\r\n var tuple = versionTuples[2];\r\n return tuple && tuple[1] || '';\r\n};\r\n\r\n\r\n/**\r\n * @param {string|number} version The version to check.\r\n * @return {boolean} Whether the browser version is higher or the same as the\r\n * given version.\r\n */\r\ngoog.labs.userAgent.browser.isVersionOrHigher = function(version) {\r\n return goog.string.internal.compareVersions(\r\n goog.labs.userAgent.browser.getVersion(), version) >= 0;\r\n};\r\n\r\n\r\n/**\r\n * Determines IE version. More information:\r\n * http://msdn.microsoft.com/en-us/library/ie/bg182625(v=vs.85).aspx#uaString\r\n * http://msdn.microsoft.com/en-us/library/hh869301(v=vs.85).aspx\r\n * http://blogs.msdn.com/b/ie/archive/2010/03/23/introducing-ie9-s-user-agent-string.aspx\r\n * http://blogs.msdn.com/b/ie/archive/2009/01/09/the-internet-explorer-8-user-agent-string-updated-edition.aspx\r\n *\r\n * @param {string} userAgent the User-Agent.\r\n * @return {string}\r\n * @private\r\n */\r\ngoog.labs.userAgent.browser.getIEVersion_ = function(userAgent) {\r\n // IE11 may identify itself as MSIE 9.0 or MSIE 10.0 due to an IE 11 upgrade\r\n // bug. Example UA:\r\n // Mozilla/5.0 (MSIE 9.0; Windows NT 6.1; WOW64; Trident/7.0; rv:11.0)\r\n // like Gecko.\r\n // See http://www.whatismybrowser.com/developers/unknown-user-agent-fragments.\r\n var rv = /rv: *([\\d\\.]*)/.exec(userAgent);\r\n if (rv && rv[1]) {\r\n return rv[1];\r\n }\r\n\r\n var version = '';\r\n var msie = /MSIE +([\\d\\.]+)/.exec(userAgent);\r\n if (msie && msie[1]) {\r\n // IE in compatibility mode usually identifies itself as MSIE 7.0; in this\r\n // case, use the Trident version to determine the version of IE. For more\r\n // details, see the links above.\r\n var tridentVersion = /Trident\\/(\\d.\\d)/.exec(userAgent);\r\n if (msie[1] == '7.0') {\r\n if (tridentVersion && tridentVersion[1]) {\r\n switch (tridentVersion[1]) {\r\n case '4.0':\r\n version = '8.0';\r\n break;\r\n case '5.0':\r\n version = '9.0';\r\n break;\r\n case '6.0':\r\n version = '10.0';\r\n break;\r\n case '7.0':\r\n version = '11.0';\r\n break;\r\n }\r\n } else {\r\n version = '7.0';\r\n }\r\n } else {\r\n version = msie[1];\r\n }\r\n }\r\n return version;\r\n};\r\n","// Copyright 2013 The Closure Library Authors. All Rights Reserved.\r\n//\r\n// Licensed under the Apache License, Version 2.0 (the \"License\");\r\n// you may not use this file except in compliance with the License.\r\n// You may obtain a copy of the License at\r\n//\r\n// http://www.apache.org/licenses/LICENSE-2.0\r\n//\r\n// Unless required by applicable law or agreed to in writing, software\r\n// distributed under the License is distributed on an \"AS-IS\" BASIS,\r\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n// See the License for the specific language governing permissions and\r\n// limitations under the License.\r\n\r\n/**\r\n * @fileoverview Closure user agent detection.\r\n * @see http://en.wikipedia.org/wiki/User_agent\r\n * For more information on browser brand, platform, or device see the other\r\n * sub-namespaces in goog.labs.userAgent (browser, platform, and device).\r\n *\r\n */\r\n\r\ngoog.provide('goog.labs.userAgent.engine');\r\n\r\ngoog.require('goog.array');\r\ngoog.require('goog.labs.userAgent.util');\r\ngoog.require('goog.string');\r\n\r\n\r\n/**\r\n * @return {boolean} Whether the rendering engine is Presto.\r\n */\r\ngoog.labs.userAgent.engine.isPresto = function() {\r\n return goog.labs.userAgent.util.matchUserAgent('Presto');\r\n};\r\n\r\n\r\n/**\r\n * @return {boolean} Whether the rendering engine is Trident.\r\n */\r\ngoog.labs.userAgent.engine.isTrident = function() {\r\n // IE only started including the Trident token in IE8.\r\n return goog.labs.userAgent.util.matchUserAgent('Trident') ||\r\n goog.labs.userAgent.util.matchUserAgent('MSIE');\r\n};\r\n\r\n\r\n/**\r\n * @return {boolean} Whether the rendering engine is Edge.\r\n */\r\ngoog.labs.userAgent.engine.isEdge = function() {\r\n return goog.labs.userAgent.util.matchUserAgent('Edge');\r\n};\r\n\r\n\r\n/**\r\n * @return {boolean} Whether the rendering engine is WebKit.\r\n */\r\ngoog.labs.userAgent.engine.isWebKit = function() {\r\n return goog.labs.userAgent.util.matchUserAgentIgnoreCase('WebKit') &&\r\n !goog.labs.userAgent.engine.isEdge();\r\n};\r\n\r\n\r\n/**\r\n * @return {boolean} Whether the rendering engine is Gecko.\r\n */\r\ngoog.labs.userAgent.engine.isGecko = function() {\r\n return goog.labs.userAgent.util.matchUserAgent('Gecko') &&\r\n !goog.labs.userAgent.engine.isWebKit() &&\r\n !goog.labs.userAgent.engine.isTrident() &&\r\n !goog.labs.userAgent.engine.isEdge();\r\n};\r\n\r\n\r\n/**\r\n * @return {string} The rendering engine's version or empty string if version\r\n * can't be determined.\r\n */\r\ngoog.labs.userAgent.engine.getVersion = function() {\r\n var userAgentString = goog.labs.userAgent.util.getUserAgent();\r\n if (userAgentString) {\r\n var tuples = goog.labs.userAgent.util.extractVersionTuples(userAgentString);\r\n\r\n var engineTuple = goog.labs.userAgent.engine.getEngineTuple_(tuples);\r\n if (engineTuple) {\r\n // In Gecko, the version string is either in the browser info or the\r\n // Firefox version. See Gecko user agent string reference:\r\n // http://goo.gl/mULqa\r\n if (engineTuple[0] == 'Gecko') {\r\n return goog.labs.userAgent.engine.getVersionForKey_(tuples, 'Firefox');\r\n }\r\n\r\n return engineTuple[1];\r\n }\r\n\r\n // MSIE has only one version identifier, and the Trident version is\r\n // specified in the parenthetical. IE Edge is covered in the engine tuple\r\n // detection.\r\n var browserTuple = tuples[0];\r\n var info;\r\n if (browserTuple && (info = browserTuple[2])) {\r\n var match = /Trident\\/([^\\s;]+)/.exec(info);\r\n if (match) {\r\n return match[1];\r\n }\r\n }\r\n }\r\n return '';\r\n};\r\n\r\n\r\n/**\r\n * @param {!Array<!Array<string>>} tuples Extracted version tuples.\r\n * @return {!Array<string>|undefined} The engine tuple or undefined if not\r\n * found.\r\n * @private\r\n */\r\ngoog.labs.userAgent.engine.getEngineTuple_ = function(tuples) {\r\n if (!goog.labs.userAgent.engine.isEdge()) {\r\n return tuples[1];\r\n }\r\n for (var i = 0; i < tuples.length; i++) {\r\n var tuple = tuples[i];\r\n if (tuple[0] == 'Edge') {\r\n return tuple;\r\n }\r\n }\r\n};\r\n\r\n\r\n/**\r\n * @param {string|number} version The version to check.\r\n * @return {boolean} Whether the rendering engine version is higher or the same\r\n * as the given version.\r\n */\r\ngoog.labs.userAgent.engine.isVersionOrHigher = function(version) {\r\n return goog.string.compareVersions(\r\n goog.labs.userAgent.engine.getVersion(), version) >= 0;\r\n};\r\n\r\n\r\n/**\r\n * @param {!Array<!Array<string>>} tuples Version tuples.\r\n * @param {string} key The key to look for.\r\n * @return {string} The version string of the given key, if present.\r\n * Otherwise, the empty string.\r\n * @private\r\n */\r\ngoog.labs.userAgent.engine.getVersionForKey_ = function(tuples, key) {\r\n // TODO(nnaze): Move to util if useful elsewhere.\r\n\r\n var pair = goog.array.find(tuples, function(pair) { return key == pair[0]; });\r\n\r\n return pair && pair[1] || '';\r\n};\r\n","// Copyright 2010 The Closure Library Authors. All Rights Reserved.\r\n//\r\n// Licensed under the Apache License, Version 2.0 (the \"License\");\r\n// you may not use this file except in compliance with the License.\r\n// You may obtain a copy of the License at\r\n//\r\n// http://www.apache.org/licenses/LICENSE-2.0\r\n//\r\n// Unless required by applicable law or agreed to in writing, software\r\n// distributed under the License is distributed on an \"AS-IS\" BASIS,\r\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n// See the License for the specific language governing permissions and\r\n// limitations under the License.\r\n\r\n/**\r\n * @fileoverview Browser capability checks for the events package.\r\n *\r\n */\r\n\r\n\r\ngoog.provide('goog.events.BrowserFeature');\r\n\r\ngoog.require('goog.userAgent');\r\ngoog.scope(function() {\r\n\r\n\r\n\r\n/**\r\n * Enum of browser capabilities.\r\n * @enum {boolean}\r\n */\r\ngoog.events.BrowserFeature = {\r\n /**\r\n * Whether the button attribute of the event is W3C compliant. False in\r\n * Internet Explorer prior to version 9; document-version dependent.\r\n */\r\n HAS_W3C_BUTTON:\r\n !goog.userAgent.IE || goog.userAgent.isDocumentModeOrHigher(9),\r\n\r\n /**\r\n * Whether the browser supports full W3C event model.\r\n */\r\n HAS_W3C_EVENT_SUPPORT:\r\n !goog.userAgent.IE || goog.userAgent.isDocumentModeOrHigher(9),\r\n\r\n /**\r\n * To prevent default in IE7-8 for certain keydown events we need set the\r\n * keyCode to -1.\r\n */\r\n SET_KEY_CODE_TO_PREVENT_DEFAULT:\r\n goog.userAgent.IE && !goog.userAgent.isVersionOrHigher('9'),\r\n\r\n /**\r\n * Whether the `navigator.onLine` property is supported.\r\n */\r\n HAS_NAVIGATOR_ONLINE_PROPERTY:\r\n !goog.userAgent.WEBKIT || goog.userAgent.isVersionOrHigher('528'),\r\n\r\n /**\r\n * Whether HTML5 network online/offline events are supported.\r\n */\r\n HAS_HTML5_NETWORK_EVENT_SUPPORT:\r\n goog.userAgent.GECKO && goog.userAgent.isVersionOrHigher('1.9b') ||\r\n goog.userAgent.IE && goog.userAgent.isVersionOrHigher('8') ||\r\n goog.userAgent.OPERA && goog.userAgent.isVersionOrHigher('9.5') ||\r\n goog.userAgent.WEBKIT && goog.userAgent.isVersionOrHigher('528'),\r\n\r\n /**\r\n * Whether HTML5 network events fire on document.body, or otherwise the\r\n * window.\r\n */\r\n HTML5_NETWORK_EVENTS_FIRE_ON_BODY:\r\n goog.userAgent.GECKO && !goog.userAgent.isVersionOrHigher('8') ||\r\n goog.userAgent.IE && !goog.userAgent.isVersionOrHigher('9'),\r\n\r\n /**\r\n * Whether touch is enabled in the browser.\r\n */\r\n TOUCH_ENABLED:\r\n ('ontouchstart' in goog.global ||\r\n !!(goog.global['document'] && document.documentElement &&\r\n 'ontouchstart' in document.documentElement) ||\r\n // IE10 uses non-standard touch events, so it has a different check.\r\n !!(goog.global['navigator'] &&\r\n (goog.global['navigator']['maxTouchPoints'] ||\r\n goog.global['navigator']['msMaxTouchPoints']))),\r\n\r\n /**\r\n * Whether addEventListener supports W3C standard pointer events.\r\n * http://www.w3.org/TR/pointerevents/\r\n */\r\n POINTER_EVENTS: ('PointerEvent' in goog.global),\r\n\r\n /**\r\n * Whether addEventListener supports MSPointer events (only used in IE10).\r\n * http://msdn.microsoft.com/en-us/library/ie/hh772103(v=vs.85).aspx\r\n * http://msdn.microsoft.com/library/hh673557(v=vs.85).aspx\r\n */\r\n MSPOINTER_EVENTS:\r\n ('MSPointerEvent' in goog.global &&\r\n !!(goog.global['navigator'] &&\r\n goog.global['navigator']['msPointerEnabled'])),\r\n\r\n /**\r\n * Whether addEventListener supports {passive: true}.\r\n * https://developers.google.com/web/updates/2016/06/passive-event-listeners\r\n */\r\n PASSIVE_EVENTS: purify(function() {\r\n // If we're in a web worker or other custom environment, we can't tell.\r\n if (!goog.global.addEventListener || !Object.defineProperty) { // IE 8\r\n return false;\r\n }\r\n\r\n var passive = false;\r\n var options = Object.defineProperty({}, 'passive', {\r\n get: function() {\r\n passive = true;\r\n }\r\n });\r\n try {\r\n goog.global.addEventListener('test', goog.nullFunction, options);\r\n goog.global.removeEventListener('test', goog.nullFunction, options);\r\n } catch (e) {\r\n }\r\n\r\n return passive;\r\n })\r\n};\r\n\r\n\r\n/**\r\n * Tricks Closure Compiler into believing that a function is pure. The compiler\r\n * assumes that any `valueOf` function is pure, without analyzing its contents.\r\n *\r\n * @param {function(): T} fn\r\n * @return {T}\r\n * @template T\r\n */\r\nfunction purify(fn) {\r\n return ({valueOf: fn}).valueOf();\r\n}\r\n}); // goog.scope\r\n","// Copyright 2005 The Closure Library Authors. All Rights Reserved.\r\n//\r\n// Licensed under the Apache License, Version 2.0 (the \"License\");\r\n// you may not use this file except in compliance with the License.\r\n// You may obtain a copy of the License at\r\n//\r\n// http://www.apache.org/licenses/LICENSE-2.0\r\n//\r\n// Unless required by applicable law or agreed to in writing, software\r\n// distributed under the License is distributed on an \"AS-IS\" BASIS,\r\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n// See the License for the specific language governing permissions and\r\n// limitations under the License.\r\n\r\n/**\r\n * @fileoverview A base class for event objects.\r\n *\r\n */\r\n\r\n\r\ngoog.provide('goog.events.Event');\r\ngoog.provide('goog.events.EventLike');\r\n\r\n/**\r\n * goog.events.Event no longer depends on goog.Disposable. Keep requiring\r\n * goog.Disposable here to not break projects which assume this dependency.\r\n * @suppress {extraRequire}\r\n */\r\ngoog.require('goog.Disposable');\r\ngoog.require('goog.events.EventId');\r\n\r\n\r\n/**\r\n * A typedef for event like objects that are dispatchable via the\r\n * goog.events.dispatchEvent function. strings are treated as the type for a\r\n * goog.events.Event. Objects are treated as an extension of a new\r\n * goog.events.Event with the type property of the object being used as the type\r\n * of the Event.\r\n * @typedef {string|Object|goog.events.Event|goog.events.EventId}\r\n */\r\ngoog.events.EventLike;\r\n\r\n\r\n\r\n/**\r\n * A base class for event objects, so that they can support preventDefault and\r\n * stopPropagation.\r\n *\r\n * @suppress {underscore} Several properties on this class are technically\r\n * public, but referencing these properties outside this package is strongly\r\n * discouraged.\r\n *\r\n * @param {string|!goog.events.EventId} type Event Type.\r\n * @param {Object=} opt_target Reference to the object that is the target of\r\n * this event. It has to implement the `EventTarget` interface\r\n * declared at {@link http://developer.mozilla.org/en/DOM/EventTarget}.\r\n * @constructor\r\n */\r\ngoog.events.Event = function(type, opt_target) {\r\n /**\r\n * Event type.\r\n * @type {string}\r\n */\r\n this.type = type instanceof goog.events.EventId ? String(type) : type;\r\n\r\n /**\r\n * TODO(tbreisacher): The type should probably be\r\n * EventTarget|goog.events.EventTarget.\r\n *\r\n * Target of the event.\r\n * @type {Object|undefined}\r\n */\r\n this.target = opt_target;\r\n\r\n /**\r\n * Object that had the listener attached.\r\n * @type {Object|undefined}\r\n */\r\n this.currentTarget = this.target;\r\n\r\n /**\r\n * Whether to cancel the event in internal capture/bubble processing for IE.\r\n * @type {boolean}\r\n * @public\r\n */\r\n this.propagationStopped_ = false;\r\n\r\n /**\r\n * Whether the default action has been prevented.\r\n * This is a property to match the W3C specification at\r\n * {@link http://www.w3.org/TR/DOM-Level-3-Events/\r\n * #events-event-type-defaultPrevented}.\r\n * Must be treated as read-only outside the class.\r\n * @type {boolean}\r\n */\r\n this.defaultPrevented = false;\r\n\r\n /**\r\n * Return value for in internal capture/bubble processing for IE.\r\n * @type {boolean}\r\n * @public\r\n */\r\n this.returnValue_ = true;\r\n};\r\n\r\n\r\n/**\r\n * Stops event propagation.\r\n */\r\ngoog.events.Event.prototype.stopPropagation = function() {\r\n this.propagationStopped_ = true;\r\n};\r\n\r\n\r\n/**\r\n * Prevents the default action, for example a link redirecting to a url.\r\n */\r\ngoog.events.Event.prototype.preventDefault = function() {\r\n this.defaultPrevented = true;\r\n this.returnValue_ = false;\r\n};\r\n\r\n\r\n/**\r\n * Stops the propagation of the event. It is equivalent to\r\n * `e.stopPropagation()`, but can be used as the callback argument of\r\n * {@link goog.events.listen} without declaring another function.\r\n * @param {!goog.events.Event} e An event.\r\n */\r\ngoog.events.Event.stopPropagation = function(e) {\r\n e.stopPropagation();\r\n};\r\n\r\n\r\n/**\r\n * Prevents the default action. It is equivalent to\r\n * `e.preventDefault()`, but can be used as the callback argument of\r\n * {@link goog.events.listen} without declaring another function.\r\n * @param {!goog.events.Event} e An event.\r\n */\r\ngoog.events.Event.preventDefault = function(e) {\r\n e.preventDefault();\r\n};\r\n","// Copyright 2005 The Closure Library Authors. All Rights Reserved.\r\n//\r\n// Licensed under the Apache License, Version 2.0 (the \"License\");\r\n// you may not use this file except in compliance with the License.\r\n// You may obtain a copy of the License at\r\n//\r\n// http://www.apache.org/licenses/LICENSE-2.0\r\n//\r\n// Unless required by applicable law or agreed to in writing, software\r\n// distributed under the License is distributed on an \"AS-IS\" BASIS,\r\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n// See the License for the specific language governing permissions and\r\n// limitations under the License.\r\n\r\n/**\r\n * @fileoverview A patched, standardized event object for browser events.\r\n *\r\n * <pre>\r\n * The patched event object contains the following members:\r\n * - type {string} Event type, e.g. 'click'\r\n * - target {Object} The element that actually triggered the event\r\n * - currentTarget {Object} The element the listener is attached to\r\n * - relatedTarget {Object} For mouseover and mouseout, the previous object\r\n * - offsetX {number} X-coordinate relative to target\r\n * - offsetY {number} Y-coordinate relative to target\r\n * - clientX {number} X-coordinate relative to viewport\r\n * - clientY {number} Y-coordinate relative to viewport\r\n * - screenX {number} X-coordinate relative to the edge of the screen\r\n * - screenY {number} Y-coordinate relative to the edge of the screen\r\n * - button {number} Mouse button. Use isButton() to test.\r\n * - keyCode {number} Key-code\r\n * - ctrlKey {boolean} Was ctrl key depressed\r\n * - altKey {boolean} Was alt key depressed\r\n * - shiftKey {boolean} Was shift key depressed\r\n * - metaKey {boolean} Was meta key depressed\r\n * - pointerId {number} Pointer ID\r\n * - pointerType {string} Pointer type, e.g. 'mouse', 'pen', or 'touch'\r\n * - defaultPrevented {boolean} Whether the default action has been prevented\r\n * - state {Object} History state object\r\n *\r\n * NOTE: The keyCode member contains the raw browser keyCode. For normalized\r\n * key and character code use {@link goog.events.KeyHandler}.\r\n * </pre>\r\n *\r\n * @author arv@google.com (Erik Arvidsson)\r\n */\r\n\r\ngoog.provide('goog.events.BrowserEvent');\r\ngoog.provide('goog.events.BrowserEvent.MouseButton');\r\ngoog.provide('goog.events.BrowserEvent.PointerType');\r\n\r\ngoog.require('goog.debug');\r\ngoog.require('goog.events.BrowserFeature');\r\ngoog.require('goog.events.Event');\r\ngoog.require('goog.events.EventType');\r\ngoog.require('goog.reflect');\r\ngoog.require('goog.userAgent');\r\n\r\n/**\r\n * @define {boolean} If true, use the layerX and layerY properties of a native\r\n * browser event over the offsetX and offsetY properties, which cause expensive\r\n * reflow. If layerX or layerY is not defined, offsetX and offsetY will be used\r\n * as usual.\r\n */\r\ngoog.events.USE_LAYER_XY_AS_OFFSET_XY =\r\n goog.define('goog.events.USE_LAYER_XY_AS_OFFSET_XY', false);\r\n\r\n/**\r\n * Accepts a browser event object and creates a patched, cross browser event\r\n * object.\r\n * The content of this object will not be initialized if no event object is\r\n * provided. If this is the case, init() needs to be invoked separately.\r\n * @param {Event=} opt_e Browser event object.\r\n * @param {EventTarget=} opt_currentTarget Current target for event.\r\n * @constructor\r\n * @extends {goog.events.Event}\r\n */\r\ngoog.events.BrowserEvent = function(opt_e, opt_currentTarget) {\r\n goog.events.BrowserEvent.base(this, 'constructor', opt_e ? opt_e.type : '');\r\n\r\n /**\r\n * Target that fired the event.\r\n * @override\r\n * @type {?Node}\r\n */\r\n this.target = null;\r\n\r\n /**\r\n * Node that had the listener attached.\r\n * @override\r\n * @type {?Node|undefined}\r\n */\r\n this.currentTarget = null;\r\n\r\n /**\r\n * For mouseover and mouseout events, the related object for the event.\r\n * @type {?Node}\r\n */\r\n this.relatedTarget = null;\r\n\r\n /**\r\n * X-coordinate relative to target.\r\n * @type {number}\r\n */\r\n this.offsetX = 0;\r\n\r\n /**\r\n * Y-coordinate relative to target.\r\n * @type {number}\r\n */\r\n this.offsetY = 0;\r\n\r\n /**\r\n * X-coordinate relative to the window.\r\n * @type {number}\r\n */\r\n this.clientX = 0;\r\n\r\n /**\r\n * Y-coordinate relative to the window.\r\n * @type {number}\r\n */\r\n this.clientY = 0;\r\n\r\n /**\r\n * X-coordinate relative to the monitor.\r\n * @type {number}\r\n */\r\n this.screenX = 0;\r\n\r\n /**\r\n * Y-coordinate relative to the monitor.\r\n * @type {number}\r\n */\r\n this.screenY = 0;\r\n\r\n /**\r\n * Which mouse button was pressed.\r\n * @type {number}\r\n */\r\n this.button = 0;\r\n\r\n /**\r\n * Key of key press.\r\n * @type {string}\r\n */\r\n this.key = '';\r\n\r\n /**\r\n * Keycode of key press.\r\n * @type {number}\r\n */\r\n this.keyCode = 0;\r\n\r\n /**\r\n * Keycode of key press.\r\n * @type {number}\r\n */\r\n this.charCode = 0;\r\n\r\n /**\r\n * Whether control was pressed at time of event.\r\n * @type {boolean}\r\n */\r\n this.ctrlKey = false;\r\n\r\n /**\r\n * Whether alt was pressed at time of event.\r\n * @type {boolean}\r\n */\r\n this.altKey = false;\r\n\r\n /**\r\n * Whether shift was pressed at time of event.\r\n * @type {boolean}\r\n */\r\n this.shiftKey = false;\r\n\r\n /**\r\n * Whether the meta key was pressed at time of event.\r\n * @type {boolean}\r\n */\r\n this.metaKey = false;\r\n\r\n /**\r\n * History state object, only set for PopState events where it's a copy of the\r\n * state object provided to pushState or replaceState.\r\n * @type {?Object}\r\n */\r\n this.state = null;\r\n\r\n /**\r\n * Whether the default platform modifier key was pressed at time of event.\r\n * (This is control for all platforms except Mac, where it's Meta.)\r\n * @type {boolean}\r\n */\r\n this.platformModifierKey = false;\r\n\r\n /**\r\n * @type {number}\r\n */\r\n this.pointerId = 0;\r\n\r\n /**\r\n * @type {string}\r\n */\r\n this.pointerType = '';\r\n\r\n /**\r\n * The browser event object.\r\n * @private {?Event}\r\n */\r\n this.event_ = null;\r\n\r\n if (opt_e) {\r\n this.init(opt_e, opt_currentTarget);\r\n }\r\n};\r\ngoog.inherits(goog.events.BrowserEvent, goog.events.Event);\r\n\r\n\r\n/**\r\n * Normalized button constants for the mouse.\r\n * @enum {number}\r\n */\r\ngoog.events.BrowserEvent.MouseButton = {\r\n LEFT: 0,\r\n MIDDLE: 1,\r\n RIGHT: 2\r\n};\r\n\r\n\r\n/**\r\n * Normalized pointer type constants for pointer events.\r\n * @enum {string}\r\n */\r\ngoog.events.BrowserEvent.PointerType = {\r\n MOUSE: 'mouse',\r\n PEN: 'pen',\r\n TOUCH: 'touch'\r\n};\r\n\r\n\r\n/**\r\n * Static data for mapping mouse buttons.\r\n * @type {!Array<number>}\r\n * @deprecated Use `goog.events.BrowserEvent.IE_BUTTON_MAP` instead.\r\n */\r\ngoog.events.BrowserEvent.IEButtonMap = goog.debug.freeze([\r\n 1, // LEFT\r\n 4, // MIDDLE\r\n 2 // RIGHT\r\n]);\r\n\r\n\r\n/**\r\n * Static data for mapping mouse buttons.\r\n * @const {!Array<number>}\r\n */\r\ngoog.events.BrowserEvent.IE_BUTTON_MAP = goog.events.BrowserEvent.IEButtonMap;\r\n\r\n\r\n/**\r\n * Static data for mapping MSPointerEvent types to PointerEvent types.\r\n * @const {!Object<number, goog.events.BrowserEvent.PointerType>}\r\n */\r\ngoog.events.BrowserEvent.IE_POINTER_TYPE_MAP = goog.debug.freeze({\r\n 2: goog.events.BrowserEvent.PointerType.TOUCH,\r\n 3: goog.events.BrowserEvent.PointerType.PEN,\r\n 4: goog.events.BrowserEvent.PointerType.MOUSE\r\n});\r\n\r\n\r\n/**\r\n * Accepts a browser event object and creates a patched, cross browser event\r\n * object.\r\n * @param {Event} e Browser event object.\r\n * @param {EventTarget=} opt_currentTarget Current target for event.\r\n */\r\ngoog.events.BrowserEvent.prototype.init = function(e, opt_currentTarget) {\r\n var type = this.type = e.type;\r\n\r\n /**\r\n * On touch devices use the first \"changed touch\" as the relevant touch.\r\n * @type {?Touch}\r\n */\r\n var relevantTouch =\r\n e.changedTouches && e.changedTouches.length ? e.changedTouches[0] : null;\r\n\r\n // TODO(nicksantos): Change this.target to type EventTarget.\r\n this.target = /** @type {Node} */ (e.target) || e.srcElement;\r\n\r\n // TODO(nicksantos): Change this.currentTarget to type EventTarget.\r\n this.currentTarget = /** @type {Node} */ (opt_currentTarget);\r\n\r\n var relatedTarget = /** @type {Node} */ (e.relatedTarget);\r\n if (relatedTarget) {\r\n // There's a bug in FireFox where sometimes, relatedTarget will be a\r\n // chrome element, and accessing any property of it will get a permission\r\n // denied exception. See:\r\n // https://bugzilla.mozilla.org/show_bug.cgi?id=497780\r\n if (goog.userAgent.GECKO) {\r\n if (!goog.reflect.canAccessProperty(relatedTarget, 'nodeName')) {\r\n relatedTarget = null;\r\n }\r\n }\r\n } else if (type == goog.events.EventType.MOUSEOVER) {\r\n relatedTarget = e.fromElement;\r\n } else if (type == goog.events.EventType.MOUSEOUT) {\r\n relatedTarget = e.toElement;\r\n }\r\n\r\n this.relatedTarget = relatedTarget;\r\n\r\n if (relevantTouch) {\r\n this.clientX = relevantTouch.clientX !== undefined ? relevantTouch.clientX :\r\n relevantTouch.pageX;\r\n this.clientY = relevantTouch.clientY !== undefined ? relevantTouch.clientY :\r\n relevantTouch.pageY;\r\n this.screenX = relevantTouch.screenX || 0;\r\n this.screenY = relevantTouch.screenY || 0;\r\n } else {\r\n if (goog.events.USE_LAYER_XY_AS_OFFSET_XY) {\r\n this.offsetX = (e.layerX !== undefined) ? e.layerX : e.offsetX;\r\n this.offsetY = (e.layerY !== undefined) ? e.layerY : e.offsetY;\r\n } else {\r\n // Webkit emits a lame warning whenever layerX/layerY is accessed.\r\n // http://code.google.com/p/chromium/issues/detail?id=101733\r\n this.offsetX = (goog.userAgent.WEBKIT || e.offsetX !== undefined) ?\r\n e.offsetX :\r\n e.layerX;\r\n this.offsetY = (goog.userAgent.WEBKIT || e.offsetY !== undefined) ?\r\n e.offsetY :\r\n e.layerY;\r\n }\r\n this.clientX = e.clientX !== undefined ? e.clientX : e.pageX;\r\n this.clientY = e.clientY !== undefined ? e.clientY : e.pageY;\r\n this.screenX = e.screenX || 0;\r\n this.screenY = e.screenY || 0;\r\n }\r\n\r\n this.button = e.button;\r\n\r\n this.keyCode = e.keyCode || 0;\r\n this.key = e.key || '';\r\n this.charCode = e.charCode || (type == 'keypress' ? e.keyCode : 0);\r\n this.ctrlKey = e.ctrlKey;\r\n this.altKey = e.altKey;\r\n this.shiftKey = e.shiftKey;\r\n this.metaKey = e.metaKey;\r\n this.platformModifierKey = goog.userAgent.MAC ? e.metaKey : e.ctrlKey;\r\n this.pointerId = e.pointerId || 0;\r\n this.pointerType = goog.events.BrowserEvent.getPointerType_(e);\r\n this.state = e.state;\r\n this.event_ = e;\r\n if (e.defaultPrevented) {\r\n this.preventDefault();\r\n }\r\n};\r\n\r\n\r\n/**\r\n * Tests to see which button was pressed during the event. This is really only\r\n * useful in IE and Gecko browsers. And in IE, it's only useful for\r\n * mousedown/mouseup events, because click only fires for the left mouse button.\r\n *\r\n * Safari 2 only reports the left button being clicked, and uses the value '1'\r\n * instead of 0. Opera only reports a mousedown event for the middle button, and\r\n * no mouse events for the right button. Opera has default behavior for left and\r\n * middle click that can only be overridden via a configuration setting.\r\n *\r\n * There's a nice table of this mess at http://www.unixpapa.com/js/mouse.html.\r\n *\r\n * @param {goog.events.BrowserEvent.MouseButton} button The button\r\n * to test for.\r\n * @return {boolean} True if button was pressed.\r\n */\r\ngoog.events.BrowserEvent.prototype.isButton = function(button) {\r\n if (!goog.events.BrowserFeature.HAS_W3C_BUTTON) {\r\n if (this.type == 'click') {\r\n return button == goog.events.BrowserEvent.MouseButton.LEFT;\r\n } else {\r\n return !!(\r\n this.event_.button & goog.events.BrowserEvent.IE_BUTTON_MAP[button]);\r\n }\r\n } else {\r\n return this.event_.button == button;\r\n }\r\n};\r\n\r\n\r\n/**\r\n * Whether this has an \"action\"-producing mouse button.\r\n *\r\n * By definition, this includes left-click on windows/linux, and left-click\r\n * without the ctrl key on Macs.\r\n *\r\n * @return {boolean} The result.\r\n */\r\ngoog.events.BrowserEvent.prototype.isMouseActionButton = function() {\r\n // Webkit does not ctrl+click to be a right-click, so we\r\n // normalize it to behave like Gecko and Opera.\r\n return this.isButton(goog.events.BrowserEvent.MouseButton.LEFT) &&\r\n !(goog.userAgent.WEBKIT && goog.userAgent.MAC && this.ctrlKey);\r\n};\r\n\r\n\r\n/**\r\n * @override\r\n */\r\ngoog.events.BrowserEvent.prototype.stopPropagation = function() {\r\n goog.events.BrowserEvent.superClass_.stopPropagation.call(this);\r\n if (this.event_.stopPropagation) {\r\n this.event_.stopPropagation();\r\n } else {\r\n this.event_.cancelBubble = true;\r\n }\r\n};\r\n\r\n\r\n/**\r\n * @override\r\n */\r\ngoog.events.BrowserEvent.prototype.preventDefault = function() {\r\n goog.events.BrowserEvent.superClass_.preventDefault.call(this);\r\n var be = this.event_;\r\n if (!be.preventDefault) {\r\n be.returnValue = false;\r\n if (goog.events.BrowserFeature.SET_KEY_CODE_TO_PREVENT_DEFAULT) {\r\n\r\n try {\r\n // Most keys can be prevented using returnValue. Some special keys\r\n // require setting the keyCode to -1 as well:\r\n //\r\n // In IE7:\r\n // F3, F5, F10, F11, Ctrl+P, Crtl+O, Ctrl+F (these are taken from IE6)\r\n //\r\n // In IE8:\r\n // Ctrl+P, Crtl+O, Ctrl+F (F1-F12 cannot be stopped through the event)\r\n //\r\n // We therefore do this for all function keys as well as when Ctrl key\r\n // is pressed.\r\n var VK_F1 = 112;\r\n var VK_F12 = 123;\r\n if (be.ctrlKey || be.keyCode >= VK_F1 && be.keyCode <= VK_F12) {\r\n be.keyCode = -1;\r\n }\r\n } catch (ex) {\r\n // IE throws an 'access denied' exception when trying to change\r\n // keyCode in some situations (e.g. srcElement is input[type=file],\r\n // or srcElement is an anchor tag rewritten by parent's innerHTML).\r\n // Do nothing in this case.\r\n }\r\n }\r\n } else {\r\n be.preventDefault();\r\n }\r\n};\r\n\r\n\r\n/**\r\n * @return {Event} The underlying browser event object.\r\n */\r\ngoog.events.BrowserEvent.prototype.getBrowserEvent = function() {\r\n return this.event_;\r\n};\r\n\r\n\r\n/**\r\n * Extracts the pointer type from the given event.\r\n * @param {!Event} e\r\n * @return {string} The pointer type, e.g. 'mouse', 'pen', or 'touch'.\r\n * @private\r\n */\r\ngoog.events.BrowserEvent.getPointerType_ = function(e) {\r\n if (goog.isString(e.pointerType)) {\r\n return e.pointerType;\r\n }\r\n // IE10 uses integer codes for pointer type.\r\n // https://msdn.microsoft.com/en-us/library/hh772359(v=vs.85).aspx\r\n return goog.events.BrowserEvent.IE_POINTER_TYPE_MAP[e.pointerType] || '';\r\n};\r\n","// Copyright 2010 The Closure Library Authors. All Rights Reserved.\r\n//\r\n// Licensed under the Apache License, Version 2.0 (the \"License\");\r\n// you may not use this file except in compliance with the License.\r\n// You may obtain a copy of the License at\r\n//\r\n// http://www.apache.org/licenses/LICENSE-2.0\r\n//\r\n// Unless required by applicable law or agreed to in writing, software\r\n// distributed under the License is distributed on an \"AS-IS\" BASIS,\r\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n// See the License for the specific language governing permissions and\r\n// limitations under the License.\r\n\r\n/**\r\n * @fileoverview Event Types.\r\n *\r\n * @author arv@google.com (Erik Arvidsson)\r\n */\r\n\r\n\r\ngoog.provide('goog.events.EventType');\r\ngoog.provide('goog.events.MouseAsMouseEventType');\r\ngoog.provide('goog.events.MouseEvents');\r\ngoog.provide('goog.events.PointerAsMouseEventType');\r\ngoog.provide('goog.events.PointerAsTouchEventType');\r\ngoog.provide('goog.events.PointerFallbackEventType');\r\ngoog.provide('goog.events.PointerTouchFallbackEventType');\r\n\r\ngoog.require('goog.events.BrowserFeature');\r\ngoog.require('goog.userAgent');\r\n\r\n\r\n/**\r\n * Returns a prefixed event name for the current browser.\r\n * @param {string} eventName The name of the event.\r\n * @return {string} The prefixed event name.\r\n * @suppress {missingRequire|missingProvide}\r\n * @private\r\n */\r\ngoog.events.getVendorPrefixedName_ = function(eventName) {\r\n return goog.userAgent.WEBKIT ?\r\n 'webkit' + eventName :\r\n (goog.userAgent.OPERA ? 'o' + eventName.toLowerCase() :\r\n eventName.toLowerCase());\r\n};\r\n\r\n\r\n/**\r\n * Constants for event names.\r\n * @enum {string}\r\n */\r\ngoog.events.EventType = {\r\n // Mouse events\r\n CLICK: 'click',\r\n RIGHTCLICK: 'rightclick',\r\n DBLCLICK: 'dblclick',\r\n AUXCLICK: 'auxclick',\r\n MOUSEDOWN: 'mousedown',\r\n MOUSEUP: 'mouseup',\r\n MOUSEOVER: 'mouseover',\r\n MOUSEOUT: 'mouseout',\r\n MOUSEMOVE: 'mousemove',\r\n MOUSEENTER: 'mouseenter',\r\n MOUSELEAVE: 'mouseleave',\r\n\r\n // Non-existent event; will never fire. This exists as a mouse counterpart to\r\n // POINTERCANCEL.\r\n MOUSECANCEL: 'mousecancel',\r\n\r\n // Selection events.\r\n // https://www.w3.org/TR/selection-api/\r\n SELECTIONCHANGE: 'selectionchange',\r\n SELECTSTART: 'selectstart', // IE, Safari, Chrome\r\n\r\n // Wheel events\r\n // http://www.w3.org/TR/DOM-Level-3-Events/#events-wheelevents\r\n WHEEL: 'wheel',\r\n\r\n // Key events\r\n KEYPRESS: 'keypress',\r\n KEYDOWN: 'keydown',\r\n KEYUP: 'keyup',\r\n\r\n // Focus\r\n BLUR: 'blur',\r\n FOCUS: 'focus',\r\n DEACTIVATE: 'deactivate', // IE only\r\n FOCUSIN: 'focusin',\r\n FOCUSOUT: 'focusout',\r\n\r\n // Forms\r\n CHANGE: 'change',\r\n RESET: 'reset',\r\n SELECT: 'select',\r\n SUBMIT: 'submit',\r\n INPUT: 'input',\r\n PROPERTYCHANGE: 'propertychange', // IE only\r\n\r\n // Drag and drop\r\n DRAGSTART: 'dragstart',\r\n DRAG: 'drag',\r\n DRAGENTER: 'dragenter',\r\n DRAGOVER: 'dragover',\r\n DRAGLEAVE: 'dragleave',\r\n DROP: 'drop',\r\n DRAGEND: 'dragend',\r\n\r\n // Touch events\r\n // Note that other touch events exist, but we should follow the W3C list here.\r\n // http://www.w3.org/TR/touch-events/#list-of-touchevent-types\r\n TOUCHSTART: 'touchstart',\r\n TOUCHMOVE: 'touchmove',\r\n TOUCHEND: 'touchend',\r\n TOUCHCANCEL: 'touchcancel',\r\n\r\n // Misc\r\n BEFOREUNLOAD: 'beforeunload',\r\n CONSOLEMESSAGE: 'consolemessage',\r\n CONTEXTMENU: 'contextmenu',\r\n DEVICECHANGE: 'devicechange',\r\n DEVICEMOTION: 'devicemotion',\r\n DEVICEORIENTATION: 'deviceorientation',\r\n DOMCONTENTLOADED: 'DOMContentLoaded',\r\n ERROR: 'error',\r\n HELP: 'help',\r\n LOAD: 'load',\r\n LOSECAPTURE: 'losecapture',\r\n ORIENTATIONCHANGE: 'orientationchange',\r\n READYSTATECHANGE: 'readystatechange',\r\n RESIZE: 'resize',\r\n SCROLL: 'scroll',\r\n UNLOAD: 'unload',\r\n\r\n // Media events\r\n CANPLAY: 'canplay',\r\n CANPLAYTHROUGH: 'canplaythrough',\r\n DURATIONCHANGE: 'durationchange',\r\n EMPTIED: 'emptied',\r\n ENDED: 'ended',\r\n LOADEDDATA: 'loadeddata',\r\n LOADEDMETADATA: 'loadedmetadata',\r\n PAUSE: 'pause',\r\n PLAY: 'play',\r\n PLAYING: 'playing',\r\n RATECHANGE: 'ratechange',\r\n SEEKED: 'seeked',\r\n SEEKING: 'seeking',\r\n STALLED: 'stalled',\r\n SUSPEND: 'suspend',\r\n TIMEUPDATE: 'timeupdate',\r\n VOLUMECHANGE: 'volumechange',\r\n WAITING: 'waiting',\r\n\r\n // Media Source Extensions events\r\n // https://www.w3.org/TR/media-source/#mediasource-events\r\n SOURCEOPEN: 'sourceopen',\r\n SOURCEENDED: 'sourceended',\r\n SOURCECLOSED: 'sourceclosed',\r\n // https://www.w3.org/TR/media-source/#sourcebuffer-events\r\n ABORT: 'abort',\r\n UPDATE: 'update',\r\n UPDATESTART: 'updatestart',\r\n UPDATEEND: 'updateend',\r\n\r\n // HTML 5 History events\r\n // See http://www.w3.org/TR/html5/browsers.html#event-definitions-0\r\n HASHCHANGE: 'hashchange',\r\n PAGEHIDE: 'pagehide',\r\n PAGESHOW: 'pageshow',\r\n POPSTATE: 'popstate',\r\n\r\n // Copy and Paste\r\n // Support is limited. Make sure it works on your favorite browser\r\n // before using.\r\n // http://www.quirksmode.org/dom/events/cutcopypaste.html\r\n COPY: 'copy',\r\n PASTE: 'paste',\r\n CUT: 'cut',\r\n BEFORECOPY: 'beforecopy',\r\n BEFORECUT: 'beforecut',\r\n BEFOREPASTE: 'beforepaste',\r\n\r\n // HTML5 online/offline events.\r\n // http://www.w3.org/TR/offline-webapps/#related\r\n ONLINE: 'online',\r\n OFFLINE: 'offline',\r\n\r\n // HTML 5 worker events\r\n MESSAGE: 'message',\r\n CONNECT: 'connect',\r\n\r\n // Service Worker Events - ServiceWorkerGlobalScope context\r\n // See https://w3c.github.io/ServiceWorker/#execution-context-events\r\n // Note: message event defined in worker events section\r\n INSTALL: 'install',\r\n ACTIVATE: 'activate',\r\n FETCH: 'fetch',\r\n FOREIGNFETCH: 'foreignfetch',\r\n MESSAGEERROR: 'messageerror',\r\n\r\n // Service Worker Events - Document context\r\n // See https://w3c.github.io/ServiceWorker/#document-context-events\r\n STATECHANGE: 'statechange',\r\n UPDATEFOUND: 'updatefound',\r\n CONTROLLERCHANGE: 'controllerchange',\r\n\r\n // CSS animation events.\r\n /** @suppress {missingRequire} */\r\n ANIMATIONSTART: goog.events.getVendorPrefixedName_('AnimationStart'),\r\n /** @suppress {missingRequire} */\r\n ANIMATIONEND: goog.events.getVendorPrefixedName_('AnimationEnd'),\r\n /** @suppress {missingRequire} */\r\n ANIMATIONITERATION: goog.events.getVendorPrefixedName_('AnimationIteration'),\r\n\r\n // CSS transition events. Based on the browser support described at:\r\n // https://developer.mozilla.org/en/css/css_transitions#Browser_compatibility\r\n /** @suppress {missingRequire} */\r\n TRANSITIONEND: goog.events.getVendorPrefixedName_('TransitionEnd'),\r\n\r\n // W3C Pointer Events\r\n // http://www.w3.org/TR/pointerevents/\r\n POINTERDOWN: 'pointerdown',\r\n POINTERUP: 'pointerup',\r\n POINTERCANCEL: 'pointercancel',\r\n POINTERMOVE: 'pointermove',\r\n POINTEROVER: 'pointerover',\r\n POINTEROUT: 'pointerout',\r\n POINTERENTER: 'pointerenter',\r\n POINTERLEAVE: 'pointerleave',\r\n GOTPOINTERCAPTURE: 'gotpointercapture',\r\n LOSTPOINTERCAPTURE: 'lostpointercapture',\r\n\r\n // IE specific events.\r\n // See http://msdn.microsoft.com/en-us/library/ie/hh772103(v=vs.85).aspx\r\n // Note: these events will be supplanted in IE11.\r\n MSGESTURECHANGE: 'MSGestureChange',\r\n MSGESTUREEND: 'MSGestureEnd',\r\n MSGESTUREHOLD: 'MSGestureHold',\r\n MSGESTURESTART: 'MSGestureStart',\r\n MSGESTURETAP: 'MSGestureTap',\r\n MSGOTPOINTERCAPTURE: 'MSGotPointerCapture',\r\n MSINERTIASTART: 'MSInertiaStart',\r\n MSLOSTPOINTERCAPTURE: 'MSLostPointerCapture',\r\n MSPOINTERCANCEL: 'MSPointerCancel',\r\n MSPOINTERDOWN: 'MSPointerDown',\r\n MSPOINTERENTER: 'MSPointerEnter',\r\n MSPOINTERHOVER: 'MSPointerHover',\r\n MSPOINTERLEAVE: 'MSPointerLeave',\r\n MSPOINTERMOVE: 'MSPointerMove',\r\n MSPOINTEROUT: 'MSPointerOut',\r\n MSPOINTEROVER: 'MSPointerOver',\r\n MSPOINTERUP: 'MSPointerUp',\r\n\r\n // Native IMEs/input tools events.\r\n TEXT: 'text',\r\n // The textInput event is supported in IE9+, but only in lower case. All other\r\n // browsers use the camel-case event name.\r\n TEXTINPUT: goog.userAgent.IE ? 'textinput' : 'textInput',\r\n COMPOSITIONSTART: 'compositionstart',\r\n COMPOSITIONUPDATE: 'compositionupdate',\r\n COMPOSITIONEND: 'compositionend',\r\n\r\n // The beforeinput event is initially only supported in Safari. See\r\n // https://bugs.chromium.org/p/chromium/issues/detail?id=342670 for Chrome\r\n // implementation tracking.\r\n BEFOREINPUT: 'beforeinput',\r\n\r\n // Webview tag events\r\n // See https://developer.chrome.com/apps/tags/webview\r\n EXIT: 'exit',\r\n LOADABORT: 'loadabort',\r\n LOADCOMMIT: 'loadcommit',\r\n LOADREDIRECT: 'loadredirect',\r\n LOADSTART: 'loadstart',\r\n LOADSTOP: 'loadstop',\r\n RESPONSIVE: 'responsive',\r\n SIZECHANGED: 'sizechanged',\r\n UNRESPONSIVE: 'unresponsive',\r\n\r\n // HTML5 Page Visibility API. See details at\r\n // `goog.labs.dom.PageVisibilityMonitor`.\r\n VISIBILITYCHANGE: 'visibilitychange',\r\n\r\n // LocalStorage event.\r\n STORAGE: 'storage',\r\n\r\n // DOM Level 2 mutation events (deprecated).\r\n DOMSUBTREEMODIFIED: 'DOMSubtreeModified',\r\n DOMNODEINSERTED: 'DOMNodeInserted',\r\n DOMNODEREMOVED: 'DOMNodeRemoved',\r\n DOMNODEREMOVEDFROMDOCUMENT: 'DOMNodeRemovedFromDocument',\r\n DOMNODEINSERTEDINTODOCUMENT: 'DOMNodeInsertedIntoDocument',\r\n DOMATTRMODIFIED: 'DOMAttrModified',\r\n DOMCHARACTERDATAMODIFIED: 'DOMCharacterDataModified',\r\n\r\n // Print events.\r\n BEFOREPRINT: 'beforeprint',\r\n AFTERPRINT: 'afterprint',\r\n\r\n // Web app manifest events.\r\n BEFOREINSTALLPROMPT: 'beforeinstallprompt',\r\n APPINSTALLED: 'appinstalled'\r\n};\r\n\r\n\r\n/**\r\n * Returns one of the given pointer fallback event names in order of preference:\r\n * 1. pointerEventName\r\n * 2. msPointerEventName\r\n * 3. fallbackEventName\r\n * @param {string} pointerEventName\r\n * @param {string} msPointerEventName\r\n * @param {string} fallbackEventName\r\n * @return {string} The supported pointer or fallback (mouse or touch) event\r\n * name.\r\n * @private\r\n */\r\ngoog.events.getPointerFallbackEventName_ = function(\r\n pointerEventName, msPointerEventName, fallbackEventName) {\r\n if (goog.events.BrowserFeature.POINTER_EVENTS) {\r\n return pointerEventName;\r\n }\r\n if (goog.events.BrowserFeature.MSPOINTER_EVENTS) {\r\n return msPointerEventName;\r\n }\r\n return fallbackEventName;\r\n};\r\n\r\n\r\n/**\r\n * Constants for pointer event names that fall back to corresponding mouse event\r\n * names on unsupported platforms. These are intended to be drop-in replacements\r\n * for corresponding values in `goog.events.EventType`.\r\n * @enum {string}\r\n */\r\ngoog.events.PointerFallbackEventType = {\r\n POINTERDOWN: goog.events.getPointerFallbackEventName_(\r\n goog.events.EventType.POINTERDOWN, goog.events.EventType.MSPOINTERDOWN,\r\n goog.events.EventType.MOUSEDOWN),\r\n POINTERUP: goog.events.getPointerFallbackEventName_(\r\n goog.events.EventType.POINTERUP, goog.events.EventType.MSPOINTERUP,\r\n goog.events.EventType.MOUSEUP),\r\n POINTERCANCEL: goog.events.getPointerFallbackEventName_(\r\n goog.events.EventType.POINTERCANCEL,\r\n goog.events.EventType.MSPOINTERCANCEL,\r\n // When falling back to mouse events, there is no MOUSECANCEL equivalent\r\n // of POINTERCANCEL. In this case POINTERUP already falls back to MOUSEUP\r\n // which represents both UP and CANCEL. POINTERCANCEL does not fall back\r\n // to MOUSEUP to prevent listening twice on the same event.\r\n goog.events.EventType.MOUSECANCEL),\r\n POINTERMOVE: goog.events.getPointerFallbackEventName_(\r\n goog.events.EventType.POINTERMOVE, goog.events.EventType.MSPOINTERMOVE,\r\n goog.events.EventType.MOUSEMOVE),\r\n POINTEROVER: goog.events.getPointerFallbackEventName_(\r\n goog.events.EventType.POINTEROVER, goog.events.EventType.MSPOINTEROVER,\r\n goog.events.EventType.MOUSEOVER),\r\n POINTEROUT: goog.events.getPointerFallbackEventName_(\r\n goog.events.EventType.POINTEROUT, goog.events.EventType.MSPOINTEROUT,\r\n goog.events.EventType.MOUSEOUT),\r\n POINTERENTER: goog.events.getPointerFallbackEventName_(\r\n goog.events.EventType.POINTERENTER, goog.events.EventType.MSPOINTERENTER,\r\n goog.events.EventType.MOUSEENTER),\r\n POINTERLEAVE: goog.events.getPointerFallbackEventName_(\r\n goog.events.EventType.POINTERLEAVE, goog.events.EventType.MSPOINTERLEAVE,\r\n goog.events.EventType.MOUSELEAVE)\r\n};\r\n\r\n\r\n/**\r\n * Constants for pointer event names that fall back to corresponding touch event\r\n * names on unsupported platforms. These are intended to be drop-in replacements\r\n * for corresponding values in `goog.events.EventType`.\r\n * @enum {string}\r\n */\r\ngoog.events.PointerTouchFallbackEventType = {\r\n POINTERDOWN: goog.events.getPointerFallbackEventName_(\r\n goog.events.EventType.POINTERDOWN, goog.events.EventType.MSPOINTERDOWN,\r\n goog.events.EventType.TOUCHSTART),\r\n POINTERUP: goog.events.getPointerFallbackEventName_(\r\n goog.events.EventType.POINTERUP, goog.events.EventType.MSPOINTERUP,\r\n goog.events.EventType.TOUCHEND),\r\n POINTERCANCEL: goog.events.getPointerFallbackEventName_(\r\n goog.events.EventType.POINTERCANCEL,\r\n goog.events.EventType.MSPOINTERCANCEL, goog.events.EventType.TOUCHCANCEL),\r\n POINTERMOVE: goog.events.getPointerFallbackEventName_(\r\n goog.events.EventType.POINTERMOVE, goog.events.EventType.MSPOINTERMOVE,\r\n goog.events.EventType.TOUCHMOVE)\r\n};\r\n\r\n\r\n/**\r\n * Mapping of mouse event names to underlying browser event names.\r\n * @typedef {{\r\n * MOUSEDOWN: string,\r\n * MOUSEUP: string,\r\n * MOUSECANCEL:string,\r\n * MOUSEMOVE:string,\r\n * MOUSEOVER:string,\r\n * MOUSEOUT:string,\r\n * MOUSEENTER:string,\r\n * MOUSELEAVE: string,\r\n * }}\r\n */\r\ngoog.events.MouseEvents;\r\n\r\n\r\n/**\r\n * An alias for `goog.events.EventType.MOUSE*` event types that is overridden by\r\n * corresponding `POINTER*` event types.\r\n * @const {!goog.events.MouseEvents}\r\n */\r\ngoog.events.PointerAsMouseEventType = {\r\n MOUSEDOWN: goog.events.PointerFallbackEventType.POINTERDOWN,\r\n MOUSEUP: goog.events.PointerFallbackEventType.POINTERUP,\r\n MOUSECANCEL: goog.events.PointerFallbackEventType.POINTERCANCEL,\r\n MOUSEMOVE: goog.events.PointerFallbackEventType.POINTERMOVE,\r\n MOUSEOVER: goog.events.PointerFallbackEventType.POINTEROVER,\r\n MOUSEOUT: goog.events.PointerFallbackEventType.POINTEROUT,\r\n MOUSEENTER: goog.events.PointerFallbackEventType.POINTERENTER,\r\n MOUSELEAVE: goog.events.PointerFallbackEventType.POINTERLEAVE\r\n};\r\n\r\n\r\n/**\r\n * An alias for `goog.events.EventType.MOUSE*` event types that continue to use\r\n * mouse events.\r\n * @const {!goog.events.MouseEvents}\r\n */\r\ngoog.events.MouseAsMouseEventType = {\r\n MOUSEDOWN: goog.events.EventType.MOUSEDOWN,\r\n MOUSEUP: goog.events.EventType.MOUSEUP,\r\n MOUSECANCEL: goog.events.EventType.MOUSECANCEL,\r\n MOUSEMOVE: goog.events.EventType.MOUSEMOVE,\r\n MOUSEOVER: goog.events.EventType.MOUSEOVER,\r\n MOUSEOUT: goog.events.EventType.MOUSEOUT,\r\n MOUSEENTER: goog.events.EventType.MOUSEENTER,\r\n MOUSELEAVE: goog.events.EventType.MOUSELEAVE\r\n};\r\n\r\n\r\n/**\r\n * An alias for `goog.events.EventType.TOUCH*` event types that is overridden by\r\n * corresponding `POINTER*` event types.\r\n * @enum {string}\r\n */\r\ngoog.events.PointerAsTouchEventType = {\r\n TOUCHCANCEL: goog.events.PointerTouchFallbackEventType.POINTERCANCEL,\r\n TOUCHEND: goog.events.PointerTouchFallbackEventType.POINTERUP,\r\n TOUCHMOVE: goog.events.PointerTouchFallbackEventType.POINTERMOVE,\r\n TOUCHSTART: goog.events.PointerTouchFallbackEventType.POINTERDOWN\r\n};\r\n","// Copyright 2012 The Closure Library Authors. All Rights Reserved.\r\n//\r\n// Licensed under the Apache License, Version 2.0 (the \"License\");\r\n// you may not use this file except in compliance with the License.\r\n// You may obtain a copy of the License at\r\n//\r\n// http://www.apache.org/licenses/LICENSE-2.0\r\n//\r\n// Unless required by applicable law or agreed to in writing, software\r\n// distributed under the License is distributed on an \"AS-IS\" BASIS,\r\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n// See the License for the specific language governing permissions and\r\n// limitations under the License.\r\n\r\n/**\r\n * @fileoverview An interface for a listenable JavaScript object.\r\n * @author chrishenry@google.com (Chris Henry)\r\n */\r\n\r\ngoog.provide('goog.events.Listenable');\r\ngoog.provide('goog.events.ListenableKey');\r\n\r\n/** @suppress {extraRequire} */\r\ngoog.require('goog.events.EventId');\r\n\r\ngoog.forwardDeclare('goog.events.EventLike');\r\ngoog.forwardDeclare('goog.events.EventTarget');\r\n\r\n\r\n\r\n/**\r\n * A listenable interface. A listenable is an object with the ability\r\n * to dispatch/broadcast events to \"event listeners\" registered via\r\n * listen/listenOnce.\r\n *\r\n * The interface allows for an event propagation mechanism similar\r\n * to one offered by native browser event targets, such as\r\n * capture/bubble mechanism, stopping propagation, and preventing\r\n * default actions. Capture/bubble mechanism depends on the ancestor\r\n * tree constructed via `#getParentEventTarget`; this tree\r\n * must be directed acyclic graph. The meaning of default action(s)\r\n * in preventDefault is specific to a particular use case.\r\n *\r\n * Implementations that do not support capture/bubble or can not have\r\n * a parent listenable can simply not implement any ability to set the\r\n * parent listenable (and have `#getParentEventTarget` return\r\n * null).\r\n *\r\n * Implementation of this class can be used with or independently from\r\n * goog.events.\r\n *\r\n * Implementation must call `#addImplementation(implClass)`.\r\n *\r\n * @interface\r\n * @see goog.events\r\n * @see http://www.w3.org/TR/DOM-Level-2-Events/events.html\r\n */\r\ngoog.events.Listenable = function() {};\r\n\r\n\r\n/**\r\n * An expando property to indicate that an object implements\r\n * goog.events.Listenable.\r\n *\r\n * See addImplementation/isImplementedBy.\r\n *\r\n * @type {string}\r\n * @const\r\n */\r\ngoog.events.Listenable.IMPLEMENTED_BY_PROP =\r\n 'closure_listenable_' + ((Math.random() * 1e6) | 0);\r\n\r\n\r\n/**\r\n * Marks a given class (constructor) as an implementation of\r\n * Listenable, so that we can query that fact at runtime. The class\r\n * must have already implemented the interface.\r\n * @param {function(new:goog.events.Listenable,...)} cls The class constructor.\r\n * The corresponding class must have already implemented the interface.\r\n */\r\ngoog.events.Listenable.addImplementation = function(cls) {\r\n cls.prototype[goog.events.Listenable.IMPLEMENTED_BY_PROP] = true;\r\n};\r\n\r\n\r\n/**\r\n * @param {Object} obj The object to check.\r\n * @return {boolean} Whether a given instance implements Listenable. The\r\n * class/superclass of the instance must call addImplementation.\r\n */\r\ngoog.events.Listenable.isImplementedBy = function(obj) {\r\n return !!(obj && obj[goog.events.Listenable.IMPLEMENTED_BY_PROP]);\r\n};\r\n\r\n\r\n/**\r\n * Adds an event listener. A listener can only be added once to an\r\n * object and if it is added again the key for the listener is\r\n * returned. Note that if the existing listener is a one-off listener\r\n * (registered via listenOnce), it will no longer be a one-off\r\n * listener after a call to listen().\r\n *\r\n * @param {string|!goog.events.EventId<EVENTOBJ>} type The event type id.\r\n * @param {function(this:SCOPE, EVENTOBJ):(boolean|undefined)} listener Callback\r\n * method.\r\n * @param {boolean=} opt_useCapture Whether to fire in capture phase\r\n * (defaults to false).\r\n * @param {SCOPE=} opt_listenerScope Object in whose scope to call the\r\n * listener.\r\n * @return {!goog.events.ListenableKey} Unique key for the listener.\r\n * @template SCOPE,EVENTOBJ\r\n */\r\ngoog.events.Listenable.prototype.listen;\r\n\r\n\r\n/**\r\n * Adds an event listener that is removed automatically after the\r\n * listener fired once.\r\n *\r\n * If an existing listener already exists, listenOnce will do\r\n * nothing. In particular, if the listener was previously registered\r\n * via listen(), listenOnce() will not turn the listener into a\r\n * one-off listener. Similarly, if there is already an existing\r\n * one-off listener, listenOnce does not modify the listeners (it is\r\n * still a once listener).\r\n *\r\n * @param {string|!goog.events.EventId<EVENTOBJ>} type The event type id.\r\n * @param {function(this:SCOPE, EVENTOBJ):(boolean|undefined)} listener Callback\r\n * method.\r\n * @param {boolean=} opt_useCapture Whether to fire in capture phase\r\n * (defaults to false).\r\n * @param {SCOPE=} opt_listenerScope Object in whose scope to call the\r\n * listener.\r\n * @return {!goog.events.ListenableKey} Unique key for the listener.\r\n * @template SCOPE,EVENTOBJ\r\n */\r\ngoog.events.Listenable.prototype.listenOnce;\r\n\r\n\r\n/**\r\n * Removes an event listener which was added with listen() or listenOnce().\r\n *\r\n * @param {string|!goog.events.EventId<EVENTOBJ>} type The event type id.\r\n * @param {function(this:SCOPE, EVENTOBJ):(boolean|undefined)} listener Callback\r\n * method.\r\n * @param {boolean=} opt_useCapture Whether to fire in capture phase\r\n * (defaults to false).\r\n * @param {SCOPE=} opt_listenerScope Object in whose scope to call\r\n * the listener.\r\n * @return {boolean} Whether any listener was removed.\r\n * @template SCOPE,EVENTOBJ\r\n */\r\ngoog.events.Listenable.prototype.unlisten;\r\n\r\n\r\n/**\r\n * Removes an event listener which was added with listen() by the key\r\n * returned by listen().\r\n *\r\n * @param {!goog.events.ListenableKey} key The key returned by\r\n * listen() or listenOnce().\r\n * @return {boolean} Whether any listener was removed.\r\n */\r\ngoog.events.Listenable.prototype.unlistenByKey;\r\n\r\n\r\n/**\r\n * Dispatches an event (or event like object) and calls all listeners\r\n * listening for events of this type. The type of the event is decided by the\r\n * type property on the event object.\r\n *\r\n * If any of the listeners returns false OR calls preventDefault then this\r\n * function will return false. If one of the capture listeners calls\r\n * stopPropagation, then the bubble listeners won't fire.\r\n *\r\n * @param {goog.events.EventLike} e Event object.\r\n * @return {boolean} If anyone called preventDefault on the event object (or\r\n * if any of the listeners returns false) this will also return false.\r\n */\r\ngoog.events.Listenable.prototype.dispatchEvent;\r\n\r\n\r\n/**\r\n * Removes all listeners from this listenable. If type is specified,\r\n * it will only remove listeners of the particular type. otherwise all\r\n * registered listeners will be removed.\r\n *\r\n * @param {string=} opt_type Type of event to remove, default is to\r\n * remove all types.\r\n * @return {number} Number of listeners removed.\r\n */\r\ngoog.events.Listenable.prototype.removeAllListeners;\r\n\r\n\r\n/**\r\n * Returns the parent of this event target to use for capture/bubble\r\n * mechanism.\r\n *\r\n * NOTE(chrishenry): The name reflects the original implementation of\r\n * custom event target (`goog.events.EventTarget`). We decided\r\n * that changing the name is not worth it.\r\n *\r\n * @return {goog.events.Listenable} The parent EventTarget or null if\r\n * there is no parent.\r\n */\r\ngoog.events.Listenable.prototype.getParentEventTarget;\r\n\r\n\r\n/**\r\n * Fires all registered listeners in this listenable for the given\r\n * type and capture mode, passing them the given eventObject. This\r\n * does not perform actual capture/bubble. Only implementors of the\r\n * interface should be using this.\r\n *\r\n * @param {string|!goog.events.EventId<EVENTOBJ>} type The type of the\r\n * listeners to fire.\r\n * @param {boolean} capture The capture mode of the listeners to fire.\r\n * @param {EVENTOBJ} eventObject The event object to fire.\r\n * @return {boolean} Whether all listeners succeeded without\r\n * attempting to prevent default behavior. If any listener returns\r\n * false or called goog.events.Event#preventDefault, this returns\r\n * false.\r\n * @template EVENTOBJ\r\n */\r\ngoog.events.Listenable.prototype.fireListeners;\r\n\r\n\r\n/**\r\n * Gets all listeners in this listenable for the given type and\r\n * capture mode.\r\n *\r\n * @param {string|!goog.events.EventId} type The type of the listeners to fire.\r\n * @param {boolean} capture The capture mode of the listeners to fire.\r\n * @return {!Array<!goog.events.ListenableKey>} An array of registered\r\n * listeners.\r\n * @template EVENTOBJ\r\n */\r\ngoog.events.Listenable.prototype.getListeners;\r\n\r\n\r\n/**\r\n * Gets the goog.events.ListenableKey for the event or null if no such\r\n * listener is in use.\r\n *\r\n * @param {string|!goog.events.EventId<EVENTOBJ>} type The name of the event\r\n * without the 'on' prefix.\r\n * @param {function(this:SCOPE, EVENTOBJ):(boolean|undefined)} listener The\r\n * listener function to get.\r\n * @param {boolean} capture Whether the listener is a capturing listener.\r\n * @param {SCOPE=} opt_listenerScope Object in whose scope to call the\r\n * listener.\r\n * @return {goog.events.ListenableKey} the found listener or null if not found.\r\n * @template SCOPE,EVENTOBJ\r\n */\r\ngoog.events.Listenable.prototype.getListener;\r\n\r\n\r\n/**\r\n * Whether there is any active listeners matching the specified\r\n * signature. If either the type or capture parameters are\r\n * unspecified, the function will match on the remaining criteria.\r\n *\r\n * @param {string|!goog.events.EventId<EVENTOBJ>=} opt_type Event type.\r\n * @param {boolean=} opt_capture Whether to check for capture or bubble\r\n * listeners.\r\n * @return {boolean} Whether there is any active listeners matching\r\n * the requested type and/or capture phase.\r\n * @template EVENTOBJ\r\n */\r\ngoog.events.Listenable.prototype.hasListener;\r\n\r\n\r\n\r\n/**\r\n * An interface that describes a single registered listener.\r\n * @interface\r\n */\r\ngoog.events.ListenableKey = function() {};\r\n\r\n\r\n/**\r\n * Counter used to create a unique key\r\n * @type {number}\r\n * @private\r\n */\r\ngoog.events.ListenableKey.counter_ = 0;\r\n\r\n\r\n/**\r\n * Reserves a key to be used for ListenableKey#key field.\r\n * @return {number} A number to be used to fill ListenableKey#key\r\n * field.\r\n */\r\ngoog.events.ListenableKey.reserveKey = function() {\r\n return ++goog.events.ListenableKey.counter_;\r\n};\r\n\r\n\r\n/**\r\n * The source event target.\r\n * @type {Object|goog.events.Listenable|goog.events.EventTarget}\r\n */\r\ngoog.events.ListenableKey.prototype.src;\r\n\r\n\r\n/**\r\n * The event type the listener is listening to.\r\n * @type {string}\r\n */\r\ngoog.events.ListenableKey.prototype.type;\r\n\r\n\r\n/**\r\n * The listener function.\r\n * @type {function(?):?|{handleEvent:function(?):?}|null}\r\n */\r\ngoog.events.ListenableKey.prototype.listener;\r\n\r\n\r\n/**\r\n * Whether the listener works on capture phase.\r\n * @type {boolean}\r\n */\r\ngoog.events.ListenableKey.prototype.capture;\r\n\r\n\r\n/**\r\n * The 'this' object for the listener function's scope.\r\n * @type {Object|undefined}\r\n */\r\ngoog.events.ListenableKey.prototype.handler;\r\n\r\n\r\n/**\r\n * A globally unique number to identify the key.\r\n * @type {number}\r\n */\r\ngoog.events.ListenableKey.prototype.key;\r\n","// Copyright 2005 The Closure Library Authors. All Rights Reserved.\r\n//\r\n// Licensed under the Apache License, Version 2.0 (the \"License\");\r\n// you may not use this file except in compliance with the License.\r\n// You may obtain a copy of the License at\r\n//\r\n// http://www.apache.org/licenses/LICENSE-2.0\r\n//\r\n// Unless required by applicable law or agreed to in writing, software\r\n// distributed under the License is distributed on an \"AS-IS\" BASIS,\r\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n// See the License for the specific language governing permissions and\r\n// limitations under the License.\r\n\r\n/**\r\n * @fileoverview Listener object.\r\n * @see ../demos/events.html\r\n */\r\n\r\ngoog.provide('goog.events.Listener');\r\n\r\ngoog.require('goog.events.ListenableKey');\r\n\r\n\r\n\r\n/**\r\n * Simple class that stores information about a listener\r\n * @param {function(?):?} listener Callback function.\r\n * @param {Function} proxy Wrapper for the listener that patches the event.\r\n * @param {EventTarget|goog.events.Listenable} src Source object for\r\n * the event.\r\n * @param {string} type Event type.\r\n * @param {boolean} capture Whether in capture or bubble phase.\r\n * @param {Object=} opt_handler Object in whose context to execute the callback.\r\n * @implements {goog.events.ListenableKey}\r\n * @constructor\r\n */\r\ngoog.events.Listener = function(\r\n listener, proxy, src, type, capture, opt_handler) {\r\n if (goog.events.Listener.ENABLE_MONITORING) {\r\n this.creationStack = new Error().stack;\r\n }\r\n\r\n /** @override */\r\n this.listener = listener;\r\n\r\n /**\r\n * A wrapper over the original listener. This is used solely to\r\n * handle native browser events (it is used to simulate the capture\r\n * phase and to patch the event object).\r\n * @type {Function}\r\n */\r\n this.proxy = proxy;\r\n\r\n /**\r\n * Object or node that callback is listening to\r\n * @type {EventTarget|goog.events.Listenable}\r\n */\r\n this.src = src;\r\n\r\n /**\r\n * The event type.\r\n * @const {string}\r\n */\r\n this.type = type;\r\n\r\n /**\r\n * Whether the listener is being called in the capture or bubble phase\r\n * @const {boolean}\r\n */\r\n this.capture = !!capture;\r\n\r\n /**\r\n * Optional object whose context to execute the listener in\r\n * @type {Object|undefined}\r\n */\r\n this.handler = opt_handler;\r\n\r\n /**\r\n * The key of the listener.\r\n * @const {number}\r\n * @override\r\n */\r\n this.key = goog.events.ListenableKey.reserveKey();\r\n\r\n /**\r\n * Whether to remove the listener after it has been called.\r\n * @type {boolean}\r\n */\r\n this.callOnce = false;\r\n\r\n /**\r\n * Whether the listener has been removed.\r\n * @type {boolean}\r\n */\r\n this.removed = false;\r\n};\r\n\r\n\r\n/**\r\n * @define {boolean} Whether to enable the monitoring of the\r\n * goog.events.Listener instances. Switching on the monitoring is only\r\n * recommended for debugging because it has a significant impact on\r\n * performance and memory usage. If switched off, the monitoring code\r\n * compiles down to 0 bytes.\r\n */\r\ngoog.events.Listener.ENABLE_MONITORING =\r\n goog.define('goog.events.Listener.ENABLE_MONITORING', false);\r\n\r\n\r\n/**\r\n * If monitoring the goog.events.Listener instances is enabled, stores the\r\n * creation stack trace of the Disposable instance.\r\n * @type {string}\r\n */\r\ngoog.events.Listener.prototype.creationStack;\r\n\r\n\r\n/**\r\n * Marks this listener as removed. This also remove references held by\r\n * this listener object (such as listener and event source).\r\n */\r\ngoog.events.Listener.prototype.markAsRemoved = function() {\r\n this.removed = true;\r\n this.listener = null;\r\n this.proxy = null;\r\n this.src = null;\r\n this.handler = null;\r\n};\r\n","// Copyright 2013 The Closure Library Authors. All Rights Reserved.\r\n//\r\n// Licensed under the Apache License, Version 2.0 (the \"License\");\r\n// you may not use this file except in compliance with the License.\r\n// You may obtain a copy of the License at\r\n//\r\n// http://www.apache.org/licenses/LICENSE-2.0\r\n//\r\n// Unless required by applicable law or agreed to in writing, software\r\n// distributed under the License is distributed on an \"AS-IS\" BASIS,\r\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n// See the License for the specific language governing permissions and\r\n// limitations under the License.\r\n\r\n/**\r\n * @fileoverview A map of listeners that provides utility functions to\r\n * deal with listeners on an event target. Used by\r\n * `goog.events.EventTarget`.\r\n *\r\n * WARNING: Do not use this class from outside goog.events package.\r\n */\r\n\r\ngoog.provide('goog.events.ListenerMap');\r\n\r\ngoog.require('goog.array');\r\ngoog.require('goog.events.Listener');\r\ngoog.require('goog.object');\r\n\r\n\r\n\r\n/**\r\n * Creates a new listener map.\r\n * @param {EventTarget|goog.events.Listenable} src The src object.\r\n * @constructor\r\n * @final\r\n */\r\ngoog.events.ListenerMap = function(src) {\r\n /** @type {EventTarget|goog.events.Listenable} */\r\n this.src = src;\r\n\r\n /**\r\n * Maps of event type to an array of listeners.\r\n * @type {!Object<string, !Array<!goog.events.Listener>>}\r\n */\r\n this.listeners = {};\r\n\r\n /**\r\n * The count of types in this map that have registered listeners.\r\n * @private {number}\r\n */\r\n this.typeCount_ = 0;\r\n};\r\n\r\n\r\n/**\r\n * @return {number} The count of event types in this map that actually\r\n * have registered listeners.\r\n */\r\ngoog.events.ListenerMap.prototype.getTypeCount = function() {\r\n return this.typeCount_;\r\n};\r\n\r\n\r\n/**\r\n * @return {number} Total number of registered listeners.\r\n */\r\ngoog.events.ListenerMap.prototype.getListenerCount = function() {\r\n var count = 0;\r\n for (var type in this.listeners) {\r\n count += this.listeners[type].length;\r\n }\r\n return count;\r\n};\r\n\r\n\r\n/**\r\n * Adds an event listener. A listener can only be added once to an\r\n * object and if it is added again the key for the listener is\r\n * returned.\r\n *\r\n * Note that a one-off listener will not change an existing listener,\r\n * if any. On the other hand a normal listener will change existing\r\n * one-off listener to become a normal listener.\r\n *\r\n * @param {string|!goog.events.EventId} type The listener event type.\r\n * @param {!Function} listener This listener callback method.\r\n * @param {boolean} callOnce Whether the listener is a one-off\r\n * listener.\r\n * @param {boolean=} opt_useCapture The capture mode of the listener.\r\n * @param {Object=} opt_listenerScope Object in whose scope to call the\r\n * listener.\r\n * @return {!goog.events.ListenableKey} Unique key for the listener.\r\n */\r\ngoog.events.ListenerMap.prototype.add = function(\r\n type, listener, callOnce, opt_useCapture, opt_listenerScope) {\r\n var typeStr = type.toString();\r\n var listenerArray = this.listeners[typeStr];\r\n if (!listenerArray) {\r\n listenerArray = this.listeners[typeStr] = [];\r\n this.typeCount_++;\r\n }\r\n\r\n var listenerObj;\r\n var index = goog.events.ListenerMap.findListenerIndex_(\r\n listenerArray, listener, opt_useCapture, opt_listenerScope);\r\n if (index > -1) {\r\n listenerObj = listenerArray[index];\r\n if (!callOnce) {\r\n // Ensure that, if there is an existing callOnce listener, it is no\r\n // longer a callOnce listener.\r\n listenerObj.callOnce = false;\r\n }\r\n } else {\r\n listenerObj = new goog.events.Listener(\r\n listener, null, this.src, typeStr, !!opt_useCapture, opt_listenerScope);\r\n listenerObj.callOnce = callOnce;\r\n listenerArray.push(listenerObj);\r\n }\r\n return listenerObj;\r\n};\r\n\r\n\r\n/**\r\n * Removes a matching listener.\r\n * @param {string|!goog.events.EventId} type The listener event type.\r\n * @param {!Function} listener This listener callback method.\r\n * @param {boolean=} opt_useCapture The capture mode of the listener.\r\n * @param {Object=} opt_listenerScope Object in whose scope to call the\r\n * listener.\r\n * @return {boolean} Whether any listener was removed.\r\n */\r\ngoog.events.ListenerMap.prototype.remove = function(\r\n type, listener, opt_useCapture, opt_listenerScope) {\r\n var typeStr = type.toString();\r\n if (!(typeStr in this.listeners)) {\r\n return false;\r\n }\r\n\r\n var listenerArray = this.listeners[typeStr];\r\n var index = goog.events.ListenerMap.findListenerIndex_(\r\n listenerArray, listener, opt_useCapture, opt_listenerScope);\r\n if (index > -1) {\r\n var listenerObj = listenerArray[index];\r\n listenerObj.markAsRemoved();\r\n goog.array.removeAt(listenerArray, index);\r\n if (listenerArray.length == 0) {\r\n delete this.listeners[typeStr];\r\n this.typeCount_--;\r\n }\r\n return true;\r\n }\r\n return false;\r\n};\r\n\r\n\r\n/**\r\n * Removes the given listener object.\r\n * @param {!goog.events.ListenableKey} listener The listener to remove.\r\n * @return {boolean} Whether the listener is removed.\r\n */\r\ngoog.events.ListenerMap.prototype.removeByKey = function(listener) {\r\n var type = listener.type;\r\n if (!(type in this.listeners)) {\r\n return false;\r\n }\r\n\r\n var removed = goog.array.remove(this.listeners[type], listener);\r\n if (removed) {\r\n /** @type {!goog.events.Listener} */ (listener).markAsRemoved();\r\n if (this.listeners[type].length == 0) {\r\n delete this.listeners[type];\r\n this.typeCount_--;\r\n }\r\n }\r\n return removed;\r\n};\r\n\r\n\r\n/**\r\n * Removes all listeners from this map. If opt_type is provided, only\r\n * listeners that match the given type are removed.\r\n * @param {string|!goog.events.EventId=} opt_type Type of event to remove.\r\n * @return {number} Number of listeners removed.\r\n */\r\ngoog.events.ListenerMap.prototype.removeAll = function(opt_type) {\r\n var typeStr = opt_type && opt_type.toString();\r\n var count = 0;\r\n for (var type in this.listeners) {\r\n if (!typeStr || type == typeStr) {\r\n var listenerArray = this.listeners[type];\r\n for (var i = 0; i < listenerArray.length; i++) {\r\n ++count;\r\n listenerArray[i].markAsRemoved();\r\n }\r\n delete this.listeners[type];\r\n this.typeCount_--;\r\n }\r\n }\r\n return count;\r\n};\r\n\r\n\r\n/**\r\n * Gets all listeners that match the given type and capture mode. The\r\n * returned array is a copy (but the listener objects are not).\r\n * @param {string|!goog.events.EventId} type The type of the listeners\r\n * to retrieve.\r\n * @param {boolean} capture The capture mode of the listeners to retrieve.\r\n * @return {!Array<!goog.events.ListenableKey>} An array of matching\r\n * listeners.\r\n */\r\ngoog.events.ListenerMap.prototype.getListeners = function(type, capture) {\r\n var listenerArray = this.listeners[type.toString()];\r\n var rv = [];\r\n if (listenerArray) {\r\n for (var i = 0; i < listenerArray.length; ++i) {\r\n var listenerObj = listenerArray[i];\r\n if (listenerObj.capture == capture) {\r\n rv.push(listenerObj);\r\n }\r\n }\r\n }\r\n return rv;\r\n};\r\n\r\n\r\n/**\r\n * Gets the goog.events.ListenableKey for the event or null if no such\r\n * listener is in use.\r\n *\r\n * @param {string|!goog.events.EventId} type The type of the listener\r\n * to retrieve.\r\n * @param {!Function} listener The listener function to get.\r\n * @param {boolean} capture Whether the listener is a capturing listener.\r\n * @param {Object=} opt_listenerScope Object in whose scope to call the\r\n * listener.\r\n * @return {goog.events.ListenableKey} the found listener or null if not found.\r\n */\r\ngoog.events.ListenerMap.prototype.getListener = function(\r\n type, listener, capture, opt_listenerScope) {\r\n var listenerArray = this.listeners[type.toString()];\r\n var i = -1;\r\n if (listenerArray) {\r\n i = goog.events.ListenerMap.findListenerIndex_(\r\n listenerArray, listener, capture, opt_listenerScope);\r\n }\r\n return i > -1 ? listenerArray[i] : null;\r\n};\r\n\r\n\r\n/**\r\n * Whether there is a matching listener. If either the type or capture\r\n * parameters are unspecified, the function will match on the\r\n * remaining criteria.\r\n *\r\n * @param {string|!goog.events.EventId=} opt_type The type of the listener.\r\n * @param {boolean=} opt_capture The capture mode of the listener.\r\n * @return {boolean} Whether there is an active listener matching\r\n * the requested type and/or capture phase.\r\n */\r\ngoog.events.ListenerMap.prototype.hasListener = function(\r\n opt_type, opt_capture) {\r\n var hasType = goog.isDef(opt_type);\r\n var typeStr = hasType ? opt_type.toString() : '';\r\n var hasCapture = goog.isDef(opt_capture);\r\n\r\n return goog.object.some(this.listeners, function(listenerArray, type) {\r\n for (var i = 0; i < listenerArray.length; ++i) {\r\n if ((!hasType || listenerArray[i].type == typeStr) &&\r\n (!hasCapture || listenerArray[i].capture == opt_capture)) {\r\n return true;\r\n }\r\n }\r\n\r\n return false;\r\n });\r\n};\r\n\r\n\r\n/**\r\n * Finds the index of a matching goog.events.Listener in the given\r\n * listenerArray.\r\n * @param {!Array<!goog.events.Listener>} listenerArray Array of listener.\r\n * @param {!Function} listener The listener function.\r\n * @param {boolean=} opt_useCapture The capture flag for the listener.\r\n * @param {Object=} opt_listenerScope The listener scope.\r\n * @return {number} The index of the matching listener within the\r\n * listenerArray.\r\n * @private\r\n */\r\ngoog.events.ListenerMap.findListenerIndex_ = function(\r\n listenerArray, listener, opt_useCapture, opt_listenerScope) {\r\n for (var i = 0; i < listenerArray.length; ++i) {\r\n var listenerObj = listenerArray[i];\r\n if (!listenerObj.removed && listenerObj.listener == listener &&\r\n listenerObj.capture == !!opt_useCapture &&\r\n listenerObj.handler == opt_listenerScope) {\r\n return i;\r\n }\r\n }\r\n return -1;\r\n};\r\n","// Copyright 2005 The Closure Library Authors. All Rights Reserved.\r\n//\r\n// Licensed under the Apache License, Version 2.0 (the \"License\");\r\n// you may not use this file except in compliance with the License.\r\n// You may obtain a copy of the License at\r\n//\r\n// http://www.apache.org/licenses/LICENSE-2.0\r\n//\r\n// Unless required by applicable law or agreed to in writing, software\r\n// distributed under the License is distributed on an \"AS-IS\" BASIS,\r\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n// See the License for the specific language governing permissions and\r\n// limitations under the License.\r\n\r\n/**\r\n * @fileoverview An event manager for both native browser event\r\n * targets and custom JavaScript event targets\r\n * (`goog.events.Listenable`). This provides an abstraction\r\n * over browsers' event systems.\r\n *\r\n * It also provides a simulation of W3C event model's capture phase in\r\n * Internet Explorer (IE 8 and below). Caveat: the simulation does not\r\n * interact well with listeners registered directly on the elements\r\n * (bypassing goog.events) or even with listeners registered via\r\n * goog.events in a separate JS binary. In these cases, we provide\r\n * no ordering guarantees.\r\n *\r\n * The listeners will receive a \"patched\" event object. Such event object\r\n * contains normalized values for certain event properties that differs in\r\n * different browsers.\r\n *\r\n * Example usage:\r\n * <pre>\r\n * goog.events.listen(myNode, 'click', function(e) { alert('woo') });\r\n * goog.events.listen(myNode, 'mouseover', mouseHandler, true);\r\n * goog.events.unlisten(myNode, 'mouseover', mouseHandler, true);\r\n * goog.events.removeAll(myNode);\r\n * </pre>\r\n *\r\n * in IE and event object patching]\r\n * @author arv@google.com (Erik Arvidsson)\r\n *\r\n * @see ../demos/events.html\r\n * @see ../demos/event-propagation.html\r\n * @see ../demos/stopevent.html\r\n */\r\n\r\n// IMPLEMENTATION NOTES:\r\n// goog.events stores an auxiliary data structure on each EventTarget\r\n// source being listened on. This allows us to take advantage of GC,\r\n// having the data structure GC'd when the EventTarget is GC'd. This\r\n// GC behavior is equivalent to using W3C DOM Events directly.\r\n\r\ngoog.provide('goog.events');\r\ngoog.provide('goog.events.CaptureSimulationMode');\r\ngoog.provide('goog.events.Key');\r\ngoog.provide('goog.events.ListenableType');\r\n\r\ngoog.require('goog.asserts');\r\ngoog.require('goog.debug.entryPointRegistry');\r\ngoog.require('goog.events.BrowserEvent');\r\ngoog.require('goog.events.BrowserFeature');\r\ngoog.require('goog.events.Listenable');\r\ngoog.require('goog.events.ListenerMap');\r\n\r\ngoog.forwardDeclare('goog.debug.ErrorHandler');\r\ngoog.forwardDeclare('goog.events.EventWrapper');\r\n\r\n\r\n/**\r\n * @typedef {number|goog.events.ListenableKey}\r\n */\r\ngoog.events.Key;\r\n\r\n\r\n/**\r\n * @typedef {EventTarget|goog.events.Listenable}\r\n */\r\ngoog.events.ListenableType;\r\n\r\n\r\n/**\r\n * Property name on a native event target for the listener map\r\n * associated with the event target.\r\n * @private @const {string}\r\n */\r\ngoog.events.LISTENER_MAP_PROP_ = 'closure_lm_' + ((Math.random() * 1e6) | 0);\r\n\r\n\r\n/**\r\n * String used to prepend to IE event types.\r\n * @const\r\n * @private\r\n */\r\ngoog.events.onString_ = 'on';\r\n\r\n\r\n/**\r\n * Map of computed \"on<eventname>\" strings for IE event types. Caching\r\n * this removes an extra object allocation in goog.events.listen which\r\n * improves IE6 performance.\r\n * @const\r\n * @dict\r\n * @private\r\n */\r\ngoog.events.onStringMap_ = {};\r\n\r\n\r\n/**\r\n * @enum {number} Different capture simulation mode for IE8-.\r\n */\r\ngoog.events.CaptureSimulationMode = {\r\n /**\r\n * Does not perform capture simulation. Will asserts in IE8- when you\r\n * add capture listeners.\r\n */\r\n OFF_AND_FAIL: 0,\r\n\r\n /**\r\n * Does not perform capture simulation, silently ignore capture\r\n * listeners.\r\n */\r\n OFF_AND_SILENT: 1,\r\n\r\n /**\r\n * Performs capture simulation.\r\n */\r\n ON: 2\r\n};\r\n\r\n\r\n/**\r\n * @define {number} The capture simulation mode for IE8-. By default,\r\n * this is ON.\r\n */\r\ngoog.events.CAPTURE_SIMULATION_MODE =\r\n goog.define('goog.events.CAPTURE_SIMULATION_MODE', 2);\r\n\r\n\r\n/**\r\n * Estimated count of total native listeners.\r\n * @private {number}\r\n */\r\ngoog.events.listenerCountEstimate_ = 0;\r\n\r\n\r\n/**\r\n * Adds an event listener for a specific event on a native event\r\n * target (such as a DOM element) or an object that has implemented\r\n * {@link goog.events.Listenable}. A listener can only be added once\r\n * to an object and if it is added again the key for the listener is\r\n * returned. Note that if the existing listener is a one-off listener\r\n * (registered via listenOnce), it will no longer be a one-off\r\n * listener after a call to listen().\r\n *\r\n * @param {EventTarget|goog.events.Listenable} src The node to listen\r\n * to events on.\r\n * @param {string|Array<string>|\r\n * !goog.events.EventId<EVENTOBJ>|!Array<!goog.events.EventId<EVENTOBJ>>}\r\n * type Event type or array of event types.\r\n * @param {function(this:T, EVENTOBJ):?|{handleEvent:function(?):?}|null}\r\n * listener Callback method, or an object with a handleEvent function.\r\n * WARNING: passing an Object is now softly deprecated.\r\n * @param {(boolean|!AddEventListenerOptions)=} opt_options\r\n * @param {T=} opt_handler Element in whose scope to call the listener.\r\n * @return {goog.events.Key} Unique key for the listener.\r\n * @template T,EVENTOBJ\r\n */\r\ngoog.events.listen = function(src, type, listener, opt_options, opt_handler) {\r\n if (opt_options && opt_options.once) {\r\n return goog.events.listenOnce(\r\n src, type, listener, opt_options, opt_handler);\r\n }\r\n if (goog.isArray(type)) {\r\n for (var i = 0; i < type.length; i++) {\r\n goog.events.listen(src, type[i], listener, opt_options, opt_handler);\r\n }\r\n return null;\r\n }\r\n\r\n listener = goog.events.wrapListener(listener);\r\n if (goog.events.Listenable.isImplementedBy(src)) {\r\n var capture =\r\n goog.isObject(opt_options) ? !!opt_options.capture : !!opt_options;\r\n return src.listen(\r\n /** @type {string|!goog.events.EventId} */ (type), listener, capture,\r\n opt_handler);\r\n } else {\r\n return goog.events.listen_(\r\n /** @type {!EventTarget} */ (src), type, listener,\r\n /* callOnce */ false, opt_options, opt_handler);\r\n }\r\n};\r\n\r\n\r\n/**\r\n * Adds an event listener for a specific event on a native event\r\n * target. A listener can only be added once to an object and if it\r\n * is added again the key for the listener is returned.\r\n *\r\n * Note that a one-off listener will not change an existing listener,\r\n * if any. On the other hand a normal listener will change existing\r\n * one-off listener to become a normal listener.\r\n *\r\n * @param {EventTarget} src The node to listen to events on.\r\n * @param {string|?goog.events.EventId<EVENTOBJ>} type Event type.\r\n * @param {!Function} listener Callback function.\r\n * @param {boolean} callOnce Whether the listener is a one-off\r\n * listener or otherwise.\r\n * @param {(boolean|!AddEventListenerOptions)=} opt_options\r\n * @param {Object=} opt_handler Element in whose scope to call the listener.\r\n * @return {goog.events.ListenableKey} Unique key for the listener.\r\n * @template EVENTOBJ\r\n * @private\r\n */\r\ngoog.events.listen_ = function(\r\n src, type, listener, callOnce, opt_options, opt_handler) {\r\n if (!type) {\r\n throw new Error('Invalid event type');\r\n }\r\n\r\n var capture =\r\n goog.isObject(opt_options) ? !!opt_options.capture : !!opt_options;\r\n if (capture && !goog.events.BrowserFeature.HAS_W3C_EVENT_SUPPORT) {\r\n if (goog.events.CAPTURE_SIMULATION_MODE ==\r\n goog.events.CaptureSimulationMode.OFF_AND_FAIL) {\r\n goog.asserts.fail('Can not register capture listener in IE8-.');\r\n return null;\r\n } else if (\r\n goog.events.CAPTURE_SIMULATION_MODE ==\r\n goog.events.CaptureSimulationMode.OFF_AND_SILENT) {\r\n return null;\r\n }\r\n }\r\n\r\n var listenerMap = goog.events.getListenerMap_(src);\r\n if (!listenerMap) {\r\n src[goog.events.LISTENER_MAP_PROP_] = listenerMap =\r\n new goog.events.ListenerMap(src);\r\n }\r\n\r\n var listenerObj = /** @type {goog.events.Listener} */ (\r\n listenerMap.add(type, listener, callOnce, capture, opt_handler));\r\n\r\n // If the listenerObj already has a proxy, it has been set up\r\n // previously. We simply return.\r\n if (listenerObj.proxy) {\r\n return listenerObj;\r\n }\r\n\r\n var proxy = goog.events.getProxy();\r\n listenerObj.proxy = proxy;\r\n\r\n proxy.src = src;\r\n proxy.listener = listenerObj;\r\n\r\n // Attach the proxy through the browser's API\r\n if (src.addEventListener) {\r\n // Don't pass an object as `capture` if the browser doesn't support that.\r\n if (!goog.events.BrowserFeature.PASSIVE_EVENTS) {\r\n opt_options = capture;\r\n }\r\n // Don't break tests that expect a boolean.\r\n if (opt_options === undefined) opt_options = false;\r\n src.addEventListener(type.toString(), proxy, opt_options);\r\n } else if (src.attachEvent) {\r\n // The else if above used to be an unconditional else. It would call\r\n // exception on IE11, spoiling the day of some callers. The previous\r\n // incarnation of this code, from 2007, indicates that it replaced an\r\n // earlier still version that caused excess allocations on IE6.\r\n src.attachEvent(goog.events.getOnString_(type.toString()), proxy);\r\n } else if (src.addListener && src.removeListener) {\r\n // In IE, MediaQueryList uses addListener() insteadd of addEventListener. In\r\n // Safari, there is no global for the MediaQueryList constructor, so we just\r\n // check whether the object \"looks like\" MediaQueryList.\r\n goog.asserts.assert(\r\n type === 'change', 'MediaQueryList only has a change event');\r\n src.addListener(proxy);\r\n } else {\r\n throw new Error('addEventListener and attachEvent are unavailable.');\r\n }\r\n\r\n goog.events.listenerCountEstimate_++;\r\n return listenerObj;\r\n};\r\n\r\n\r\n/**\r\n * Helper function for returning a proxy function.\r\n * @return {!Function} A new or reused function object.\r\n */\r\ngoog.events.getProxy = function() {\r\n var proxyCallbackFunction = goog.events.handleBrowserEvent_;\r\n // Use a local var f to prevent one allocation.\r\n var f =\r\n goog.events.BrowserFeature.HAS_W3C_EVENT_SUPPORT ? function(eventObject) {\r\n return proxyCallbackFunction.call(f.src, f.listener, eventObject);\r\n } : function(eventObject) {\r\n var v = proxyCallbackFunction.call(f.src, f.listener, eventObject);\r\n // NOTE(chrishenry): In IE, we hack in a capture phase. However, if\r\n // there is inline event handler which tries to prevent default (for\r\n // example <a href=\"...\" onclick=\"return false\">...</a>) in a\r\n // descendant element, the prevent default will be overridden\r\n // by this listener if this listener were to return true. Hence, we\r\n // return undefined.\r\n if (!v) return v;\r\n };\r\n return f;\r\n};\r\n\r\n\r\n/**\r\n * Adds an event listener for a specific event on a native event\r\n * target (such as a DOM element) or an object that has implemented\r\n * {@link goog.events.Listenable}. After the event has fired the event\r\n * listener is removed from the target.\r\n *\r\n * If an existing listener already exists, listenOnce will do\r\n * nothing. In particular, if the listener was previously registered\r\n * via listen(), listenOnce() will not turn the listener into a\r\n * one-off listener. Similarly, if there is already an existing\r\n * one-off listener, listenOnce does not modify the listeners (it is\r\n * still a once listener).\r\n *\r\n * @param {EventTarget|goog.events.Listenable} src The node to listen\r\n * to events on.\r\n * @param {string|Array<string>|\r\n * !goog.events.EventId<EVENTOBJ>|!Array<!goog.events.EventId<EVENTOBJ>>}\r\n * type Event type or array of event types.\r\n * @param {function(this:T, EVENTOBJ):?|{handleEvent:function(?):?}|null}\r\n * listener Callback method.\r\n * @param {(boolean|!AddEventListenerOptions)=} opt_options\r\n * @param {T=} opt_handler Element in whose scope to call the listener.\r\n * @return {goog.events.Key} Unique key for the listener.\r\n * @template T,EVENTOBJ\r\n */\r\ngoog.events.listenOnce = function(\r\n src, type, listener, opt_options, opt_handler) {\r\n if (goog.isArray(type)) {\r\n for (var i = 0; i < type.length; i++) {\r\n goog.events.listenOnce(src, type[i], listener, opt_options, opt_handler);\r\n }\r\n return null;\r\n }\r\n\r\n listener = goog.events.wrapListener(listener);\r\n if (goog.events.Listenable.isImplementedBy(src)) {\r\n var capture =\r\n goog.isObject(opt_options) ? !!opt_options.capture : !!opt_options;\r\n return src.listenOnce(\r\n /** @type {string|!goog.events.EventId} */ (type), listener, capture,\r\n opt_handler);\r\n } else {\r\n return goog.events.listen_(\r\n /** @type {!EventTarget} */ (src), type, listener,\r\n /* callOnce */ true, opt_options, opt_handler);\r\n }\r\n};\r\n\r\n\r\n/**\r\n * Adds an event listener with a specific event wrapper on a DOM Node or an\r\n * object that has implemented {@link goog.events.Listenable}. A listener can\r\n * only be added once to an object.\r\n *\r\n * @param {EventTarget|goog.events.Listenable} src The target to\r\n * listen to events on.\r\n * @param {goog.events.EventWrapper} wrapper Event wrapper to use.\r\n * @param {function(this:T, ?):?|{handleEvent:function(?):?}|null} listener\r\n * Callback method, or an object with a handleEvent function.\r\n * @param {boolean=} opt_capt Whether to fire in capture phase (defaults to\r\n * false).\r\n * @param {T=} opt_handler Element in whose scope to call the listener.\r\n * @template T\r\n */\r\ngoog.events.listenWithWrapper = function(\r\n src, wrapper, listener, opt_capt, opt_handler) {\r\n wrapper.listen(src, listener, opt_capt, opt_handler);\r\n};\r\n\r\n\r\n/**\r\n * Removes an event listener which was added with listen().\r\n *\r\n * @param {EventTarget|goog.events.Listenable} src The target to stop\r\n * listening to events on.\r\n * @param {string|Array<string>|\r\n * !goog.events.EventId<EVENTOBJ>|!Array<!goog.events.EventId<EVENTOBJ>>}\r\n * type Event type or array of event types to unlisten to.\r\n * @param {function(?):?|{handleEvent:function(?):?}|null} listener The\r\n * listener function to remove.\r\n * @param {(boolean|!EventListenerOptions)=} opt_options\r\n * whether the listener is fired during the capture or bubble phase of the\r\n * event.\r\n * @param {Object=} opt_handler Element in whose scope to call the listener.\r\n * @return {?boolean} indicating whether the listener was there to remove.\r\n * @template EVENTOBJ\r\n */\r\ngoog.events.unlisten = function(src, type, listener, opt_options, opt_handler) {\r\n if (goog.isArray(type)) {\r\n for (var i = 0; i < type.length; i++) {\r\n goog.events.unlisten(src, type[i], listener, opt_options, opt_handler);\r\n }\r\n return null;\r\n }\r\n var capture =\r\n goog.isObject(opt_options) ? !!opt_options.capture : !!opt_options;\r\n\r\n listener = goog.events.wrapListener(listener);\r\n if (goog.events.Listenable.isImplementedBy(src)) {\r\n return src.unlisten(\r\n /** @type {string|!goog.events.EventId} */ (type), listener, capture,\r\n opt_handler);\r\n }\r\n\r\n if (!src) {\r\n // TODO(chrishenry): We should tighten the API to only accept\r\n // non-null objects, or add an assertion here.\r\n return false;\r\n }\r\n\r\n var listenerMap = goog.events.getListenerMap_(\r\n /** @type {!EventTarget} */ (src));\r\n if (listenerMap) {\r\n var listenerObj = listenerMap.getListener(\r\n /** @type {string|!goog.events.EventId} */ (type), listener, capture,\r\n opt_handler);\r\n if (listenerObj) {\r\n return goog.events.unlistenByKey(listenerObj);\r\n }\r\n }\r\n\r\n return false;\r\n};\r\n\r\n\r\n/**\r\n * Removes an event listener which was added with listen() by the key\r\n * returned by listen().\r\n *\r\n * @param {goog.events.Key} key The key returned by listen() for this\r\n * event listener.\r\n * @return {boolean} indicating whether the listener was there to remove.\r\n */\r\ngoog.events.unlistenByKey = function(key) {\r\n // TODO(chrishenry): Remove this check when tests that rely on this\r\n // are fixed.\r\n if (goog.isNumber(key)) {\r\n return false;\r\n }\r\n\r\n var listener = key;\r\n if (!listener || listener.removed) {\r\n return false;\r\n }\r\n\r\n var src = listener.src;\r\n if (goog.events.Listenable.isImplementedBy(src)) {\r\n return /** @type {!goog.events.Listenable} */ (src).unlistenByKey(listener);\r\n }\r\n\r\n var type = listener.type;\r\n var proxy = listener.proxy;\r\n if (src.removeEventListener) {\r\n src.removeEventListener(type, proxy, listener.capture);\r\n } else if (src.detachEvent) {\r\n src.detachEvent(goog.events.getOnString_(type), proxy);\r\n } else if (src.addListener && src.removeListener) {\r\n src.removeListener(proxy);\r\n }\r\n goog.events.listenerCountEstimate_--;\r\n\r\n var listenerMap = goog.events.getListenerMap_(\r\n /** @type {!EventTarget} */ (src));\r\n // TODO(chrishenry): Try to remove this conditional and execute the\r\n // first branch always. This should be safe.\r\n if (listenerMap) {\r\n listenerMap.removeByKey(listener);\r\n if (listenerMap.getTypeCount() == 0) {\r\n // Null the src, just because this is simple to do (and useful\r\n // for IE <= 7).\r\n listenerMap.src = null;\r\n // We don't use delete here because IE does not allow delete\r\n // on a window object.\r\n src[goog.events.LISTENER_MAP_PROP_] = null;\r\n }\r\n } else {\r\n /** @type {!goog.events.Listener} */ (listener).markAsRemoved();\r\n }\r\n\r\n return true;\r\n};\r\n\r\n\r\n/**\r\n * Removes an event listener which was added with listenWithWrapper().\r\n *\r\n * @param {EventTarget|goog.events.Listenable} src The target to stop\r\n * listening to events on.\r\n * @param {goog.events.EventWrapper} wrapper Event wrapper to use.\r\n * @param {function(?):?|{handleEvent:function(?):?}|null} listener The\r\n * listener function to remove.\r\n * @param {boolean=} opt_capt In DOM-compliant browsers, this determines\r\n * whether the listener is fired during the capture or bubble phase of the\r\n * event.\r\n * @param {Object=} opt_handler Element in whose scope to call the listener.\r\n */\r\ngoog.events.unlistenWithWrapper = function(\r\n src, wrapper, listener, opt_capt, opt_handler) {\r\n wrapper.unlisten(src, listener, opt_capt, opt_handler);\r\n};\r\n\r\n\r\n/**\r\n * Removes all listeners from an object. You can also optionally\r\n * remove listeners of a particular type.\r\n *\r\n * @param {Object|undefined} obj Object to remove listeners from. Must be an\r\n * EventTarget or a goog.events.Listenable.\r\n * @param {string|!goog.events.EventId=} opt_type Type of event to remove.\r\n * Default is all types.\r\n * @return {number} Number of listeners removed.\r\n */\r\ngoog.events.removeAll = function(obj, opt_type) {\r\n // TODO(chrishenry): Change the type of obj to\r\n // (!EventTarget|!goog.events.Listenable).\r\n\r\n if (!obj) {\r\n return 0;\r\n }\r\n\r\n if (goog.events.Listenable.isImplementedBy(obj)) {\r\n return /** @type {?} */ (obj).removeAllListeners(opt_type);\r\n }\r\n\r\n var listenerMap = goog.events.getListenerMap_(\r\n /** @type {!EventTarget} */ (obj));\r\n if (!listenerMap) {\r\n return 0;\r\n }\r\n\r\n var count = 0;\r\n var typeStr = opt_type && opt_type.toString();\r\n for (var type in listenerMap.listeners) {\r\n if (!typeStr || type == typeStr) {\r\n // Clone so that we don't need to worry about unlistenByKey\r\n // changing the content of the ListenerMap.\r\n var listeners = listenerMap.listeners[type].concat();\r\n for (var i = 0; i < listeners.length; ++i) {\r\n if (goog.events.unlistenByKey(listeners[i])) {\r\n ++count;\r\n }\r\n }\r\n }\r\n }\r\n return count;\r\n};\r\n\r\n\r\n/**\r\n * Gets the listeners for a given object, type and capture phase.\r\n *\r\n * @param {Object} obj Object to get listeners for.\r\n * @param {string|!goog.events.EventId} type Event type.\r\n * @param {boolean} capture Capture phase?.\r\n * @return {Array<!goog.events.Listener>} Array of listener objects.\r\n */\r\ngoog.events.getListeners = function(obj, type, capture) {\r\n if (goog.events.Listenable.isImplementedBy(obj)) {\r\n return /** @type {!goog.events.Listenable} */ (obj).getListeners(\r\n type, capture);\r\n } else {\r\n if (!obj) {\r\n // TODO(chrishenry): We should tighten the API to accept\r\n // !EventTarget|goog.events.Listenable, and add an assertion here.\r\n return [];\r\n }\r\n\r\n var listenerMap = goog.events.getListenerMap_(\r\n /** @type {!EventTarget} */ (obj));\r\n return listenerMap ? listenerMap.getListeners(type, capture) : [];\r\n }\r\n};\r\n\r\n\r\n/**\r\n * Gets the goog.events.Listener for the event or null if no such listener is\r\n * in use.\r\n *\r\n * @param {EventTarget|goog.events.Listenable} src The target from\r\n * which to get listeners.\r\n * @param {?string|!goog.events.EventId<EVENTOBJ>} type The type of the event.\r\n * @param {function(EVENTOBJ):?|{handleEvent:function(?):?}|null} listener The\r\n * listener function to get.\r\n * @param {boolean=} opt_capt In DOM-compliant browsers, this determines\r\n * whether the listener is fired during the\r\n * capture or bubble phase of the event.\r\n * @param {Object=} opt_handler Element in whose scope to call the listener.\r\n * @return {goog.events.ListenableKey} the found listener or null if not found.\r\n * @template EVENTOBJ\r\n */\r\ngoog.events.getListener = function(src, type, listener, opt_capt, opt_handler) {\r\n // TODO(chrishenry): Change type from ?string to string, or add assertion.\r\n type = /** @type {string} */ (type);\r\n listener = goog.events.wrapListener(listener);\r\n var capture = !!opt_capt;\r\n if (goog.events.Listenable.isImplementedBy(src)) {\r\n return src.getListener(type, listener, capture, opt_handler);\r\n }\r\n\r\n if (!src) {\r\n // TODO(chrishenry): We should tighten the API to only accept\r\n // non-null objects, or add an assertion here.\r\n return null;\r\n }\r\n\r\n var listenerMap = goog.events.getListenerMap_(\r\n /** @type {!EventTarget} */ (src));\r\n if (listenerMap) {\r\n return listenerMap.getListener(type, listener, capture, opt_handler);\r\n }\r\n return null;\r\n};\r\n\r\n\r\n/**\r\n * Returns whether an event target has any active listeners matching the\r\n * specified signature. If either the type or capture parameters are\r\n * unspecified, the function will match on the remaining criteria.\r\n *\r\n * @param {EventTarget|goog.events.Listenable} obj Target to get\r\n * listeners for.\r\n * @param {string|!goog.events.EventId=} opt_type Event type.\r\n * @param {boolean=} opt_capture Whether to check for capture or bubble-phase\r\n * listeners.\r\n * @return {boolean} Whether an event target has one or more listeners matching\r\n * the requested type and/or capture phase.\r\n */\r\ngoog.events.hasListener = function(obj, opt_type, opt_capture) {\r\n if (goog.events.Listenable.isImplementedBy(obj)) {\r\n return obj.hasListener(opt_type, opt_capture);\r\n }\r\n\r\n var listenerMap = goog.events.getListenerMap_(\r\n /** @type {!EventTarget} */ (obj));\r\n return !!listenerMap && listenerMap.hasListener(opt_type, opt_capture);\r\n};\r\n\r\n\r\n/**\r\n * Provides a nice string showing the normalized event objects public members\r\n * @param {Object} e Event Object.\r\n * @return {string} String of the public members of the normalized event object.\r\n */\r\ngoog.events.expose = function(e) {\r\n var str = [];\r\n for (var key in e) {\r\n if (e[key] && e[key].id) {\r\n str.push(key + ' = ' + e[key] + ' (' + e[key].id + ')');\r\n } else {\r\n str.push(key + ' = ' + e[key]);\r\n }\r\n }\r\n return str.join('\\n');\r\n};\r\n\r\n\r\n/**\r\n * Returns a string with on prepended to the specified type. This is used for IE\r\n * which expects \"on\" to be prepended. This function caches the string in order\r\n * to avoid extra allocations in steady state.\r\n * @param {string} type Event type.\r\n * @return {string} The type string with 'on' prepended.\r\n * @private\r\n */\r\ngoog.events.getOnString_ = function(type) {\r\n if (type in goog.events.onStringMap_) {\r\n return goog.events.onStringMap_[type];\r\n }\r\n return goog.events.onStringMap_[type] = goog.events.onString_ + type;\r\n};\r\n\r\n\r\n/**\r\n * Fires an object's listeners of a particular type and phase\r\n *\r\n * @param {Object} obj Object whose listeners to call.\r\n * @param {string|!goog.events.EventId} type Event type.\r\n * @param {boolean} capture Which event phase.\r\n * @param {Object} eventObject Event object to be passed to listener.\r\n * @return {boolean} True if all listeners returned true else false.\r\n */\r\ngoog.events.fireListeners = function(obj, type, capture, eventObject) {\r\n if (goog.events.Listenable.isImplementedBy(obj)) {\r\n return /** @type {!goog.events.Listenable} */ (obj).fireListeners(\r\n type, capture, eventObject);\r\n }\r\n\r\n return goog.events.fireListeners_(obj, type, capture, eventObject);\r\n};\r\n\r\n\r\n/**\r\n * Fires an object's listeners of a particular type and phase.\r\n * @param {Object} obj Object whose listeners to call.\r\n * @param {string|!goog.events.EventId} type Event type.\r\n * @param {boolean} capture Which event phase.\r\n * @param {Object} eventObject Event object to be passed to listener.\r\n * @return {boolean} True if all listeners returned true else false.\r\n * @private\r\n */\r\ngoog.events.fireListeners_ = function(obj, type, capture, eventObject) {\r\n /** @type {boolean} */\r\n var retval = true;\r\n\r\n var listenerMap = goog.events.getListenerMap_(\r\n /** @type {EventTarget} */ (obj));\r\n if (listenerMap) {\r\n // TODO(chrishenry): Original code avoids array creation when there\r\n // is no listener, so we do the same. If this optimization turns\r\n // out to be not required, we can replace this with\r\n // listenerMap.getListeners(type, capture) instead, which is simpler.\r\n var listenerArray = listenerMap.listeners[type.toString()];\r\n if (listenerArray) {\r\n listenerArray = listenerArray.concat();\r\n for (var i = 0; i < listenerArray.length; i++) {\r\n var listener = listenerArray[i];\r\n // We might not have a listener if the listener was removed.\r\n if (listener && listener.capture == capture && !listener.removed) {\r\n var result = goog.events.fireListener(listener, eventObject);\r\n retval = retval && (result !== false);\r\n }\r\n }\r\n }\r\n }\r\n return retval;\r\n};\r\n\r\n\r\n/**\r\n * Fires a listener with a set of arguments\r\n *\r\n * @param {goog.events.Listener} listener The listener object to call.\r\n * @param {Object} eventObject The event object to pass to the listener.\r\n * @return {*} Result of listener.\r\n */\r\ngoog.events.fireListener = function(listener, eventObject) {\r\n var listenerFn = listener.listener;\r\n var listenerHandler = listener.handler || listener.src;\r\n\r\n if (listener.callOnce) {\r\n goog.events.unlistenByKey(listener);\r\n }\r\n return listenerFn.call(listenerHandler, eventObject);\r\n};\r\n\r\n\r\n/**\r\n * Gets the total number of listeners currently in the system.\r\n * @return {number} Number of listeners.\r\n * @deprecated This returns estimated count, now that Closure no longer\r\n * stores a central listener registry. We still return an estimation\r\n * to keep existing listener-related tests passing. In the near future,\r\n * this function will be removed.\r\n */\r\ngoog.events.getTotalListenerCount = function() {\r\n return goog.events.listenerCountEstimate_;\r\n};\r\n\r\n\r\n/**\r\n * Dispatches an event (or event like object) and calls all listeners\r\n * listening for events of this type. The type of the event is decided by the\r\n * type property on the event object.\r\n *\r\n * If any of the listeners returns false OR calls preventDefault then this\r\n * function will return false. If one of the capture listeners calls\r\n * stopPropagation, then the bubble listeners won't fire.\r\n *\r\n * @param {goog.events.Listenable} src The event target.\r\n * @param {goog.events.EventLike} e Event object.\r\n * @return {boolean} If anyone called preventDefault on the event object (or\r\n * if any of the handlers returns false) this will also return false.\r\n * If there are no handlers, or if all handlers return true, this returns\r\n * true.\r\n */\r\ngoog.events.dispatchEvent = function(src, e) {\r\n goog.asserts.assert(\r\n goog.events.Listenable.isImplementedBy(src),\r\n 'Can not use goog.events.dispatchEvent with ' +\r\n 'non-goog.events.Listenable instance.');\r\n return src.dispatchEvent(e);\r\n};\r\n\r\n\r\n/**\r\n * Installs exception protection for the browser event entry point using the\r\n * given error handler.\r\n *\r\n * @param {goog.debug.ErrorHandler} errorHandler Error handler with which to\r\n * protect the entry point.\r\n */\r\ngoog.events.protectBrowserEventEntryPoint = function(errorHandler) {\r\n goog.events.handleBrowserEvent_ =\r\n errorHandler.protectEntryPoint(goog.events.handleBrowserEvent_);\r\n};\r\n\r\n\r\n/**\r\n * Handles an event and dispatches it to the correct listeners. This\r\n * function is a proxy for the real listener the user specified.\r\n *\r\n * @param {goog.events.Listener} listener The listener object.\r\n * @param {Event=} opt_evt Optional event object that gets passed in via the\r\n * native event handlers.\r\n * @return {*} Result of the event handler.\r\n * @this {EventTarget} The object or Element that fired the event.\r\n * @private\r\n */\r\ngoog.events.handleBrowserEvent_ = function(listener, opt_evt) {\r\n if (listener.removed) {\r\n return true;\r\n }\r\n\r\n // Synthesize event propagation if the browser does not support W3C\r\n // event model.\r\n if (!goog.events.BrowserFeature.HAS_W3C_EVENT_SUPPORT) {\r\n var ieEvent = opt_evt ||\r\n /** @type {Event} */ (goog.getObjectByName('window.event'));\r\n var evt = new goog.events.BrowserEvent(ieEvent, this);\r\n /** @type {*} */\r\n var retval = true;\r\n\r\n if (goog.events.CAPTURE_SIMULATION_MODE ==\r\n goog.events.CaptureSimulationMode.ON) {\r\n // If we have not marked this event yet, we should perform capture\r\n // simulation.\r\n if (!goog.events.isMarkedIeEvent_(ieEvent)) {\r\n goog.events.markIeEvent_(ieEvent);\r\n\r\n var ancestors = [];\r\n for (var parent = evt.currentTarget; parent;\r\n parent = parent.parentNode) {\r\n ancestors.push(parent);\r\n }\r\n\r\n // Fire capture listeners.\r\n var type = listener.type;\r\n for (var i = ancestors.length - 1; !evt.propagationStopped_ && i >= 0;\r\n i--) {\r\n evt.currentTarget = ancestors[i];\r\n var result =\r\n goog.events.fireListeners_(ancestors[i], type, true, evt);\r\n retval = retval && result;\r\n }\r\n\r\n // Fire bubble listeners.\r\n //\r\n // We can technically rely on IE to perform bubble event\r\n // propagation. However, it turns out that IE fires events in\r\n // opposite order of attachEvent registration, which broke\r\n // some code and tests that rely on the order. (While W3C DOM\r\n // Level 2 Events TR leaves the event ordering unspecified,\r\n // modern browsers and W3C DOM Level 3 Events Working Draft\r\n // actually specify the order as the registration order.)\r\n for (var i = 0; !evt.propagationStopped_ && i < ancestors.length; i++) {\r\n evt.currentTarget = ancestors[i];\r\n var result =\r\n goog.events.fireListeners_(ancestors[i], type, false, evt);\r\n retval = retval && result;\r\n }\r\n }\r\n } else {\r\n retval = goog.events.fireListener(listener, evt);\r\n }\r\n return retval;\r\n }\r\n\r\n // Otherwise, simply fire the listener.\r\n return goog.events.fireListener(\r\n listener, new goog.events.BrowserEvent(opt_evt, this));\r\n};\r\n\r\n\r\n/**\r\n * This is used to mark the IE event object so we do not do the Closure pass\r\n * twice for a bubbling event.\r\n * @param {Event} e The IE browser event.\r\n * @private\r\n */\r\ngoog.events.markIeEvent_ = function(e) {\r\n // Only the keyCode and the returnValue can be changed. We use keyCode for\r\n // non keyboard events.\r\n // event.returnValue is a bit more tricky. It is undefined by default. A\r\n // boolean false prevents the default action. In a window.onbeforeunload and\r\n // the returnValue is non undefined it will be alerted. However, we will only\r\n // modify the returnValue for keyboard events. We can get a problem if non\r\n // closure events sets the keyCode or the returnValue\r\n\r\n var useReturnValue = false;\r\n\r\n if (e.keyCode == 0) {\r\n // We cannot change the keyCode in case that srcElement is input[type=file].\r\n // We could test that that is the case but that would allocate 3 objects.\r\n // If we use try/catch we will only allocate extra objects in the case of a\r\n // failure.\r\n\r\n try {\r\n e.keyCode = -1;\r\n return;\r\n } catch (ex) {\r\n useReturnValue = true;\r\n }\r\n }\r\n\r\n if (useReturnValue ||\r\n /** @type {boolean|undefined} */ (e.returnValue) == undefined) {\r\n e.returnValue = true;\r\n }\r\n};\r\n\r\n\r\n/**\r\n * This is used to check if an IE event has already been handled by the Closure\r\n * system so we do not do the Closure pass twice for a bubbling event.\r\n * @param {Event} e The IE browser event.\r\n * @return {boolean} True if the event object has been marked.\r\n * @private\r\n */\r\ngoog.events.isMarkedIeEvent_ = function(e) {\r\n return e.keyCode < 0 || e.returnValue != undefined;\r\n};\r\n\r\n\r\n/**\r\n * Counter to create unique event ids.\r\n * @private {number}\r\n */\r\ngoog.events.uniqueIdCounter_ = 0;\r\n\r\n\r\n/**\r\n * Creates a unique event id.\r\n *\r\n * @param {string} identifier The identifier.\r\n * @return {string} A unique identifier.\r\n * @idGenerator {unique}\r\n */\r\ngoog.events.getUniqueId = function(identifier) {\r\n return identifier + '_' + goog.events.uniqueIdCounter_++;\r\n};\r\n\r\n\r\n/**\r\n * @param {EventTarget} src The source object.\r\n * @return {goog.events.ListenerMap} A listener map for the given\r\n * source object, or null if none exists.\r\n * @private\r\n */\r\ngoog.events.getListenerMap_ = function(src) {\r\n var listenerMap = src[goog.events.LISTENER_MAP_PROP_];\r\n // IE serializes the property as well (e.g. when serializing outer\r\n // HTML). So we must check that the value is of the correct type.\r\n return listenerMap instanceof goog.events.ListenerMap ? listenerMap : null;\r\n};\r\n\r\n\r\n/**\r\n * Expando property for listener function wrapper for Object with\r\n * handleEvent.\r\n * @private @const {string}\r\n */\r\ngoog.events.LISTENER_WRAPPER_PROP_ =\r\n '__closure_events_fn_' + ((Math.random() * 1e9) >>> 0);\r\n\r\n\r\n/**\r\n * @param {Object|Function} listener The listener function or an\r\n * object that contains handleEvent method.\r\n * @return {!Function} Either the original function or a function that\r\n * calls obj.handleEvent. If the same listener is passed to this\r\n * function more than once, the same function is guaranteed to be\r\n * returned.\r\n */\r\ngoog.events.wrapListener = function(listener) {\r\n goog.asserts.assert(listener, 'Listener can not be null.');\r\n\r\n if (goog.isFunction(listener)) {\r\n return listener;\r\n }\r\n\r\n goog.asserts.assert(\r\n listener.handleEvent, 'An object listener must have handleEvent method.');\r\n if (!listener[goog.events.LISTENER_WRAPPER_PROP_]) {\r\n listener[goog.events.LISTENER_WRAPPER_PROP_] = function(e) {\r\n return /** @type {?} */ (listener).handleEvent(e);\r\n };\r\n }\r\n return listener[goog.events.LISTENER_WRAPPER_PROP_];\r\n};\r\n\r\n\r\n// Register the browser event handler as an entry point, so that\r\n// it can be monitored for exception handling, etc.\r\ngoog.debug.entryPointRegistry.register(\r\n /**\r\n * @param {function(!Function): !Function} transformer The transforming\r\n * function.\r\n */\r\n function(transformer) {\r\n goog.events.handleBrowserEvent_ =\r\n transformer(goog.events.handleBrowserEvent_);\r\n });\r\n","// Copyright 2005 The Closure Library Authors. All Rights Reserved.\r\n//\r\n// Licensed under the Apache License, Version 2.0 (the \"License\");\r\n// you may not use this file except in compliance with the License.\r\n// You may obtain a copy of the License at\r\n//\r\n// http://www.apache.org/licenses/LICENSE-2.0\r\n//\r\n// Unless required by applicable law or agreed to in writing, software\r\n// distributed under the License is distributed on an \"AS-IS\" BASIS,\r\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n// See the License for the specific language governing permissions and\r\n// limitations under the License.\r\n\r\n/**\r\n * @fileoverview A disposable implementation of a custom\r\n * listenable/event target. See also: documentation for\r\n * `goog.events.Listenable`.\r\n *\r\n * @author arv@google.com (Erik Arvidsson) [Original implementation]\r\n * @see ../demos/eventtarget.html\r\n * @see goog.events.Listenable\r\n */\r\n\r\ngoog.provide('goog.events.EventTarget');\r\n\r\ngoog.require('goog.Disposable');\r\ngoog.require('goog.asserts');\r\ngoog.require('goog.events');\r\ngoog.require('goog.events.Event');\r\ngoog.require('goog.events.Listenable');\r\ngoog.require('goog.events.ListenerMap');\r\ngoog.require('goog.object');\r\n\r\n\r\n\r\n/**\r\n * An implementation of `goog.events.Listenable` with full W3C\r\n * EventTarget-like support (capture/bubble mechanism, stopping event\r\n * propagation, preventing default actions).\r\n *\r\n * You may subclass this class to turn your class into a Listenable.\r\n *\r\n * Unless propagation is stopped, an event dispatched by an\r\n * EventTarget will bubble to the parent returned by\r\n * `getParentEventTarget`. To set the parent, call\r\n * `setParentEventTarget`. Subclasses that don't support\r\n * changing the parent can override the setter to throw an error.\r\n *\r\n * Example usage:\r\n * <pre>\r\n * var source = new goog.events.EventTarget();\r\n * function handleEvent(e) {\r\n * alert('Type: ' + e.type + '; Target: ' + e.target);\r\n * }\r\n * source.listen('foo', handleEvent);\r\n * // Or: goog.events.listen(source, 'foo', handleEvent);\r\n * ...\r\n * source.dispatchEvent('foo'); // will call handleEvent\r\n * ...\r\n * source.unlisten('foo', handleEvent);\r\n * // Or: goog.events.unlisten(source, 'foo', handleEvent);\r\n * </pre>\r\n *\r\n * @constructor\r\n * @extends {goog.Disposable}\r\n * @implements {goog.events.Listenable}\r\n */\r\ngoog.events.EventTarget = function() {\r\n goog.Disposable.call(this);\r\n\r\n /**\r\n * Maps of event type to an array of listeners.\r\n * @private {!goog.events.ListenerMap}\r\n */\r\n this.eventTargetListeners_ = new goog.events.ListenerMap(this);\r\n\r\n /**\r\n * The object to use for event.target. Useful when mixing in an\r\n * EventTarget to another object.\r\n * @private {!Object}\r\n */\r\n this.actualEventTarget_ = this;\r\n\r\n /**\r\n * Parent event target, used during event bubbling.\r\n *\r\n * TODO(chrishenry): Change this to goog.events.Listenable. This\r\n * currently breaks people who expect getParentEventTarget to return\r\n * goog.events.EventTarget.\r\n *\r\n * @private {?goog.events.EventTarget}\r\n */\r\n this.parentEventTarget_ = null;\r\n};\r\ngoog.inherits(goog.events.EventTarget, goog.Disposable);\r\ngoog.events.Listenable.addImplementation(goog.events.EventTarget);\r\n\r\n\r\n/**\r\n * An artificial cap on the number of ancestors you can have. This is mainly\r\n * for loop detection.\r\n * @const {number}\r\n * @private\r\n */\r\ngoog.events.EventTarget.MAX_ANCESTORS_ = 1000;\r\n\r\n\r\n/**\r\n * Returns the parent of this event target to use for bubbling.\r\n *\r\n * @return {goog.events.EventTarget} The parent EventTarget or null if\r\n * there is no parent.\r\n * @override\r\n */\r\ngoog.events.EventTarget.prototype.getParentEventTarget = function() {\r\n return this.parentEventTarget_;\r\n};\r\n\r\n\r\n/**\r\n * Sets the parent of this event target to use for capture/bubble\r\n * mechanism.\r\n * @param {goog.events.EventTarget} parent Parent listenable (null if none).\r\n */\r\ngoog.events.EventTarget.prototype.setParentEventTarget = function(parent) {\r\n this.parentEventTarget_ = parent;\r\n};\r\n\r\n\r\n/**\r\n * Adds an event listener to the event target. The same handler can only be\r\n * added once per the type. Even if you add the same handler multiple times\r\n * using the same type then it will only be called once when the event is\r\n * dispatched.\r\n *\r\n * @param {string|!goog.events.EventId} type The type of the event to listen for\r\n * @param {function(?):?|{handleEvent:function(?):?}|null} handler The function\r\n * to handle the event. The handler can also be an object that implements\r\n * the handleEvent method which takes the event object as argument.\r\n * @param {boolean=} opt_capture In DOM-compliant browsers, this determines\r\n * whether the listener is fired during the capture or bubble phase\r\n * of the event.\r\n * @param {Object=} opt_handlerScope Object in whose scope to call\r\n * the listener.\r\n * @deprecated Use `#listen` instead, when possible. Otherwise, use\r\n * `goog.events.listen` if you are passing Object\r\n * (instead of Function) as handler.\r\n */\r\ngoog.events.EventTarget.prototype.addEventListener = function(\r\n type, handler, opt_capture, opt_handlerScope) {\r\n goog.events.listen(this, type, handler, opt_capture, opt_handlerScope);\r\n};\r\n\r\n\r\n/**\r\n * Removes an event listener from the event target. The handler must be the\r\n * same object as the one added. If the handler has not been added then\r\n * nothing is done.\r\n *\r\n * @param {string} type The type of the event to listen for.\r\n * @param {function(?):?|{handleEvent:function(?):?}|null} handler The function\r\n * to handle the event. The handler can also be an object that implements\r\n * the handleEvent method which takes the event object as argument.\r\n * @param {boolean=} opt_capture In DOM-compliant browsers, this determines\r\n * whether the listener is fired during the capture or bubble phase\r\n * of the event.\r\n * @param {Object=} opt_handlerScope Object in whose scope to call\r\n * the listener.\r\n * @deprecated Use `#unlisten` instead, when possible. Otherwise, use\r\n * `goog.events.unlisten` if you are passing Object\r\n * (instead of Function) as handler.\r\n */\r\ngoog.events.EventTarget.prototype.removeEventListener = function(\r\n type, handler, opt_capture, opt_handlerScope) {\r\n goog.events.unlisten(this, type, handler, opt_capture, opt_handlerScope);\r\n};\r\n\r\n\r\n/** @override */\r\ngoog.events.EventTarget.prototype.dispatchEvent = function(e) {\r\n this.assertInitialized_();\r\n\r\n var ancestorsTree, ancestor = this.getParentEventTarget();\r\n if (ancestor) {\r\n ancestorsTree = [];\r\n var ancestorCount = 1;\r\n for (; ancestor; ancestor = ancestor.getParentEventTarget()) {\r\n ancestorsTree.push(ancestor);\r\n goog.asserts.assert(\r\n (++ancestorCount < goog.events.EventTarget.MAX_ANCESTORS_),\r\n 'infinite loop');\r\n }\r\n }\r\n\r\n return goog.events.EventTarget.dispatchEventInternal_(\r\n this.actualEventTarget_, e, ancestorsTree);\r\n};\r\n\r\n\r\n/**\r\n * Removes listeners from this object. Classes that extend EventTarget may\r\n * need to override this method in order to remove references to DOM Elements\r\n * and additional listeners.\r\n * @override\r\n * @protected\r\n */\r\ngoog.events.EventTarget.prototype.disposeInternal = function() {\r\n goog.events.EventTarget.superClass_.disposeInternal.call(this);\r\n\r\n this.removeAllListeners();\r\n this.parentEventTarget_ = null;\r\n};\r\n\r\n\r\n/** @override */\r\ngoog.events.EventTarget.prototype.listen = function(\r\n type, listener, opt_useCapture, opt_listenerScope) {\r\n this.assertInitialized_();\r\n return this.eventTargetListeners_.add(\r\n String(type), listener, false /* callOnce */, opt_useCapture,\r\n opt_listenerScope);\r\n};\r\n\r\n\r\n/** @override */\r\ngoog.events.EventTarget.prototype.listenOnce = function(\r\n type, listener, opt_useCapture, opt_listenerScope) {\r\n return this.eventTargetListeners_.add(\r\n String(type), listener, true /* callOnce */, opt_useCapture,\r\n opt_listenerScope);\r\n};\r\n\r\n\r\n/** @override */\r\ngoog.events.EventTarget.prototype.unlisten = function(\r\n type, listener, opt_useCapture, opt_listenerScope) {\r\n return this.eventTargetListeners_.remove(\r\n String(type), listener, opt_useCapture, opt_listenerScope);\r\n};\r\n\r\n\r\n/** @override */\r\ngoog.events.EventTarget.prototype.unlistenByKey = function(key) {\r\n return this.eventTargetListeners_.removeByKey(key);\r\n};\r\n\r\n\r\n/** @override */\r\ngoog.events.EventTarget.prototype.removeAllListeners = function(opt_type) {\r\n // TODO(chrishenry): Previously, removeAllListeners can be called on\r\n // uninitialized EventTarget, so we preserve that behavior. We\r\n // should remove this when usages that rely on that fact are purged.\r\n if (!this.eventTargetListeners_) {\r\n return 0;\r\n }\r\n return this.eventTargetListeners_.removeAll(opt_type);\r\n};\r\n\r\n\r\n/** @override */\r\ngoog.events.EventTarget.prototype.fireListeners = function(\r\n type, capture, eventObject) {\r\n // TODO(chrishenry): Original code avoids array creation when there\r\n // is no listener, so we do the same. If this optimization turns\r\n // out to be not required, we can replace this with\r\n // getListeners(type, capture) instead, which is simpler.\r\n var listenerArray = this.eventTargetListeners_.listeners[String(type)];\r\n if (!listenerArray) {\r\n return true;\r\n }\r\n listenerArray = listenerArray.concat();\r\n\r\n var rv = true;\r\n for (var i = 0; i < listenerArray.length; ++i) {\r\n var listener = listenerArray[i];\r\n // We might not have a listener if the listener was removed.\r\n if (listener && !listener.removed && listener.capture == capture) {\r\n var listenerFn = listener.listener;\r\n var listenerHandler = listener.handler || listener.src;\r\n\r\n if (listener.callOnce) {\r\n this.unlistenByKey(listener);\r\n }\r\n rv = listenerFn.call(listenerHandler, eventObject) !== false && rv;\r\n }\r\n }\r\n\r\n return rv && eventObject.returnValue_ != false;\r\n};\r\n\r\n\r\n/** @override */\r\ngoog.events.EventTarget.prototype.getListeners = function(type, capture) {\r\n return this.eventTargetListeners_.getListeners(String(type), capture);\r\n};\r\n\r\n\r\n/** @override */\r\ngoog.events.EventTarget.prototype.getListener = function(\r\n type, listener, capture, opt_listenerScope) {\r\n return this.eventTargetListeners_.getListener(\r\n String(type), listener, capture, opt_listenerScope);\r\n};\r\n\r\n\r\n/** @override */\r\ngoog.events.EventTarget.prototype.hasListener = function(\r\n opt_type, opt_capture) {\r\n var id = goog.isDef(opt_type) ? String(opt_type) : undefined;\r\n return this.eventTargetListeners_.hasListener(id, opt_capture);\r\n};\r\n\r\n\r\n/**\r\n * Sets the target to be used for `event.target` when firing\r\n * event. Mainly used for testing. For example, see\r\n * `goog.testing.events.mixinListenable`.\r\n * @param {!Object} target The target.\r\n */\r\ngoog.events.EventTarget.prototype.setTargetForTesting = function(target) {\r\n this.actualEventTarget_ = target;\r\n};\r\n\r\n\r\n/**\r\n * Asserts that the event target instance is initialized properly.\r\n * @private\r\n */\r\ngoog.events.EventTarget.prototype.assertInitialized_ = function() {\r\n goog.asserts.assert(\r\n this.eventTargetListeners_,\r\n 'Event target is not initialized. Did you call the superclass ' +\r\n '(goog.events.EventTarget) constructor?');\r\n};\r\n\r\n\r\n/**\r\n * Dispatches the given event on the ancestorsTree.\r\n *\r\n * @param {!Object} target The target to dispatch on.\r\n * @param {goog.events.Event|Object|string} e The event object.\r\n * @param {Array<goog.events.Listenable>=} opt_ancestorsTree The ancestors\r\n * tree of the target, in reverse order from the closest ancestor\r\n * to the root event target. May be null if the target has no ancestor.\r\n * @return {boolean} If anyone called preventDefault on the event object (or\r\n * if any of the listeners returns false) this will also return false.\r\n * @private\r\n */\r\ngoog.events.EventTarget.dispatchEventInternal_ = function(\r\n target, e, opt_ancestorsTree) {\r\n /** @suppress {missingProperties} */\r\n var type = e.type || /** @type {string} */ (e);\r\n\r\n // If accepting a string or object, create a custom event object so that\r\n // preventDefault and stopPropagation work with the event.\r\n if (goog.isString(e)) {\r\n e = new goog.events.Event(e, target);\r\n } else if (!(e instanceof goog.events.Event)) {\r\n var oldEvent = e;\r\n e = new goog.events.Event(type, target);\r\n goog.object.extend(e, oldEvent);\r\n } else {\r\n e.target = e.target || target;\r\n }\r\n\r\n var rv = true, currentTarget;\r\n\r\n // Executes all capture listeners on the ancestors, if any.\r\n if (opt_ancestorsTree) {\r\n for (var i = opt_ancestorsTree.length - 1; !e.propagationStopped_ && i >= 0;\r\n i--) {\r\n currentTarget = e.currentTarget = opt_ancestorsTree[i];\r\n rv = currentTarget.fireListeners(type, true, e) && rv;\r\n }\r\n }\r\n\r\n // Executes capture and bubble listeners on the target.\r\n if (!e.propagationStopped_) {\r\n currentTarget = /** @type {?} */ (e.currentTarget = target);\r\n rv = currentTarget.fireListeners(type, true, e) && rv;\r\n if (!e.propagationStopped_) {\r\n rv = currentTarget.fireListeners(type, false, e) && rv;\r\n }\r\n }\r\n\r\n // Executes all bubble listeners on the ancestors, if any.\r\n if (opt_ancestorsTree) {\r\n for (i = 0; !e.propagationStopped_ && i < opt_ancestorsTree.length; i++) {\r\n currentTarget = e.currentTarget = opt_ancestorsTree[i];\r\n rv = currentTarget.fireListeners(type, false, e) && rv;\r\n }\r\n }\r\n\r\n return rv;\r\n};\r\n","// Copyright 2006 The Closure Library Authors. All Rights Reserved.\r\n//\r\n// Licensed under the Apache License, Version 2.0 (the \"License\");\r\n// you may not use this file except in compliance with the License.\r\n// You may obtain a copy of the License at\r\n//\r\n// http://www.apache.org/licenses/LICENSE-2.0\r\n//\r\n// Unless required by applicable law or agreed to in writing, software\r\n// distributed under the License is distributed on an \"AS-IS\" BASIS,\r\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n// See the License for the specific language governing permissions and\r\n// limitations under the License.\r\n\r\n/**\r\n * @fileoverview JSON utility functions.\r\n * @author arv@google.com (Erik Arvidsson)\r\n */\r\n\r\n\r\ngoog.provide('goog.json');\r\ngoog.provide('goog.json.Replacer');\r\ngoog.provide('goog.json.Reviver');\r\ngoog.provide('goog.json.Serializer');\r\n\r\n\r\n/**\r\n * @define {boolean} If true, use the native JSON parsing API.\r\n * NOTE: The default `goog.json.parse` implementation is able to handle\r\n * invalid JSON. JSPB used to produce invalid JSON which is not the case\r\n * anymore so this is safe to enable for parsing JSPB. Using native JSON is\r\n * faster and safer than the default implementation using `eval`.\r\n */\r\ngoog.json.USE_NATIVE_JSON = goog.define('goog.json.USE_NATIVE_JSON', false);\r\n\r\n/**\r\n * @define {boolean} If true, try the native JSON parsing API first. If it\r\n * fails, log an error and use `eval` instead. This is useful when\r\n * transitioning to `goog.json.USE_NATIVE_JSON`. The error logger needs to\r\n * be set by `goog.json.setErrorLogger`. If it is not set then the error\r\n * is ignored.\r\n */\r\ngoog.json.TRY_NATIVE_JSON = goog.define('goog.json.TRY_NATIVE_JSON', false);\r\n\r\n\r\n/**\r\n * Tests if a string is an invalid JSON string. This only ensures that we are\r\n * not using any invalid characters\r\n * @param {string} s The string to test.\r\n * @return {boolean} True if the input is a valid JSON string.\r\n */\r\ngoog.json.isValid = function(s) {\r\n // All empty whitespace is not valid.\r\n if (/^\\s*$/.test(s)) {\r\n return false;\r\n }\r\n\r\n // This is taken from http://www.json.org/json2.js which is released to the\r\n // public domain.\r\n // Changes: We dissallow \\u2028 Line separator and \\u2029 Paragraph separator\r\n // inside strings. We also treat \\u2028 and \\u2029 as whitespace which they\r\n // are in the RFC but IE and Safari does not match \\s to these so we need to\r\n // include them in the reg exps in all places where whitespace is allowed.\r\n // We allowed \\x7f inside strings because some tools don't escape it,\r\n // e.g. http://www.json.org/java/org/json/JSONObject.java\r\n\r\n // Parsing happens in three stages. In the first stage, we run the text\r\n // against regular expressions that look for non-JSON patterns. We are\r\n // especially concerned with '()' and 'new' because they can cause invocation,\r\n // and '=' because it can cause mutation. But just to be safe, we want to\r\n // reject all unexpected forms.\r\n\r\n // We split the first stage into 4 regexp operations in order to work around\r\n // crippling inefficiencies in IE's and Safari's regexp engines. First we\r\n // replace all backslash pairs with '@' (a non-JSON character). Second, we\r\n // replace all simple value tokens with ']' characters, but only when followed\r\n // by a colon, comma, closing bracket or end of string. Third, we delete all\r\n // open brackets that follow a colon or comma or that begin the text. Finally,\r\n // we look to see that the remaining characters are only whitespace or ']' or\r\n // ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.\r\n\r\n // Don't make these static since they have the global flag.\r\n var backslashesRe = /\\\\[\"\\\\\\/bfnrtu]/g;\r\n var simpleValuesRe =\r\n /(?:\"[^\"\\\\\\n\\r\\u2028\\u2029\\x00-\\x08\\x0a-\\x1f]*\"|true|false|null|-?\\d+(?:\\.\\d*)?(?:[eE][+\\-]?\\d+)?)[\\s\\u2028\\u2029]*(?=:|,|]|}|$)/g;\r\n var openBracketsRe = /(?:^|:|,)(?:[\\s\\u2028\\u2029]*\\[)+/g;\r\n var remainderRe = /^[\\],:{}\\s\\u2028\\u2029]*$/;\r\n\r\n return remainderRe.test(\r\n s.replace(backslashesRe, '@')\r\n .replace(simpleValuesRe, ']')\r\n .replace(openBracketsRe, ''));\r\n};\r\n\r\n/**\r\n * Logs a parsing error in `JSON.parse` solvable by using `eval`\r\n * if `goog.json.TRY_NATIVE_JSON` is enabled.\r\n * @private {function(string, !Error)} The first parameter is the error message,\r\n * the second is the exception thrown by `JSON.parse`.\r\n */\r\ngoog.json.errorLogger_ = goog.nullFunction;\r\n\r\n\r\n/**\r\n * Sets an error logger to use if there's a recoverable parsing error and\r\n * `goog.json.TRY_NATIVE_JSON` is enabled.\r\n * @param {function(string, !Error)} errorLogger The first parameter is the\r\n * error message, the second is the exception thrown by `JSON.parse`.\r\n */\r\ngoog.json.setErrorLogger = function(errorLogger) {\r\n goog.json.errorLogger_ = errorLogger;\r\n};\r\n\r\n\r\n/**\r\n * Parses a JSON string and returns the result. This throws an exception if\r\n * the string is an invalid JSON string.\r\n *\r\n * Note that this is very slow on large strings. Use JSON.parse if possible.\r\n *\r\n * @param {*} s The JSON string to parse.\r\n * @throws Error if s is invalid JSON.\r\n * @return {Object} The object generated from the JSON string, or null.\r\n * @deprecated Use JSON.parse.\r\n */\r\ngoog.json.parse = goog.json.USE_NATIVE_JSON ?\r\n /** @type {function(*):Object} */ (goog.global['JSON']['parse']) :\r\n function(s) {\r\n var error;\r\n if (goog.json.TRY_NATIVE_JSON) {\r\n try {\r\n return goog.global['JSON']['parse'](s);\r\n } catch (ex) {\r\n error = ex;\r\n }\r\n }\r\n var o = String(s);\r\n if (goog.json.isValid(o)) {\r\n\r\n try {\r\n var result = /** @type {?Object} */ (eval('(' + o + ')'));\r\n if (error) {\r\n goog.json.errorLogger_('Invalid JSON: ' + o, error);\r\n }\r\n return result;\r\n } catch (ex) {\r\n }\r\n }\r\n throw new Error('Invalid JSON string: ' + o);\r\n };\r\n\r\n\r\n/**\r\n * JSON replacer, as defined in Section 15.12.3 of the ES5 spec.\r\n * @see http://ecma-international.org/ecma-262/5.1/#sec-15.12.3\r\n *\r\n * TODO(nicksantos): Array should also be a valid replacer.\r\n *\r\n * @typedef {function(this:Object, string, *): *}\r\n */\r\ngoog.json.Replacer;\r\n\r\n\r\n/**\r\n * JSON reviver, as defined in Section 15.12.2 of the ES5 spec.\r\n * @see http://ecma-international.org/ecma-262/5.1/#sec-15.12.3\r\n *\r\n * @typedef {function(this:Object, string, *): *}\r\n */\r\ngoog.json.Reviver;\r\n\r\n\r\n/**\r\n * Serializes an object or a value to a JSON string.\r\n *\r\n * @param {*} object The object to serialize.\r\n * @param {?goog.json.Replacer=} opt_replacer A replacer function\r\n * called for each (key, value) pair that determines how the value\r\n * should be serialized. By defult, this just returns the value\r\n * and allows default serialization to kick in.\r\n * @throws Error if there are loops in the object graph.\r\n * @return {string} A JSON string representation of the input.\r\n */\r\ngoog.json.serialize = goog.json.USE_NATIVE_JSON ?\r\n /** @type {function(*, ?goog.json.Replacer=):string} */\r\n (goog.global['JSON']['stringify']) :\r\n function(object, opt_replacer) {\r\n // NOTE(nicksantos): Currently, we never use JSON.stringify.\r\n //\r\n // The last time I evaluated this, JSON.stringify had subtle bugs and\r\n // behavior differences on all browsers, and the performance win was not\r\n // large enough to justify all the issues. This may change in the future\r\n // as browser implementations get better.\r\n //\r\n // assertSerialize in json_test contains if branches for the cases\r\n // that fail.\r\n return new goog.json.Serializer(opt_replacer).serialize(object);\r\n };\r\n\r\n\r\n\r\n/**\r\n * Class that is used to serialize JSON objects to a string.\r\n * @param {?goog.json.Replacer=} opt_replacer Replacer.\r\n * @constructor\r\n */\r\ngoog.json.Serializer = function(opt_replacer) {\r\n /**\r\n * @type {goog.json.Replacer|null|undefined}\r\n * @private\r\n */\r\n this.replacer_ = opt_replacer;\r\n};\r\n\r\n\r\n/**\r\n * Serializes an object or a value to a JSON string.\r\n *\r\n * @param {*} object The object to serialize.\r\n * @throws Error if there are loops in the object graph.\r\n * @return {string} A JSON string representation of the input.\r\n */\r\ngoog.json.Serializer.prototype.serialize = function(object) {\r\n var sb = [];\r\n this.serializeInternal(object, sb);\r\n return sb.join('');\r\n};\r\n\r\n\r\n/**\r\n * Serializes a generic value to a JSON string\r\n * @protected\r\n * @param {*} object The object to serialize.\r\n * @param {Array<string>} sb Array used as a string builder.\r\n * @throws Error if there are loops in the object graph.\r\n */\r\ngoog.json.Serializer.prototype.serializeInternal = function(object, sb) {\r\n if (object == null) {\r\n // undefined == null so this branch covers undefined as well as null\r\n sb.push('null');\r\n return;\r\n }\r\n\r\n if (typeof object == 'object') {\r\n if (goog.isArray(object)) {\r\n this.serializeArray(object, sb);\r\n return;\r\n } else if (\r\n object instanceof String || object instanceof Number ||\r\n object instanceof Boolean) {\r\n object = object.valueOf();\r\n // Fall through to switch below.\r\n } else {\r\n this.serializeObject_(/** @type {!Object} */ (object), sb);\r\n return;\r\n }\r\n }\r\n\r\n switch (typeof object) {\r\n case 'string':\r\n this.serializeString_(object, sb);\r\n break;\r\n case 'number':\r\n this.serializeNumber_(object, sb);\r\n break;\r\n case 'boolean':\r\n sb.push(String(object));\r\n break;\r\n case 'function':\r\n sb.push('null');\r\n break;\r\n default:\r\n throw new Error('Unknown type: ' + typeof object);\r\n }\r\n};\r\n\r\n\r\n/**\r\n * Character mappings used internally for goog.string.quote\r\n * @private\r\n * @type {!Object}\r\n */\r\ngoog.json.Serializer.charToJsonCharCache_ = {\r\n '\\\"': '\\\\\"',\r\n '\\\\': '\\\\\\\\',\r\n '/': '\\\\/',\r\n '\\b': '\\\\b',\r\n '\\f': '\\\\f',\r\n '\\n': '\\\\n',\r\n '\\r': '\\\\r',\r\n '\\t': '\\\\t',\r\n\r\n '\\x0B': '\\\\u000b' // '\\v' is not supported in JScript\r\n};\r\n\r\n\r\n/**\r\n * Regular expression used to match characters that need to be replaced.\r\n * The S60 browser has a bug where unicode characters are not matched by\r\n * regular expressions. The condition below detects such behaviour and\r\n * adjusts the regular expression accordingly.\r\n * @private\r\n * @type {!RegExp}\r\n */\r\ngoog.json.Serializer.charsToReplace_ = /\\uffff/.test('\\uffff') ?\r\n /[\\\\\\\"\\x00-\\x1f\\x7f-\\uffff]/g :\r\n /[\\\\\\\"\\x00-\\x1f\\x7f-\\xff]/g;\r\n\r\n\r\n/**\r\n * Serializes a string to a JSON string\r\n * @private\r\n * @param {string} s The string to serialize.\r\n * @param {Array<string>} sb Array used as a string builder.\r\n */\r\ngoog.json.Serializer.prototype.serializeString_ = function(s, sb) {\r\n // The official JSON implementation does not work with international\r\n // characters.\r\n sb.push('\"', s.replace(goog.json.Serializer.charsToReplace_, function(c) {\r\n // caching the result improves performance by a factor 2-3\r\n var rv = goog.json.Serializer.charToJsonCharCache_[c];\r\n if (!rv) {\r\n rv = '\\\\u' + (c.charCodeAt(0) | 0x10000).toString(16).substr(1);\r\n goog.json.Serializer.charToJsonCharCache_[c] = rv;\r\n }\r\n return rv;\r\n }), '\"');\r\n};\r\n\r\n\r\n/**\r\n * Serializes a number to a JSON string\r\n * @private\r\n * @param {number} n The number to serialize.\r\n * @param {Array<string>} sb Array used as a string builder.\r\n */\r\ngoog.json.Serializer.prototype.serializeNumber_ = function(n, sb) {\r\n sb.push(isFinite(n) && !isNaN(n) ? String(n) : 'null');\r\n};\r\n\r\n\r\n/**\r\n * Serializes an array to a JSON string\r\n * @param {Array<string>} arr The array to serialize.\r\n * @param {Array<string>} sb Array used as a string builder.\r\n * @protected\r\n */\r\ngoog.json.Serializer.prototype.serializeArray = function(arr, sb) {\r\n var l = arr.length;\r\n sb.push('[');\r\n var sep = '';\r\n for (var i = 0; i < l; i++) {\r\n sb.push(sep);\r\n\r\n var value = arr[i];\r\n this.serializeInternal(\r\n this.replacer_ ? this.replacer_.call(arr, String(i), value) : value,\r\n sb);\r\n\r\n sep = ',';\r\n }\r\n sb.push(']');\r\n};\r\n\r\n\r\n/**\r\n * Serializes an object to a JSON string\r\n * @private\r\n * @param {!Object} obj The object to serialize.\r\n * @param {Array<string>} sb Array used as a string builder.\r\n */\r\ngoog.json.Serializer.prototype.serializeObject_ = function(obj, sb) {\r\n sb.push('{');\r\n var sep = '';\r\n for (var key in obj) {\r\n if (Object.prototype.hasOwnProperty.call(obj, key)) {\r\n var value = obj[key];\r\n // Skip functions.\r\n if (typeof value != 'function') {\r\n sb.push(sep);\r\n this.serializeString_(key, sb);\r\n sb.push(':');\r\n\r\n this.serializeInternal(\r\n this.replacer_ ? this.replacer_.call(obj, key, value) : value, sb);\r\n\r\n sep = ',';\r\n }\r\n }\r\n }\r\n sb.push('}');\r\n};\r\n","// Copyright 2015 The Closure Library Authors. All Rights Reserved.\r\n//\r\n// Licensed under the Apache License, Version 2.0 (the \"License\");\r\n// you may not use this file except in compliance with the License.\r\n// You may obtain a copy of the License at\r\n//\r\n// http://www.apache.org/licenses/LICENSE-2.0\r\n//\r\n// Unless required by applicable law or agreed to in writing, software\r\n// distributed under the License is distributed on an \"AS-IS\" BASIS,\r\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n// See the License for the specific language governing permissions and\r\n// limitations under the License.\r\n\r\n/**\r\n * @fileoverview Simple freelist.\r\n *\r\n * An anterative to goog.structs.SimplePool, it imposes the requirement that the\r\n * objects in the list contain a \"next\" property that can be used to maintain\r\n * the pool.\r\n */\r\n\r\ngoog.provide('goog.async.FreeList');\r\n\r\n\r\n/**\r\n * @template ITEM\r\n */\r\ngoog.async.FreeList = goog.defineClass(null, {\r\n /**\r\n * @param {function():ITEM} create\r\n * @param {function(ITEM):void} reset\r\n * @param {number} limit\r\n */\r\n constructor: function(create, reset, limit) {\r\n /** @private @const {number} */\r\n this.limit_ = limit;\r\n /** @private @const {function()} */\r\n this.create_ = create;\r\n /** @private @const {function(ITEM):void} */\r\n this.reset_ = reset;\r\n\r\n /** @private {number} */\r\n this.occupants_ = 0;\r\n /** @private {ITEM} */\r\n this.head_ = null;\r\n },\r\n\r\n /**\r\n * @return {ITEM}\r\n */\r\n get: function() {\r\n var item;\r\n if (this.occupants_ > 0) {\r\n this.occupants_--;\r\n item = this.head_;\r\n this.head_ = item.next;\r\n item.next = null;\r\n } else {\r\n item = this.create_();\r\n }\r\n return item;\r\n },\r\n\r\n /**\r\n * @param {ITEM} item An item available for possible future reuse.\r\n */\r\n put: function(item) {\r\n this.reset_(item);\r\n if (this.occupants_ < this.limit_) {\r\n this.occupants_++;\r\n item.next = this.head_;\r\n this.head_ = item;\r\n }\r\n },\r\n\r\n /**\r\n * Visible for testing.\r\n * @package\r\n * @return {number}\r\n */\r\n occupants: function() { return this.occupants_; }\r\n});\r\n","// Copyright 2015 The Closure Library Authors. All Rights Reserved.\r\n//\r\n// Licensed under the Apache License, Version 2.0 (the \"License\");\r\n// you may not use this file except in compliance with the License.\r\n// You may obtain a copy of the License at\r\n//\r\n// http://www.apache.org/licenses/LICENSE-2.0\r\n//\r\n// Unless required by applicable law or agreed to in writing, software\r\n// distributed under the License is distributed on an \"AS-IS\" BASIS,\r\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n// See the License for the specific language governing permissions and\r\n// limitations under the License.\r\n\r\ngoog.provide('goog.async.WorkItem');\r\ngoog.provide('goog.async.WorkQueue');\r\n\r\ngoog.require('goog.asserts');\r\ngoog.require('goog.async.FreeList');\r\n\r\n\r\n// TODO(johnlenz): generalize the WorkQueue if this is used by more\r\n// than goog.async.run.\r\n\r\n\r\n\r\n/**\r\n * A low GC workqueue. The key elements of this design:\r\n * - avoids the need for goog.bind or equivalent by carrying scope\r\n * - avoids the need for array reallocation by using a linked list\r\n * - minimizes work entry objects allocation by recycling objects\r\n * @constructor\r\n * @final\r\n * @struct\r\n */\r\ngoog.async.WorkQueue = function() {\r\n this.workHead_ = null;\r\n this.workTail_ = null;\r\n};\r\n\r\n\r\n/** @define {number} The maximum number of entries to keep for recycling. */\r\ngoog.async.WorkQueue.DEFAULT_MAX_UNUSED =\r\n goog.define('goog.async.WorkQueue.DEFAULT_MAX_UNUSED', 100);\r\n\r\n\r\n/** @const @private {goog.async.FreeList<goog.async.WorkItem>} */\r\ngoog.async.WorkQueue.freelist_ = new goog.async.FreeList(\r\n function() { return new goog.async.WorkItem(); },\r\n function(item) { item.reset(); }, goog.async.WorkQueue.DEFAULT_MAX_UNUSED);\r\n\r\n\r\n/**\r\n * @param {function()} fn\r\n * @param {Object|null|undefined} scope\r\n */\r\ngoog.async.WorkQueue.prototype.add = function(fn, scope) {\r\n var item = this.getUnusedItem_();\r\n item.set(fn, scope);\r\n\r\n if (this.workTail_) {\r\n this.workTail_.next = item;\r\n this.workTail_ = item;\r\n } else {\r\n goog.asserts.assert(!this.workHead_);\r\n this.workHead_ = item;\r\n this.workTail_ = item;\r\n }\r\n};\r\n\r\n\r\n/**\r\n * @return {goog.async.WorkItem}\r\n */\r\ngoog.async.WorkQueue.prototype.remove = function() {\r\n var item = null;\r\n\r\n if (this.workHead_) {\r\n item = this.workHead_;\r\n this.workHead_ = this.workHead_.next;\r\n if (!this.workHead_) {\r\n this.workTail_ = null;\r\n }\r\n item.next = null;\r\n }\r\n return item;\r\n};\r\n\r\n\r\n/**\r\n * @param {goog.async.WorkItem} item\r\n */\r\ngoog.async.WorkQueue.prototype.returnUnused = function(item) {\r\n goog.async.WorkQueue.freelist_.put(item);\r\n};\r\n\r\n\r\n/**\r\n * @return {goog.async.WorkItem}\r\n * @private\r\n */\r\ngoog.async.WorkQueue.prototype.getUnusedItem_ = function() {\r\n return goog.async.WorkQueue.freelist_.get();\r\n};\r\n\r\n\r\n\r\n/**\r\n * @constructor\r\n * @final\r\n * @struct\r\n */\r\ngoog.async.WorkItem = function() {\r\n /** @type {?function()} */\r\n this.fn = null;\r\n /** @type {?Object|null|undefined} */\r\n this.scope = null;\r\n /** @type {?goog.async.WorkItem} */\r\n this.next = null;\r\n};\r\n\r\n\r\n/**\r\n * @param {function()} fn\r\n * @param {Object|null|undefined} scope\r\n */\r\ngoog.async.WorkItem.prototype.set = function(fn, scope) {\r\n this.fn = fn;\r\n this.scope = scope;\r\n this.next = null;\r\n};\r\n\r\n\r\n/** Reset the work item so they don't prevent GC before reuse */\r\ngoog.async.WorkItem.prototype.reset = function() {\r\n this.fn = null;\r\n this.scope = null;\r\n this.next = null;\r\n};\r\n","// Copyright 2013 The Closure Library Authors. All Rights Reserved.\r\n//\r\n// Licensed under the Apache License, Version 2.0 (the \"License\");\r\n// you may not use this file except in compliance with the License.\r\n// You may obtain a copy of the License at\r\n//\r\n// http://www.apache.org/licenses/LICENSE-2.0\r\n//\r\n// Unless required by applicable law or agreed to in writing, software\r\n// distributed under the License is distributed on an \"AS-IS\" BASIS,\r\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n// See the License for the specific language governing permissions and\r\n// limitations under the License.\r\n\r\ngoog.provide('goog.async.run');\r\n\r\ngoog.require('goog.async.WorkQueue');\r\ngoog.require('goog.async.nextTick');\r\ngoog.require('goog.async.throwException');\r\n\r\n/**\r\n * @define {boolean} If true, use the global Promise to implement goog.async.run\r\n * assuming either the native, or polyfill version will be used. Does still\r\n * permit tests to use forceNextTick.\r\n */\r\ngoog.ASSUME_NATIVE_PROMISE = goog.define('goog.ASSUME_NATIVE_PROMISE', false);\r\n\r\n/**\r\n * Fires the provided callback just before the current callstack unwinds, or as\r\n * soon as possible after the current JS execution context.\r\n * @param {function(this:THIS)} callback\r\n * @param {THIS=} opt_context Object to use as the \"this value\" when calling\r\n * the provided function.\r\n * @template THIS\r\n */\r\ngoog.async.run = function(callback, opt_context) {\r\n if (!goog.async.run.schedule_) {\r\n goog.async.run.initializeRunner_();\r\n }\r\n if (!goog.async.run.workQueueScheduled_) {\r\n // Nothing is currently scheduled, schedule it now.\r\n goog.async.run.schedule_();\r\n goog.async.run.workQueueScheduled_ = true;\r\n }\r\n\r\n goog.async.run.workQueue_.add(callback, opt_context);\r\n};\r\n\r\n\r\n/**\r\n * Initializes the function to use to process the work queue.\r\n * @private\r\n */\r\ngoog.async.run.initializeRunner_ = function() {\r\n if (goog.ASSUME_NATIVE_PROMISE ||\r\n (goog.global.Promise && goog.global.Promise.resolve)) {\r\n // Use goog.global.Promise instead of just Promise because the relevant\r\n // externs may be missing, and don't alias it because this could confuse the\r\n // compiler into thinking the polyfill is required when it should be treated\r\n // as optional.\r\n var promise = goog.global.Promise.resolve(undefined);\r\n goog.async.run.schedule_ = function() {\r\n promise.then(goog.async.run.processWorkQueue);\r\n };\r\n } else {\r\n goog.async.run.schedule_ = function() {\r\n goog.async.nextTick(goog.async.run.processWorkQueue);\r\n };\r\n }\r\n};\r\n\r\n\r\n/**\r\n * Forces goog.async.run to use nextTick instead of Promise.\r\n *\r\n * This should only be done in unit tests. It's useful because MockClock\r\n * replaces nextTick, but not the browser Promise implementation, so it allows\r\n * Promise-based code to be tested with MockClock.\r\n *\r\n * However, we also want to run promises if the MockClock is no longer in\r\n * control so we schedule a backup \"setTimeout\" to the unmocked timeout if\r\n * provided.\r\n *\r\n * @param {function(function())=} opt_realSetTimeout\r\n */\r\ngoog.async.run.forceNextTick = function(opt_realSetTimeout) {\r\n goog.async.run.schedule_ = function() {\r\n goog.async.nextTick(goog.async.run.processWorkQueue);\r\n if (opt_realSetTimeout) {\r\n opt_realSetTimeout(goog.async.run.processWorkQueue);\r\n }\r\n };\r\n};\r\n\r\n\r\n/**\r\n * The function used to schedule work asynchronousely.\r\n * @private {function()}\r\n */\r\ngoog.async.run.schedule_;\r\n\r\n\r\n/** @private {boolean} */\r\ngoog.async.run.workQueueScheduled_ = false;\r\n\r\n\r\n/** @private {!goog.async.WorkQueue} */\r\ngoog.async.run.workQueue_ = new goog.async.WorkQueue();\r\n\r\n\r\nif (goog.DEBUG) {\r\n /**\r\n * Reset the work queue. Only available for tests in debug mode.\r\n */\r\n goog.async.run.resetQueue = function() {\r\n goog.async.run.workQueueScheduled_ = false;\r\n goog.async.run.workQueue_ = new goog.async.WorkQueue();\r\n };\r\n}\r\n\r\n\r\n/**\r\n * Run any pending goog.async.run work items. This function is not intended\r\n * for general use, but for use by entry point handlers to run items ahead of\r\n * goog.async.nextTick.\r\n */\r\ngoog.async.run.processWorkQueue = function() {\r\n // NOTE: additional work queue items may be added while processing.\r\n var item = null;\r\n while (item = goog.async.run.workQueue_.remove()) {\r\n try {\r\n item.fn.call(item.scope);\r\n } catch (e) {\r\n goog.async.throwException(e);\r\n }\r\n goog.async.run.workQueue_.returnUnused(item);\r\n }\r\n\r\n // There are no more work items, allow processing to be scheduled again.\r\n goog.async.run.workQueueScheduled_ = false;\r\n};\r\n","// Copyright 2013 The Closure Library Authors. All Rights Reserved.\r\n//\r\n// Licensed under the Apache License, Version 2.0 (the \"License\");\r\n// you may not use this file except in compliance with the License.\r\n// You may obtain a copy of the License at\r\n//\r\n// http://www.apache.org/licenses/LICENSE-2.0\r\n//\r\n// Unless required by applicable law or agreed to in writing, software\r\n// distributed under the License is distributed on an \"AS-IS\" BASIS,\r\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n// See the License for the specific language governing permissions and\r\n// limitations under the License.\r\n\r\n/**\r\n * @fileoverview Provides a function to schedule running a function as soon\r\n * as possible after the current JS execution stops and yields to the event\r\n * loop.\r\n *\r\n */\r\n\r\ngoog.provide('goog.async.nextTick');\r\ngoog.provide('goog.async.throwException');\r\n\r\ngoog.require('goog.debug.entryPointRegistry');\r\ngoog.require('goog.dom.TagName');\r\ngoog.require('goog.functions');\r\ngoog.require('goog.labs.userAgent.browser');\r\ngoog.require('goog.labs.userAgent.engine');\r\n\r\n\r\n/**\r\n * Throw an item without interrupting the current execution context. For\r\n * example, if processing a group of items in a loop, sometimes it is useful\r\n * to report an error while still allowing the rest of the batch to be\r\n * processed.\r\n * @param {*} exception\r\n */\r\ngoog.async.throwException = function(exception) {\r\n // Each throw needs to be in its own context.\r\n goog.global.setTimeout(function() { throw exception; }, 0);\r\n};\r\n\r\n\r\n/**\r\n * Fires the provided callbacks as soon as possible after the current JS\r\n * execution context. setTimeout(…, 0) takes at least 4ms when called from\r\n * within another setTimeout(…, 0) for legacy reasons.\r\n *\r\n * This will not schedule the callback as a microtask (i.e. a task that can\r\n * preempt user input or networking callbacks). It is meant to emulate what\r\n * setTimeout(_, 0) would do if it were not throttled. If you desire microtask\r\n * behavior, use {@see goog.Promise} instead.\r\n *\r\n * @param {function(this:SCOPE)} callback Callback function to fire as soon as\r\n * possible.\r\n * @param {SCOPE=} opt_context Object in whose scope to call the listener.\r\n * @param {boolean=} opt_useSetImmediate Avoid the IE workaround that\r\n * ensures correctness at the cost of speed. See comments for details.\r\n * @template SCOPE\r\n */\r\ngoog.async.nextTick = function(callback, opt_context, opt_useSetImmediate) {\r\n var cb = callback;\r\n if (opt_context) {\r\n cb = goog.bind(callback, opt_context);\r\n }\r\n cb = goog.async.nextTick.wrapCallback_(cb);\r\n // Note we do allow callers to also request setImmediate if they are willing\r\n // to accept the possible tradeoffs of incorrectness in exchange for speed.\r\n // The IE fallback of readystate change is much slower. See useSetImmediate_\r\n // for details.\r\n if (goog.isFunction(goog.global.setImmediate) &&\r\n (opt_useSetImmediate || goog.async.nextTick.useSetImmediate_())) {\r\n goog.global.setImmediate(cb);\r\n return;\r\n }\r\n\r\n // Look for and cache the custom fallback version of setImmediate.\r\n if (!goog.async.nextTick.setImmediate_) {\r\n goog.async.nextTick.setImmediate_ =\r\n goog.async.nextTick.getSetImmediateEmulator_();\r\n }\r\n goog.async.nextTick.setImmediate_(cb);\r\n};\r\n\r\n\r\n/**\r\n * Returns whether should use setImmediate implementation currently on window.\r\n *\r\n * window.setImmediate was introduced and currently only supported by IE10+,\r\n * but due to a bug in the implementation it is not guaranteed that\r\n * setImmediate is faster than setTimeout nor that setImmediate N is before\r\n * setImmediate N+1. That is why we do not use the native version if\r\n * available. We do, however, call setImmediate if it is a non-native function\r\n * because that indicates that it has been replaced by goog.testing.MockClock\r\n * which we do want to support.\r\n * See\r\n * http://connect.microsoft.com/IE/feedback/details/801823/setimmediate-and-messagechannel-are-broken-in-ie10\r\n *\r\n * @return {boolean} Whether to use the implementation of setImmediate defined\r\n * on Window.\r\n * @private\r\n * @suppress {missingProperties} For \"Window.prototype.setImmediate\"\r\n */\r\ngoog.async.nextTick.useSetImmediate_ = function() {\r\n // Not a browser environment.\r\n if (!goog.global.Window || !goog.global.Window.prototype) {\r\n return true;\r\n }\r\n\r\n // MS Edge has window.setImmediate natively, but it's not on Window.prototype.\r\n // Also, there's no clean way to detect if the goog.global.setImmediate has\r\n // been replaced by mockClock as its replacement also shows up as \"[native\r\n // code]\" when using toString. Therefore, just always use\r\n // goog.global.setImmediate for Edge. It's unclear if it suffers the same\r\n // issues as IE10/11, but based on\r\n // https://dev.modern.ie/testdrive/demos/setimmediatesorting/\r\n // it seems they've been working to ensure it's WAI.\r\n if (goog.labs.userAgent.browser.isEdge() ||\r\n goog.global.Window.prototype.setImmediate != goog.global.setImmediate) {\r\n // Something redefined setImmediate in which case we decide to use it (This\r\n // is so that we use the mockClock setImmediate).\r\n return true;\r\n }\r\n\r\n return false;\r\n};\r\n\r\n\r\n/**\r\n * Cache for the setImmediate implementation.\r\n * @type {function(function())}\r\n * @private\r\n */\r\ngoog.async.nextTick.setImmediate_;\r\n\r\n\r\n/**\r\n * Determines the best possible implementation to run a function as soon as\r\n * the JS event loop is idle.\r\n * @return {function(function())} The \"setImmediate\" implementation.\r\n * @private\r\n */\r\ngoog.async.nextTick.getSetImmediateEmulator_ = function() {\r\n // Create a private message channel and use it to postMessage empty messages\r\n // to ourselves.\r\n /** @type {!Function|undefined} */\r\n var Channel = goog.global['MessageChannel'];\r\n // If MessageChannel is not available and we are in a browser, implement\r\n // an iframe based polyfill in browsers that have postMessage and\r\n // document.addEventListener. The latter excludes IE8 because it has a\r\n // synchronous postMessage implementation.\r\n if (typeof Channel === 'undefined' && typeof window !== 'undefined' &&\r\n window.postMessage && window.addEventListener &&\r\n // Presto (The old pre-blink Opera engine) has problems with iframes\r\n // and contentWindow.\r\n !goog.labs.userAgent.engine.isPresto()) {\r\n /** @constructor */\r\n Channel = function() {\r\n // Make an empty, invisible iframe.\r\n var iframe = /** @type {!HTMLIFrameElement} */ (\r\n document.createElement(String(goog.dom.TagName.IFRAME)));\r\n iframe.style.display = 'none';\r\n iframe.src = '';\r\n document.documentElement.appendChild(iframe);\r\n var win = iframe.contentWindow;\r\n var doc = win.document;\r\n doc.open();\r\n doc.write('');\r\n doc.close();\r\n // Do not post anything sensitive over this channel, as the workaround for\r\n // pages with file: origin could allow that information to be modified or\r\n // intercepted.\r\n var message = 'callImmediate' + Math.random();\r\n // The same origin policy rejects attempts to postMessage from file: urls\r\n // unless the origin is '*'.\r\n var origin = win.location.protocol == 'file:' ?\r\n '*' :\r\n win.location.protocol + '//' + win.location.host;\r\n var onmessage = goog.bind(function(e) {\r\n // Validate origin and message to make sure that this message was\r\n // intended for us. If the origin is set to '*' (see above) only the\r\n // message needs to match since, for example, '*' != 'file://'. Allowing\r\n // the wildcard is ok, as we are not concerned with security here.\r\n if ((origin != '*' && e.origin != origin) || e.data != message) {\r\n return;\r\n }\r\n this['port1'].onmessage();\r\n }, this);\r\n win.addEventListener('message', onmessage, false);\r\n this['port1'] = {};\r\n this['port2'] = {\r\n postMessage: function() { win.postMessage(message, origin); }\r\n };\r\n };\r\n }\r\n if (typeof Channel !== 'undefined' && !goog.labs.userAgent.browser.isIE()) {\r\n // Exclude all of IE due to\r\n // http://codeforhire.com/2013/09/21/setimmediate-and-messagechannel-broken-on-internet-explorer-10/\r\n // which allows starving postMessage with a busy setTimeout loop.\r\n // This currently affects IE10 and IE11 which would otherwise be able\r\n // to use the postMessage based fallbacks.\r\n var channel = new Channel();\r\n // Use a fifo linked list to call callbacks in the right order.\r\n var head = {};\r\n var tail = head;\r\n channel['port1'].onmessage = function() {\r\n if (goog.isDef(head.next)) {\r\n head = head.next;\r\n var cb = head.cb;\r\n head.cb = null;\r\n cb();\r\n }\r\n };\r\n return function(cb) {\r\n tail.next = {cb: cb};\r\n tail = tail.next;\r\n channel['port2'].postMessage(0);\r\n };\r\n }\r\n // Implementation for IE6 to IE10: Script elements fire an asynchronous\r\n // onreadystatechange event when inserted into the DOM.\r\n if (typeof document !== 'undefined' &&\r\n 'onreadystatechange' in\r\n document.createElement(String(goog.dom.TagName.SCRIPT))) {\r\n return function(cb) {\r\n var script = /** @type {!HTMLScriptElement} */ (\r\n document.createElement(String(goog.dom.TagName.SCRIPT)));\r\n script.onreadystatechange = function() {\r\n // Clean up and call the callback.\r\n script.onreadystatechange = null;\r\n script.parentNode.removeChild(script);\r\n script = null;\r\n cb();\r\n cb = null;\r\n };\r\n document.documentElement.appendChild(script);\r\n };\r\n }\r\n // Fall back to setTimeout with 0. In browsers this creates a delay of 5ms\r\n // or more.\r\n // NOTE(user): This fallback is used for IE11.\r\n return function(cb) {\r\n goog.global.setTimeout(/** @type {function()} */ (cb), 0);\r\n };\r\n};\r\n\r\n\r\n/**\r\n * Helper function that is overrided to protect callbacks with entry point\r\n * monitor if the application monitors entry points.\r\n * @param {function()} callback Callback function to fire as soon as possible.\r\n * @return {function()} The wrapped callback.\r\n * @private\r\n */\r\ngoog.async.nextTick.wrapCallback_ = goog.functions.identity;\r\n\r\n\r\n// Register the callback function as an entry point, so that it can be\r\n// monitored for exception handling, etc. This has to be done in this file\r\n// since it requires special code to handle all browsers.\r\ngoog.debug.entryPointRegistry.register(\r\n /**\r\n * @param {function(!Function): !Function} transformer The transforming\r\n * function.\r\n */\r\n function(transformer) { goog.async.nextTick.wrapCallback_ = transformer; });\r\n","// Copyright 2006 The Closure Library Authors. All Rights Reserved.\r\n//\r\n// Licensed under the Apache License, Version 2.0 (the \"License\");\r\n// you may not use this file except in compliance with the License.\r\n// You may obtain a copy of the License at\r\n//\r\n// http://www.apache.org/licenses/LICENSE-2.0\r\n//\r\n// Unless required by applicable law or agreed to in writing, software\r\n// distributed under the License is distributed on an \"AS-IS\" BASIS,\r\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n// See the License for the specific language governing permissions and\r\n// limitations under the License.\r\n\r\n/**\r\n * @fileoverview A timer class to which other classes and objects can listen on.\r\n * This is only an abstraction above `setInterval`.\r\n *\r\n * @see ../demos/timers.html\r\n */\r\n\r\ngoog.provide('goog.Timer');\r\n\r\ngoog.require('goog.Promise');\r\ngoog.require('goog.events.EventTarget');\r\n\r\n\r\n\r\n/**\r\n * Class for handling timing events.\r\n *\r\n * @param {number=} opt_interval Number of ms between ticks (default: 1ms).\r\n * @param {Object=} opt_timerObject An object that has `setTimeout`,\r\n * `setInterval`, `clearTimeout` and `clearInterval`\r\n * (e.g., `window`).\r\n * @constructor\r\n * @extends {goog.events.EventTarget}\r\n */\r\ngoog.Timer = function(opt_interval, opt_timerObject) {\r\n goog.events.EventTarget.call(this);\r\n\r\n /**\r\n * Number of ms between ticks\r\n * @private {number}\r\n */\r\n this.interval_ = opt_interval || 1;\r\n\r\n /**\r\n * An object that implements `setTimeout`, `setInterval`,\r\n * `clearTimeout` and `clearInterval`. We default to the window\r\n * object. Changing this on {@link goog.Timer.prototype} changes the object\r\n * for all timer instances which can be useful if your environment has some\r\n * other implementation of timers than the `window` object.\r\n * @private {{setTimeout:!Function, clearTimeout:!Function}}\r\n */\r\n this.timerObject_ = /** @type {{setTimeout, clearTimeout}} */ (\r\n opt_timerObject || goog.Timer.defaultTimerObject);\r\n\r\n /**\r\n * Cached `tick_` bound to the object for later use in the timer.\r\n * @private {Function}\r\n * @const\r\n */\r\n this.boundTick_ = goog.bind(this.tick_, this);\r\n\r\n /**\r\n * Firefox browser often fires the timer event sooner (sometimes MUCH sooner)\r\n * than the requested timeout. So we compare the time to when the event was\r\n * last fired, and reschedule if appropriate. See also\r\n * {@link goog.Timer.intervalScale}.\r\n * @private {number}\r\n */\r\n this.last_ = goog.now();\r\n};\r\ngoog.inherits(goog.Timer, goog.events.EventTarget);\r\n\r\n\r\n/**\r\n * Maximum timeout value.\r\n *\r\n * Timeout values too big to fit into a signed 32-bit integer may cause overflow\r\n * in FF, Safari, and Chrome, resulting in the timeout being scheduled\r\n * immediately. It makes more sense simply not to schedule these timeouts, since\r\n * 24.8 days is beyond a reasonable expectation for the browser to stay open.\r\n *\r\n * @private {number}\r\n * @const\r\n */\r\ngoog.Timer.MAX_TIMEOUT_ = 2147483647;\r\n\r\n\r\n/**\r\n * A timer ID that cannot be returned by any known implementation of\r\n * `window.setTimeout`. Passing this value to `window.clearTimeout`\r\n * should therefore be a no-op.\r\n *\r\n * @private {number}\r\n * @const\r\n */\r\ngoog.Timer.INVALID_TIMEOUT_ID_ = -1;\r\n\r\n\r\n/**\r\n * Whether this timer is enabled\r\n * @type {boolean}\r\n */\r\ngoog.Timer.prototype.enabled = false;\r\n\r\n\r\n/**\r\n * An object that implements `setTimeout`, `setInterval`,\r\n * `clearTimeout` and `clearInterval`. We default to the global\r\n * object. Changing `goog.Timer.defaultTimerObject` changes the object for\r\n * all timer instances which can be useful if your environment has some other\r\n * implementation of timers you'd like to use.\r\n * @type {{setTimeout, clearTimeout}}\r\n */\r\ngoog.Timer.defaultTimerObject = goog.global;\r\n\r\n\r\n/**\r\n * Variable that controls the timer error correction. If the timer is called\r\n * before the requested interval times `intervalScale`, which often\r\n * happens on Mozilla, the timer is rescheduled.\r\n * @see {@link #last_}\r\n * @type {number}\r\n */\r\ngoog.Timer.intervalScale = 0.8;\r\n\r\n\r\n/**\r\n * Variable for storing the result of `setInterval`.\r\n * @private {?number}\r\n */\r\ngoog.Timer.prototype.timer_ = null;\r\n\r\n\r\n/**\r\n * Gets the interval of the timer.\r\n * @return {number} interval Number of ms between ticks.\r\n */\r\ngoog.Timer.prototype.getInterval = function() {\r\n return this.interval_;\r\n};\r\n\r\n\r\n/**\r\n * Sets the interval of the timer.\r\n * @param {number} interval Number of ms between ticks.\r\n */\r\ngoog.Timer.prototype.setInterval = function(interval) {\r\n this.interval_ = interval;\r\n if (this.timer_ && this.enabled) {\r\n // Stop and then start the timer to reset the interval.\r\n this.stop();\r\n this.start();\r\n } else if (this.timer_) {\r\n this.stop();\r\n }\r\n};\r\n\r\n\r\n/**\r\n * Callback for the `setTimeout` used by the timer.\r\n * @private\r\n */\r\ngoog.Timer.prototype.tick_ = function() {\r\n if (this.enabled) {\r\n var elapsed = goog.now() - this.last_;\r\n if (elapsed > 0 && elapsed < this.interval_ * goog.Timer.intervalScale) {\r\n this.timer_ = this.timerObject_.setTimeout(\r\n this.boundTick_, this.interval_ - elapsed);\r\n return;\r\n }\r\n\r\n // Prevents setInterval from registering a duplicate timeout when called\r\n // in the timer event handler.\r\n if (this.timer_) {\r\n this.timerObject_.clearTimeout(this.timer_);\r\n this.timer_ = null;\r\n }\r\n\r\n this.dispatchTick();\r\n // The timer could be stopped in the timer event handler.\r\n if (this.enabled) {\r\n // Stop and start to ensure there is always only one timeout even if\r\n // start is called in the timer event handler.\r\n this.stop();\r\n this.start();\r\n }\r\n }\r\n};\r\n\r\n\r\n/**\r\n * Dispatches the TICK event. This is its own method so subclasses can override.\r\n */\r\ngoog.Timer.prototype.dispatchTick = function() {\r\n this.dispatchEvent(goog.Timer.TICK);\r\n};\r\n\r\n\r\n/**\r\n * Starts the timer.\r\n */\r\ngoog.Timer.prototype.start = function() {\r\n this.enabled = true;\r\n\r\n // If there is no interval already registered, start it now\r\n if (!this.timer_) {\r\n // IMPORTANT!\r\n // window.setInterval in FireFox has a bug - it fires based on\r\n // absolute time, rather than on relative time. What this means\r\n // is that if a computer is sleeping/hibernating for 24 hours\r\n // and the timer interval was configured to fire every 1000ms,\r\n // then after the PC wakes up the timer will fire, in rapid\r\n // succession, 3600*24 times.\r\n // This bug is described here and is already fixed, but it will\r\n // take time to propagate, so for now I am switching this over\r\n // to setTimeout logic.\r\n // https://bugzilla.mozilla.org/show_bug.cgi?id=376643\r\n //\r\n this.timer_ = this.timerObject_.setTimeout(this.boundTick_, this.interval_);\r\n this.last_ = goog.now();\r\n }\r\n};\r\n\r\n\r\n/**\r\n * Stops the timer.\r\n */\r\ngoog.Timer.prototype.stop = function() {\r\n this.enabled = false;\r\n if (this.timer_) {\r\n this.timerObject_.clearTimeout(this.timer_);\r\n this.timer_ = null;\r\n }\r\n};\r\n\r\n\r\n/** @override */\r\ngoog.Timer.prototype.disposeInternal = function() {\r\n goog.Timer.superClass_.disposeInternal.call(this);\r\n this.stop();\r\n delete this.timerObject_;\r\n};\r\n\r\n\r\n/**\r\n * Constant for the timer's event type.\r\n * @const\r\n */\r\ngoog.Timer.TICK = 'tick';\r\n\r\n\r\n/**\r\n * Calls the given function once, after the optional pause.\r\n * <p>\r\n * The function is always called asynchronously, even if the delay is 0. This\r\n * is a common trick to schedule a function to run after a batch of browser\r\n * event processing.\r\n *\r\n * @param {function(this:SCOPE)|{handleEvent:function()}|null} listener Function\r\n * or object that has a handleEvent method.\r\n * @param {number=} opt_delay Milliseconds to wait; default is 0.\r\n * @param {SCOPE=} opt_handler Object in whose scope to call the listener.\r\n * @return {number} A handle to the timer ID.\r\n * @template SCOPE\r\n */\r\ngoog.Timer.callOnce = function(listener, opt_delay, opt_handler) {\r\n if (goog.isFunction(listener)) {\r\n if (opt_handler) {\r\n listener = goog.bind(listener, opt_handler);\r\n }\r\n } else if (listener && typeof listener.handleEvent == 'function') {\r\n // using typeof to prevent strict js warning\r\n listener = goog.bind(listener.handleEvent, listener);\r\n } else {\r\n throw new Error('Invalid listener argument');\r\n }\r\n\r\n if (Number(opt_delay) > goog.Timer.MAX_TIMEOUT_) {\r\n // Timeouts greater than MAX_INT return immediately due to integer\r\n // overflow in many browsers. Since MAX_INT is 24.8 days, just don't\r\n // schedule anything at all.\r\n return goog.Timer.INVALID_TIMEOUT_ID_;\r\n } else {\r\n return goog.Timer.defaultTimerObject.setTimeout(listener, opt_delay || 0);\r\n }\r\n};\r\n\r\n\r\n/**\r\n * Clears a timeout initiated by {@link #callOnce}.\r\n * @param {?number} timerId A timer ID.\r\n */\r\ngoog.Timer.clear = function(timerId) {\r\n goog.Timer.defaultTimerObject.clearTimeout(timerId);\r\n};\r\n\r\n\r\n/**\r\n * @param {number} delay Milliseconds to wait.\r\n * @param {(RESULT|goog.Thenable<RESULT>|Thenable)=} opt_result The value\r\n * with which the promise will be resolved.\r\n * @return {!goog.Promise<RESULT>} A promise that will be resolved after\r\n * the specified delay, unless it is canceled first.\r\n * @template RESULT\r\n */\r\ngoog.Timer.promise = function(delay, opt_result) {\r\n var timerKey = null;\r\n return new goog\r\n .Promise(function(resolve, reject) {\r\n timerKey =\r\n goog.Timer.callOnce(function() { resolve(opt_result); }, delay);\r\n if (timerKey == goog.Timer.INVALID_TIMEOUT_ID_) {\r\n reject(new Error('Failed to schedule timer.'));\r\n }\r\n })\r\n .thenCatch(function(error) {\r\n // Clear the timer. The most likely reason is \"cancel\" signal.\r\n goog.Timer.clear(timerKey);\r\n throw error;\r\n });\r\n};\r\n","// Copyright 2007 The Closure Library Authors. All Rights Reserved.\r\n//\r\n// Licensed under the Apache License, Version 2.0 (the \"License\");\r\n// you may not use this file except in compliance with the License.\r\n// You may obtain a copy of the License at\r\n//\r\n// http://www.apache.org/licenses/LICENSE-2.0\r\n//\r\n// Unless required by applicable law or agreed to in writing, software\r\n// distributed under the License is distributed on an \"AS-IS\" BASIS,\r\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n// See the License for the specific language governing permissions and\r\n// limitations under the License.\r\n\r\n/**\r\n * @fileoverview Definition of the goog.async.Throttle class.\r\n *\r\n * @see ../demos/timers.html\r\n */\r\n\r\ngoog.provide('goog.Throttle');\r\ngoog.provide('goog.async.Throttle');\r\n\r\ngoog.require('goog.Disposable');\r\ngoog.require('goog.Timer');\r\n\r\n\r\n\r\n/**\r\n * Throttle will perform an action that is passed in no more than once\r\n * per interval (specified in milliseconds). If it gets multiple signals\r\n * to perform the action while it is waiting, it will only perform the action\r\n * once at the end of the interval.\r\n * @param {function(this: T, ...?)} listener Function to callback when the\r\n * action is triggered.\r\n * @param {number} interval Interval over which to throttle. The listener can\r\n * only be called once per interval.\r\n * @param {T=} opt_handler Object in whose scope to call the listener.\r\n * @constructor\r\n * @struct\r\n * @extends {goog.Disposable}\r\n * @final\r\n * @template T\r\n */\r\ngoog.async.Throttle = function(listener, interval, opt_handler) {\r\n goog.async.Throttle.base(this, 'constructor');\r\n\r\n /**\r\n * Function to callback\r\n * @type {function(this: T, ...?)}\r\n * @private\r\n */\r\n this.listener_ =\r\n opt_handler != null ? goog.bind(listener, opt_handler) : listener;\r\n\r\n /**\r\n * Interval for the throttle time\r\n * @type {number}\r\n * @private\r\n */\r\n this.interval_ = interval;\r\n\r\n /**\r\n * Cached callback function invoked after the throttle timeout completes\r\n * @type {Function}\r\n * @private\r\n */\r\n this.callback_ = goog.bind(this.onTimer_, this);\r\n\r\n /**\r\n * The last arguments passed into `fire`.\r\n * @private {!IArrayLike}\r\n */\r\n this.args_ = [];\r\n};\r\ngoog.inherits(goog.async.Throttle, goog.Disposable);\r\n\r\n\r\n\r\n/**\r\n * A deprecated alias.\r\n * @deprecated Use goog.async.Throttle instead.\r\n * @constructor\r\n * @final\r\n */\r\ngoog.Throttle = goog.async.Throttle;\r\n\r\n\r\n/**\r\n * Indicates that the action is pending and needs to be fired.\r\n * @type {boolean}\r\n * @private\r\n */\r\ngoog.async.Throttle.prototype.shouldFire_ = false;\r\n\r\n\r\n/**\r\n * Indicates the count of nested pauses currently in effect on the throttle.\r\n * When this count is not zero, fired actions will be postponed until the\r\n * throttle is resumed enough times to drop the pause count to zero.\r\n * @type {number}\r\n * @private\r\n */\r\ngoog.async.Throttle.prototype.pauseCount_ = 0;\r\n\r\n\r\n/**\r\n * Timer for scheduling the next callback\r\n * @type {?number}\r\n * @private\r\n */\r\ngoog.async.Throttle.prototype.timer_ = null;\r\n\r\n\r\n/**\r\n * Notifies the throttle that the action has happened. It will throttle the call\r\n * so that the callback is not called too often according to the interval\r\n * parameter passed to the constructor, passing the arguments from the last call\r\n * of this function into the throttled function.\r\n * @param {...?} var_args Arguments to pass on to the throttled function.\r\n */\r\ngoog.async.Throttle.prototype.fire = function(var_args) {\r\n this.args_ = arguments;\r\n if (!this.timer_ && !this.pauseCount_) {\r\n this.doAction_();\r\n } else {\r\n this.shouldFire_ = true;\r\n }\r\n};\r\n\r\n\r\n/**\r\n * Cancels any pending action callback. The throttle can be restarted by\r\n * calling {@link #fire}.\r\n */\r\ngoog.async.Throttle.prototype.stop = function() {\r\n if (this.timer_) {\r\n goog.Timer.clear(this.timer_);\r\n this.timer_ = null;\r\n this.shouldFire_ = false;\r\n this.args_ = [];\r\n }\r\n};\r\n\r\n\r\n/**\r\n * Pauses the throttle. All pending and future action callbacks will be\r\n * delayed until the throttle is resumed. Pauses can be nested.\r\n */\r\ngoog.async.Throttle.prototype.pause = function() {\r\n this.pauseCount_++;\r\n};\r\n\r\n\r\n/**\r\n * Resumes the throttle. If doing so drops the pausing count to zero, pending\r\n * action callbacks will be executed as soon as possible, but still no sooner\r\n * than an interval's delay after the previous call. Future action callbacks\r\n * will be executed as normal.\r\n */\r\ngoog.async.Throttle.prototype.resume = function() {\r\n this.pauseCount_--;\r\n if (!this.pauseCount_ && this.shouldFire_ && !this.timer_) {\r\n this.shouldFire_ = false;\r\n this.doAction_();\r\n }\r\n};\r\n\r\n\r\n/** @override */\r\ngoog.async.Throttle.prototype.disposeInternal = function() {\r\n goog.async.Throttle.base(this, 'disposeInternal');\r\n this.stop();\r\n};\r\n\r\n\r\n/**\r\n * Handler for the timer to fire the throttle\r\n * @private\r\n */\r\ngoog.async.Throttle.prototype.onTimer_ = function() {\r\n this.timer_ = null;\r\n\r\n if (this.shouldFire_ && !this.pauseCount_) {\r\n this.shouldFire_ = false;\r\n this.doAction_();\r\n }\r\n};\r\n\r\n\r\n/**\r\n * Calls the callback\r\n * @private\r\n */\r\ngoog.async.Throttle.prototype.doAction_ = function() {\r\n this.timer_ = goog.Timer.callOnce(this.callback_, this.interval_);\r\n this.listener_.apply(null, this.args_);\r\n};\r\n","// Copyright 2005 The Closure Library Authors. All Rights Reserved.\r\n//\r\n// Licensed under the Apache License, Version 2.0 (the \"License\");\r\n// you may not use this file except in compliance with the License.\r\n// You may obtain a copy of the License at\r\n//\r\n// http://www.apache.org/licenses/LICENSE-2.0\r\n//\r\n// Unless required by applicable law or agreed to in writing, software\r\n// distributed under the License is distributed on an \"AS-IS\" BASIS,\r\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n// See the License for the specific language governing permissions and\r\n// limitations under the License.\r\n\r\n/**\r\n * @fileoverview Class to create objects which want to handle multiple events\r\n * and have their listeners easily cleaned up via a dispose method.\r\n *\r\n * Example:\r\n * <pre>\r\n * function Something() {\r\n * Something.base(this);\r\n *\r\n * ... set up object ...\r\n *\r\n * // Add event listeners\r\n * this.listen(this.starEl, goog.events.EventType.CLICK, this.handleStar);\r\n * this.listen(this.headerEl, goog.events.EventType.CLICK, this.expand);\r\n * this.listen(this.collapseEl, goog.events.EventType.CLICK, this.collapse);\r\n * this.listen(this.infoEl, goog.events.EventType.MOUSEOVER, this.showHover);\r\n * this.listen(this.infoEl, goog.events.EventType.MOUSEOUT, this.hideHover);\r\n * }\r\n * goog.inherits(Something, goog.events.EventHandler);\r\n *\r\n * Something.prototype.disposeInternal = function() {\r\n * Something.base(this, 'disposeInternal');\r\n * goog.dom.removeNode(this.container);\r\n * };\r\n *\r\n *\r\n * // Then elsewhere:\r\n *\r\n * var activeSomething = null;\r\n * function openSomething() {\r\n * activeSomething = new Something();\r\n * }\r\n *\r\n * function closeSomething() {\r\n * if (activeSomething) {\r\n * activeSomething.dispose(); // Remove event listeners\r\n * activeSomething = null;\r\n * }\r\n * }\r\n * </pre>\r\n *\r\n */\r\n\r\ngoog.provide('goog.events.EventHandler');\r\n\r\ngoog.require('goog.Disposable');\r\ngoog.require('goog.events');\r\ngoog.require('goog.object');\r\n\r\ngoog.forwardDeclare('goog.events.EventWrapper');\r\n\r\n\r\n\r\n/**\r\n * Super class for objects that want to easily manage a number of event\r\n * listeners. It allows a short cut to listen and also provides a quick way\r\n * to remove all events listeners belonging to this object.\r\n * @param {SCOPE=} opt_scope Object in whose scope to call the listeners.\r\n * @constructor\r\n * @extends {goog.Disposable}\r\n * @template SCOPE\r\n */\r\ngoog.events.EventHandler = function(opt_scope) {\r\n goog.Disposable.call(this);\r\n // TODO(mknichel): Rename this to this.scope_ and fix the classes in google3\r\n // that access this private variable. :(\r\n this.handler_ = opt_scope;\r\n\r\n /**\r\n * Keys for events that are being listened to.\r\n * @type {!Object<!goog.events.Key>}\r\n * @private\r\n */\r\n this.keys_ = {};\r\n};\r\ngoog.inherits(goog.events.EventHandler, goog.Disposable);\r\n\r\n\r\n/**\r\n * Utility array used to unify the cases of listening for an array of types\r\n * and listening for a single event, without using recursion or allocating\r\n * an array each time.\r\n * @type {!Array<string>}\r\n * @const\r\n * @private\r\n */\r\ngoog.events.EventHandler.typeArray_ = [];\r\n\r\n\r\n/**\r\n * Listen to an event on a Listenable. If the function is omitted then the\r\n * EventHandler's handleEvent method will be used.\r\n * @param {goog.events.ListenableType} src Event source.\r\n * @param {string|Array<string>|\r\n * !goog.events.EventId<EVENTOBJ>|!Array<!goog.events.EventId<EVENTOBJ>>}\r\n * type Event type to listen for or array of event types.\r\n * @param {function(this:SCOPE, EVENTOBJ):?|{handleEvent:function(?):?}|null=}\r\n * opt_fn Optional callback function to be used as the listener or an object\r\n * with handleEvent function.\r\n * @param {(boolean|!AddEventListenerOptions)=} opt_options\r\n * @return {THIS} This object, allowing for chaining of calls.\r\n * @this {THIS}\r\n * @template EVENTOBJ, THIS\r\n */\r\ngoog.events.EventHandler.prototype.listen = function(\r\n src, type, opt_fn, opt_options) {\r\n var self = /** @type {!goog.events.EventHandler} */ (this);\r\n return self.listen_(src, type, opt_fn, opt_options);\r\n};\r\n\r\n\r\n/**\r\n * Listen to an event on a Listenable. If the function is omitted then the\r\n * EventHandler's handleEvent method will be used.\r\n * @param {goog.events.ListenableType} src Event source.\r\n * @param {string|Array<string>|\r\n * !goog.events.EventId<EVENTOBJ>|!Array<!goog.events.EventId<EVENTOBJ>>}\r\n * type Event type to listen for or array of event types.\r\n * @param {function(this:T, EVENTOBJ):?|{handleEvent:function(this:T, ?):?}|\r\n * null|undefined} fn Optional callback function to be used as the\r\n * listener or an object with handleEvent function.\r\n * @param {boolean|!AddEventListenerOptions|undefined} options\r\n * @param {T} scope Object in whose scope to call the listener.\r\n * @return {THIS} This object, allowing for chaining of calls.\r\n * @this {THIS}\r\n * @template T, EVENTOBJ, THIS\r\n */\r\ngoog.events.EventHandler.prototype.listenWithScope = function(\r\n src, type, fn, options, scope) {\r\n var self = /** @type {!goog.events.EventHandler} */ (this);\r\n // TODO(mknichel): Deprecate this function.\r\n return self.listen_(src, type, fn, options, scope);\r\n};\r\n\r\n\r\n/**\r\n * Listen to an event on a Listenable. If the function is omitted then the\r\n * EventHandler's handleEvent method will be used.\r\n * @param {goog.events.ListenableType} src Event source.\r\n * @param {string|Array<string>|\r\n * !goog.events.EventId<EVENTOBJ>|!Array<!goog.events.EventId<EVENTOBJ>>}\r\n * type Event type to listen for or array of event types.\r\n * @param {function(EVENTOBJ):?|{handleEvent:function(?):?}|null=} opt_fn\r\n * Optional callback function to be used as the listener or an object with\r\n * handleEvent function.\r\n * @param {(boolean|!AddEventListenerOptions)=} opt_options\r\n * @param {Object=} opt_scope Object in whose scope to call the listener.\r\n * @return {THIS} This object, allowing for chaining of calls.\r\n * @this {THIS}\r\n * @template EVENTOBJ, THIS\r\n * @private\r\n */\r\ngoog.events.EventHandler.prototype.listen_ = function(\r\n src, type, opt_fn, opt_options, opt_scope) {\r\n var self = /** @type {!goog.events.EventHandler} */ (this);\r\n if (!goog.isArray(type)) {\r\n if (type) {\r\n goog.events.EventHandler.typeArray_[0] = type.toString();\r\n }\r\n type = goog.events.EventHandler.typeArray_;\r\n }\r\n for (var i = 0; i < type.length; i++) {\r\n var listenerObj = goog.events.listen(\r\n src, type[i], opt_fn || self.handleEvent, opt_options || false,\r\n opt_scope || self.handler_ || self);\r\n\r\n if (!listenerObj) {\r\n // When goog.events.listen run on OFF_AND_FAIL or OFF_AND_SILENT\r\n // (goog.events.CaptureSimulationMode) in IE8-, it will return null\r\n // value.\r\n return self;\r\n }\r\n\r\n var key = listenerObj.key;\r\n self.keys_[key] = listenerObj;\r\n }\r\n\r\n return self;\r\n};\r\n\r\n\r\n/**\r\n * Listen to an event on a Listenable. If the function is omitted, then the\r\n * EventHandler's handleEvent method will be used. After the event has fired the\r\n * event listener is removed from the target. If an array of event types is\r\n * provided, each event type will be listened to once.\r\n * @param {goog.events.ListenableType} src Event source.\r\n * @param {string|Array<string>|\r\n * !goog.events.EventId<EVENTOBJ>|!Array<!goog.events.EventId<EVENTOBJ>>}\r\n * type Event type to listen for or array of event types.\r\n * @param {function(this:SCOPE, EVENTOBJ):?|{handleEvent:function(?):?}|null=}\r\n * opt_fn\r\n * Optional callback function to be used as the listener or an object with\r\n * handleEvent function.\r\n * @param {(boolean|!AddEventListenerOptions)=} opt_options\r\n * @return {THIS} This object, allowing for chaining of calls.\r\n * @this {THIS}\r\n * @template EVENTOBJ, THIS\r\n */\r\ngoog.events.EventHandler.prototype.listenOnce = function(\r\n src, type, opt_fn, opt_options) {\r\n var self = /** @type {!goog.events.EventHandler} */ (this);\r\n return self.listenOnce_(src, type, opt_fn, opt_options);\r\n};\r\n\r\n\r\n/**\r\n * Listen to an event on a Listenable. If the function is omitted, then the\r\n * EventHandler's handleEvent method will be used. After the event has fired the\r\n * event listener is removed from the target. If an array of event types is\r\n * provided, each event type will be listened to once.\r\n * @param {goog.events.ListenableType} src Event source.\r\n * @param {string|Array<string>|\r\n * !goog.events.EventId<EVENTOBJ>|!Array<!goog.events.EventId<EVENTOBJ>>}\r\n * type Event type to listen for or array of event types.\r\n * @param {function(this:T, EVENTOBJ):?|{handleEvent:function(this:T, ?):?}|\r\n * null|undefined} fn Optional callback function to be used as the\r\n * listener or an object with handleEvent function.\r\n * @param {boolean|undefined} capture Optional whether to use capture phase.\r\n * @param {T} scope Object in whose scope to call the listener.\r\n * @return {THIS} This object, allowing for chaining of calls.\r\n * @this {THIS}\r\n * @template T, EVENTOBJ, THIS\r\n */\r\ngoog.events.EventHandler.prototype.listenOnceWithScope = function(\r\n src, type, fn, capture, scope) {\r\n var self = /** @type {!goog.events.EventHandler} */ (this);\r\n // TODO(mknichel): Deprecate this function.\r\n return self.listenOnce_(src, type, fn, capture, scope);\r\n};\r\n\r\n\r\n/**\r\n * Listen to an event on a Listenable. If the function is omitted, then the\r\n * EventHandler's handleEvent method will be used. After the event has fired\r\n * the event listener is removed from the target. If an array of event types is\r\n * provided, each event type will be listened to once.\r\n * @param {goog.events.ListenableType} src Event source.\r\n * @param {string|Array<string>|\r\n * !goog.events.EventId<EVENTOBJ>|!Array<!goog.events.EventId<EVENTOBJ>>}\r\n * type Event type to listen for or array of event types.\r\n * @param {function(EVENTOBJ):?|{handleEvent:function(?):?}|null=} opt_fn\r\n * Optional callback function to be used as the listener or an object with\r\n * handleEvent function.\r\n * @param {(boolean|!AddEventListenerOptions)=} opt_options\r\n * @param {Object=} opt_scope Object in whose scope to call the listener.\r\n * @return {THIS} This object, allowing for chaining of calls.\r\n * @this {THIS}\r\n * @template EVENTOBJ, THIS\r\n * @private\r\n */\r\ngoog.events.EventHandler.prototype.listenOnce_ = function(\r\n src, type, opt_fn, opt_options, opt_scope) {\r\n var self = /** @type {!goog.events.EventHandler} */ (this);\r\n if (goog.isArray(type)) {\r\n for (var i = 0; i < type.length; i++) {\r\n self.listenOnce_(src, type[i], opt_fn, opt_options, opt_scope);\r\n }\r\n } else {\r\n var listenerObj = goog.events.listenOnce(\r\n src, type, opt_fn || self.handleEvent, opt_options,\r\n opt_scope || self.handler_ || self);\r\n if (!listenerObj) {\r\n // When goog.events.listen run on OFF_AND_FAIL or OFF_AND_SILENT\r\n // (goog.events.CaptureSimulationMode) in IE8-, it will return null\r\n // value.\r\n return self;\r\n }\r\n\r\n var key = listenerObj.key;\r\n self.keys_[key] = listenerObj;\r\n }\r\n\r\n return self;\r\n};\r\n\r\n\r\n/**\r\n * Adds an event listener with a specific event wrapper on a DOM Node or an\r\n * object that has implemented {@link goog.events.EventTarget}. A listener can\r\n * only be added once to an object.\r\n *\r\n * @param {EventTarget|goog.events.EventTarget} src The node to listen to\r\n * events on.\r\n * @param {goog.events.EventWrapper} wrapper Event wrapper to use.\r\n * @param {function(this:SCOPE, ?):?|{handleEvent:function(?):?}|null} listener\r\n * Callback method, or an object with a handleEvent function.\r\n * @param {boolean=} opt_capt Whether to fire in capture phase (defaults to\r\n * false).\r\n * @return {THIS} This object, allowing for chaining of calls.\r\n * @this {THIS}\r\n * @template THIS\r\n */\r\ngoog.events.EventHandler.prototype.listenWithWrapper = function(\r\n src, wrapper, listener, opt_capt) {\r\n var self = /** @type {!goog.events.EventHandler} */ (this);\r\n // TODO(mknichel): Remove the opt_scope from this function and then\r\n // templatize it.\r\n return self.listenWithWrapper_(src, wrapper, listener, opt_capt);\r\n};\r\n\r\n\r\n/**\r\n * Adds an event listener with a specific event wrapper on a DOM Node or an\r\n * object that has implemented {@link goog.events.EventTarget}. A listener can\r\n * only be added once to an object.\r\n *\r\n * @param {EventTarget|goog.events.EventTarget} src The node to listen to\r\n * events on.\r\n * @param {goog.events.EventWrapper} wrapper Event wrapper to use.\r\n * @param {function(this:T, ?):?|{handleEvent:function(this:T, ?):?}|null}\r\n * listener Optional callback function to be used as the\r\n * listener or an object with handleEvent function.\r\n * @param {boolean|undefined} capture Optional whether to use capture phase.\r\n * @param {T} scope Object in whose scope to call the listener.\r\n * @return {THIS} This object, allowing for chaining of calls.\r\n * @this {THIS}\r\n * @template T, THIS\r\n */\r\ngoog.events.EventHandler.prototype.listenWithWrapperAndScope = function(\r\n src, wrapper, listener, capture, scope) {\r\n var self = /** @type {!goog.events.EventHandler} */ (this);\r\n // TODO(mknichel): Deprecate this function.\r\n return self.listenWithWrapper_(src, wrapper, listener, capture, scope);\r\n};\r\n\r\n\r\n/**\r\n * Adds an event listener with a specific event wrapper on a DOM Node or an\r\n * object that has implemented {@link goog.events.EventTarget}. A listener can\r\n * only be added once to an object.\r\n *\r\n * @param {EventTarget|goog.events.EventTarget} src The node to listen to\r\n * events on.\r\n * @param {goog.events.EventWrapper} wrapper Event wrapper to use.\r\n * @param {function(?):?|{handleEvent:function(?):?}|null} listener Callback\r\n * method, or an object with a handleEvent function.\r\n * @param {boolean=} opt_capt Whether to fire in capture phase (defaults to\r\n * false).\r\n * @param {Object=} opt_scope Element in whose scope to call the listener.\r\n * @return {THIS} This object, allowing for chaining of calls.\r\n * @this {THIS}\r\n * @template THIS\r\n * @private\r\n */\r\ngoog.events.EventHandler.prototype.listenWithWrapper_ = function(\r\n src, wrapper, listener, opt_capt, opt_scope) {\r\n var self = /** @type {!goog.events.EventHandler} */ (this);\r\n wrapper.listen(\r\n src, listener, opt_capt, opt_scope || self.handler_ || self, self);\r\n return self;\r\n};\r\n\r\n\r\n/**\r\n * @return {number} Number of listeners registered by this handler.\r\n */\r\ngoog.events.EventHandler.prototype.getListenerCount = function() {\r\n var count = 0;\r\n for (var key in this.keys_) {\r\n if (Object.prototype.hasOwnProperty.call(this.keys_, key)) {\r\n count++;\r\n }\r\n }\r\n return count;\r\n};\r\n\r\n\r\n/**\r\n * Unlistens on an event.\r\n * @param {goog.events.ListenableType} src Event source.\r\n * @param {string|Array<string>|\r\n * !goog.events.EventId<EVENTOBJ>|!Array<!goog.events.EventId<EVENTOBJ>>}\r\n * type Event type or array of event types to unlisten to.\r\n * @param {function(this:?, EVENTOBJ):?|{handleEvent:function(?):?}|null=}\r\n * opt_fn Optional callback function to be used as the listener or an object\r\n * with handleEvent function.\r\n * @param {(boolean|!EventListenerOptions)=} opt_options\r\n * @param {Object=} opt_scope Object in whose scope to call the listener.\r\n * @return {THIS} This object, allowing for chaining of calls.\r\n * @this {THIS}\r\n * @template EVENTOBJ, THIS\r\n */\r\ngoog.events.EventHandler.prototype.unlisten = function(\r\n src, type, opt_fn, opt_options, opt_scope) {\r\n var self = /** @type {!goog.events.EventHandler} */ (this);\r\n if (goog.isArray(type)) {\r\n for (var i = 0; i < type.length; i++) {\r\n self.unlisten(src, type[i], opt_fn, opt_options, opt_scope);\r\n }\r\n } else {\r\n var capture =\r\n goog.isObject(opt_options) ? !!opt_options.capture : !!opt_options;\r\n var listener = goog.events.getListener(\r\n src, type, opt_fn || self.handleEvent, capture,\r\n opt_scope || self.handler_ || self);\r\n\r\n if (listener) {\r\n goog.events.unlistenByKey(listener);\r\n delete self.keys_[listener.key];\r\n }\r\n }\r\n\r\n return self;\r\n};\r\n\r\n\r\n/**\r\n * Removes an event listener which was added with listenWithWrapper().\r\n *\r\n * @param {EventTarget|goog.events.EventTarget} src The target to stop\r\n * listening to events on.\r\n * @param {goog.events.EventWrapper} wrapper Event wrapper to use.\r\n * @param {function(?):?|{handleEvent:function(?):?}|null} listener The\r\n * listener function to remove.\r\n * @param {boolean=} opt_capt In DOM-compliant browsers, this determines\r\n * whether the listener is fired during the capture or bubble phase of the\r\n * event.\r\n * @param {Object=} opt_scope Element in whose scope to call the listener.\r\n * @return {THIS} This object, allowing for chaining of calls.\r\n * @this {THIS}\r\n * @template THIS\r\n */\r\ngoog.events.EventHandler.prototype.unlistenWithWrapper = function(\r\n src, wrapper, listener, opt_capt, opt_scope) {\r\n var self = /** @type {!goog.events.EventHandler} */ (this);\r\n wrapper.unlisten(\r\n src, listener, opt_capt, opt_scope || self.handler_ || self, self);\r\n return self;\r\n};\r\n\r\n\r\n/**\r\n * Unlistens to all events.\r\n */\r\ngoog.events.EventHandler.prototype.removeAll = function() {\r\n goog.object.forEach(this.keys_, function(listenerObj, key) {\r\n if (this.keys_.hasOwnProperty(key)) {\r\n goog.events.unlistenByKey(listenerObj);\r\n }\r\n }, this);\r\n\r\n this.keys_ = {};\r\n};\r\n\r\n\r\n/**\r\n * Disposes of this EventHandler and removes all listeners that it registered.\r\n * @override\r\n * @protected\r\n */\r\ngoog.events.EventHandler.prototype.disposeInternal = function() {\r\n goog.events.EventHandler.superClass_.disposeInternal.call(this);\r\n this.removeAll();\r\n};\r\n\r\n\r\n/**\r\n * Default event handler\r\n * @param {goog.events.Event} e Event object.\r\n */\r\ngoog.events.EventHandler.prototype.handleEvent = function(e) {\r\n throw new Error('EventHandler.handleEvent not implemented');\r\n};\r\n","// Copyright 2006 The Closure Library Authors. All Rights Reserved.\r\n//\r\n// Licensed under the Apache License, Version 2.0 (the \"License\");\r\n// you may not use this file except in compliance with the License.\r\n// You may obtain a copy of the License at\r\n//\r\n// http://www.apache.org/licenses/LICENSE-2.0\r\n//\r\n// Unless required by applicable law or agreed to in writing, software\r\n// distributed under the License is distributed on an \"AS-IS\" BASIS,\r\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n// See the License for the specific language governing permissions and\r\n// limitations under the License.\r\n\r\n/**\r\n * @fileoverview Provides a utility for tracing and debugging WebChannel\r\n * requests.\r\n */\r\n\r\n\r\ngoog.provide('goog.labs.net.webChannel.WebChannelDebug');\r\n\r\ngoog.require('goog.json');\r\ngoog.require('goog.log');\r\n\r\ngoog.forwardDeclare('goog.Uri');\r\ngoog.forwardDeclare('goog.net.XmlHttp.ReadyState');\r\n\r\n\r\n\r\n/**\r\n * Logs and keeps a buffer of debugging info for the Channel.\r\n *\r\n * @constructor\r\n * @struct\r\n * @final\r\n */\r\ngoog.labs.net.webChannel.WebChannelDebug = function() {\r\n /**\r\n * The logger instance.\r\n * @const\r\n * @private {?goog.log.Logger}\r\n */\r\n this.logger_ = goog.log.getLogger('goog.labs.net.webChannel.WebChannelDebug');\r\n\r\n /**\r\n * Whether to enable redact. Defaults to true.\r\n * @private {boolean}\r\n */\r\n this.redactEnabled_ = true;\r\n};\r\n\r\n\r\ngoog.scope(function() {\r\nvar WebChannelDebug = goog.labs.net.webChannel.WebChannelDebug;\r\n\r\n\r\n/**\r\n * Turns off redact.\r\n */\r\nWebChannelDebug.prototype.disableRedact = function() {\r\n this.redactEnabled_ = false;\r\n};\r\n\r\n\r\n/**\r\n * Logs that the browser went offline during the lifetime of a request.\r\n * @param {goog.Uri} url The URL being requested.\r\n */\r\nWebChannelDebug.prototype.browserOfflineResponse = function(url) {\r\n this.info(function() {\r\n return 'BROWSER_OFFLINE: ' + url;\r\n });\r\n};\r\n\r\n\r\n/**\r\n * Logs an XmlHttp request..\r\n * @param {string} verb The request type (GET/POST).\r\n * @param {goog.Uri} uri The request destination.\r\n * @param {string|number|undefined} id The request id.\r\n * @param {number} attempt Which attempt # the request was.\r\n * @param {?string} postData The data posted in the request.\r\n */\r\nWebChannelDebug.prototype.xmlHttpChannelRequest = function(\r\n verb, uri, id, attempt, postData) {\r\n var self = this;\r\n this.info(function() {\r\n return 'XMLHTTP REQ (' + id + ') [attempt ' + attempt + ']: ' + verb +\r\n '\\n' + uri + '\\n' + self.maybeRedactPostData_(postData);\r\n });\r\n};\r\n\r\n\r\n/**\r\n * Logs the meta data received from an XmlHttp request.\r\n * @param {string} verb The request type (GET/POST).\r\n * @param {goog.Uri} uri The request destination.\r\n * @param {string|number|undefined} id The request id.\r\n * @param {number} attempt Which attempt # the request was.\r\n * @param {goog.net.XmlHttp.ReadyState} readyState The ready state.\r\n * @param {number} statusCode The HTTP status code.\r\n */\r\nWebChannelDebug.prototype.xmlHttpChannelResponseMetaData = function(\r\n verb, uri, id, attempt, readyState, statusCode) {\r\n this.info(function() {\r\n return 'XMLHTTP RESP (' + id + ') [ attempt ' + attempt + ']: ' + verb +\r\n '\\n' + uri + '\\n' + readyState + ' ' + statusCode;\r\n });\r\n};\r\n\r\n\r\n/**\r\n * Logs the response data received from an XmlHttp request.\r\n * @param {string|number|undefined} id The request id.\r\n * @param {?string} responseText The response text.\r\n * @param {?string=} opt_desc Optional request description.\r\n */\r\nWebChannelDebug.prototype.xmlHttpChannelResponseText = function(\r\n id, responseText, opt_desc) {\r\n var self = this;\r\n this.info(function() {\r\n return 'XMLHTTP TEXT (' + id + '): ' + self.redactResponse_(responseText) +\r\n (opt_desc ? ' ' + opt_desc : '');\r\n });\r\n};\r\n\r\n\r\n/**\r\n * Logs a request timeout.\r\n * @param {goog.Uri} uri The uri that timed out.\r\n */\r\nWebChannelDebug.prototype.timeoutResponse = function(uri) {\r\n this.info(function() {\r\n return 'TIMEOUT: ' + uri;\r\n });\r\n};\r\n\r\n\r\n/**\r\n * Logs a debug message.\r\n * @param {!goog.debug.Loggable} text The message.\r\n */\r\nWebChannelDebug.prototype.debug = function(text) {\r\n goog.log.fine(this.logger_, text);\r\n};\r\n\r\n\r\n/**\r\n * Logs an exception\r\n * @param {Error} e The error or error event.\r\n * @param {goog.debug.Loggable=} opt_msg The optional message,\r\n * defaults to 'Exception'.\r\n */\r\nWebChannelDebug.prototype.dumpException = function(e, opt_msg) {\r\n goog.log.error(this.logger_, opt_msg || 'Exception', e);\r\n};\r\n\r\n\r\n/**\r\n * Logs an info message.\r\n * @param {!goog.debug.Loggable} text The message.\r\n */\r\nWebChannelDebug.prototype.info = function(text) {\r\n goog.log.info(this.logger_, text);\r\n};\r\n\r\n\r\n/**\r\n * Logs a warning message.\r\n * @param {!goog.debug.Loggable} text The message.\r\n */\r\nWebChannelDebug.prototype.warning = function(text) {\r\n goog.log.warning(this.logger_, text);\r\n};\r\n\r\n\r\n/**\r\n * Logs a severe message.\r\n * @param {!goog.debug.Loggable} text The message.\r\n */\r\nWebChannelDebug.prototype.severe = function(text) {\r\n goog.log.error(this.logger_, text);\r\n};\r\n\r\n\r\n/**\r\n * Removes potentially private data from a response so that we don't\r\n * accidentally save private and personal data to the server logs.\r\n * @param {?string} responseText A JSON response to clean.\r\n * @return {?string} The cleaned response.\r\n * @private\r\n */\r\nWebChannelDebug.prototype.redactResponse_ = function(responseText) {\r\n if (!this.redactEnabled_) {\r\n return responseText;\r\n }\r\n\r\n if (!responseText) {\r\n return null;\r\n }\r\n\r\n try {\r\n var responseArray = JSON.parse(responseText);\r\n if (responseArray) {\r\n for (var i = 0; i < responseArray.length; i++) {\r\n if (goog.isArray(responseArray[i])) {\r\n this.maybeRedactArray_(responseArray[i]);\r\n }\r\n }\r\n }\r\n\r\n return goog.json.serialize(responseArray);\r\n } catch (e) {\r\n this.debug('Exception parsing expected JS array - probably was not JS');\r\n return responseText;\r\n }\r\n};\r\n\r\n\r\n/**\r\n * Removes data from a response array that may be sensitive.\r\n * @param {!Array<?>} array The array to clean.\r\n * @private\r\n */\r\nWebChannelDebug.prototype.maybeRedactArray_ = function(array) {\r\n if (array.length < 2) {\r\n return;\r\n }\r\n var dataPart = array[1];\r\n if (!goog.isArray(dataPart)) {\r\n return;\r\n }\r\n if (dataPart.length < 1) {\r\n return;\r\n }\r\n\r\n var type = dataPart[0];\r\n if (type != 'noop' && type != 'stop' && type != 'close') {\r\n // redact all fields in the array\r\n for (var i = 1; i < dataPart.length; i++) {\r\n dataPart[i] = '';\r\n }\r\n }\r\n};\r\n\r\n\r\n/**\r\n * Removes potentially private data from a request POST body so that we don't\r\n * accidentally save private and personal data to the server logs.\r\n * @param {?string} data The data string to clean.\r\n * @return {?string} The data string with sensitive data replaced by 'redacted'.\r\n * @private\r\n */\r\nWebChannelDebug.prototype.maybeRedactPostData_ = function(data) {\r\n if (!this.redactEnabled_) {\r\n return data;\r\n }\r\n\r\n if (!data) {\r\n return null;\r\n }\r\n var out = '';\r\n var params = data.split('&');\r\n for (var i = 0; i < params.length; i++) {\r\n var param = params[i];\r\n var keyValue = param.split('=');\r\n if (keyValue.length > 1) {\r\n var key = keyValue[0];\r\n var value = keyValue[1];\r\n\r\n var keyParts = key.split('_');\r\n if (keyParts.length >= 2 && keyParts[1] == 'type') {\r\n out += key + '=' + value + '&';\r\n } else {\r\n out += key + '=' +\r\n 'redacted' +\r\n '&';\r\n }\r\n }\r\n }\r\n return out;\r\n};\r\n}); // goog.scope\r\n","// Copyright 2013 The Closure Library Authors. All Rights Reserved.\r\n//\r\n// Licensed under the Apache License, Version 2.0 (the \"License\");\r\n// you may not use this file except in compliance with the License.\r\n// You may obtain a copy of the License at\r\n//\r\n// http://www.apache.org/licenses/LICENSE-2.0\r\n//\r\n// Unless required by applicable law or agreed to in writing, software\r\n// distributed under the License is distributed on an \"AS-IS\" BASIS,\r\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n// See the License for the specific language governing permissions and\r\n// limitations under the License.\r\n\r\n/**\r\n * @fileoverview Static utilities for collecting stats associated with\r\n * ChannelRequest.\r\n */\r\n\r\n\r\ngoog.provide('goog.labs.net.webChannel.requestStats');\r\ngoog.provide('goog.labs.net.webChannel.requestStats.Event');\r\ngoog.provide('goog.labs.net.webChannel.requestStats.ServerReachability');\r\ngoog.provide('goog.labs.net.webChannel.requestStats.ServerReachabilityEvent');\r\ngoog.provide('goog.labs.net.webChannel.requestStats.Stat');\r\ngoog.provide('goog.labs.net.webChannel.requestStats.StatEvent');\r\ngoog.provide('goog.labs.net.webChannel.requestStats.TimingEvent');\r\n\r\ngoog.require('goog.events.Event');\r\ngoog.require('goog.events.EventTarget');\r\n\r\n\r\ngoog.scope(function() {\r\nvar requestStats = goog.labs.net.webChannel.requestStats;\r\n\r\n\r\n/**\r\n * Events fired.\r\n * @const\r\n */\r\nrequestStats.Event = {};\r\n\r\n\r\n/**\r\n * Singleton event target for firing stat events\r\n * @type {goog.events.EventTarget}\r\n * @private\r\n */\r\nrequestStats.statEventTarget_ = new goog.events.EventTarget();\r\n\r\n\r\n/**\r\n * The type of event that occurs every time some information about how reachable\r\n * the server is is discovered.\r\n */\r\nrequestStats.Event.SERVER_REACHABILITY_EVENT = 'serverreachability';\r\n\r\n\r\n/**\r\n * Types of events which reveal information about the reachability of the\r\n * server.\r\n * @enum {number}\r\n */\r\nrequestStats.ServerReachability = {\r\n REQUEST_MADE: 1,\r\n REQUEST_SUCCEEDED: 2,\r\n REQUEST_FAILED: 3,\r\n BACK_CHANNEL_ACTIVITY: 4 // any response data received\r\n};\r\n\r\n\r\n\r\n/**\r\n * Event class for SERVER_REACHABILITY_EVENT.\r\n *\r\n * @param {goog.events.EventTarget} target The stat event target for\r\n the channel.\r\n * @param {requestStats.ServerReachability} reachabilityType\r\n * The reachability event type.\r\n * @constructor\r\n * @extends {goog.events.Event}\r\n */\r\nrequestStats.ServerReachabilityEvent = function(target, reachabilityType) {\r\n goog.events.Event.call(\r\n this, requestStats.Event.SERVER_REACHABILITY_EVENT, target);\r\n\r\n /**\r\n * @type {requestStats.ServerReachability}\r\n */\r\n this.reachabilityType = reachabilityType;\r\n};\r\ngoog.inherits(requestStats.ServerReachabilityEvent, goog.events.Event);\r\n\r\n\r\n/**\r\n * Notify the channel that a particular fine grained network event has occurred.\r\n * Should be considered package-private.\r\n * @param {requestStats.ServerReachability} reachabilityType\r\n * The reachability event type.\r\n */\r\nrequestStats.notifyServerReachabilityEvent = function(reachabilityType) {\r\n var target = requestStats.statEventTarget_;\r\n target.dispatchEvent(\r\n new requestStats.ServerReachabilityEvent(target, reachabilityType));\r\n};\r\n\r\n\r\n/**\r\n * Stat Event that fires when things of interest happen that may be useful for\r\n * applications to know about for stats or debugging purposes.\r\n */\r\nrequestStats.Event.STAT_EVENT = 'statevent';\r\n\r\n\r\n/**\r\n * Enum that identifies events for statistics that are interesting to track.\r\n * @enum {number}\r\n */\r\nrequestStats.Stat = {\r\n /** Event indicating a new connection attempt. */\r\n CONNECT_ATTEMPT: 0,\r\n\r\n /** Event indicating a connection error due to a general network problem. */\r\n ERROR_NETWORK: 1,\r\n\r\n /**\r\n * Event indicating a connection error that isn't due to a general network\r\n * problem.\r\n */\r\n ERROR_OTHER: 2,\r\n\r\n /** Event indicating the start of test stage one. */\r\n TEST_STAGE_ONE_START: 3,\r\n\r\n /** Event indicating the start of test stage two. */\r\n TEST_STAGE_TWO_START: 4,\r\n\r\n /** Event indicating the first piece of test data was received. */\r\n TEST_STAGE_TWO_DATA_ONE: 5,\r\n\r\n /**\r\n * Event indicating that the second piece of test data was received and it was\r\n * received separately from the first.\r\n */\r\n TEST_STAGE_TWO_DATA_TWO: 6,\r\n\r\n /** Event indicating both pieces of test data were received simultaneously. */\r\n TEST_STAGE_TWO_DATA_BOTH: 7,\r\n\r\n /** Event indicating stage one of the test request failed. */\r\n TEST_STAGE_ONE_FAILED: 8,\r\n\r\n /** Event indicating stage two of the test request failed. */\r\n TEST_STAGE_TWO_FAILED: 9,\r\n\r\n /**\r\n * Event indicating that a buffering proxy is likely between the client and\r\n * the server.\r\n */\r\n PROXY: 10,\r\n\r\n /**\r\n * Event indicating that no buffering proxy is likely between the client and\r\n * the server.\r\n */\r\n NOPROXY: 11,\r\n\r\n /** Event indicating an unknown SID error. */\r\n REQUEST_UNKNOWN_SESSION_ID: 12,\r\n\r\n /** Event indicating a bad status code was received. */\r\n REQUEST_BAD_STATUS: 13,\r\n\r\n /** Event indicating incomplete data was received */\r\n REQUEST_INCOMPLETE_DATA: 14,\r\n\r\n /** Event indicating bad data was received */\r\n REQUEST_BAD_DATA: 15,\r\n\r\n /** Event indicating no data was received when data was expected. */\r\n REQUEST_NO_DATA: 16,\r\n\r\n /** Event indicating a request timeout. */\r\n REQUEST_TIMEOUT: 17,\r\n\r\n /**\r\n * Event indicating that the server never received our hanging GET and so it\r\n * is being retried.\r\n */\r\n BACKCHANNEL_MISSING: 18,\r\n\r\n /**\r\n * Event indicating that we have determined that our hanging GET is not\r\n * receiving data when it should be. Thus it is dead dead and will be retried.\r\n */\r\n BACKCHANNEL_DEAD: 19,\r\n\r\n /**\r\n * The browser declared itself offline during the lifetime of a request, or\r\n * was offline when a request was initially made.\r\n */\r\n BROWSER_OFFLINE: 20\r\n};\r\n\r\n\r\n\r\n/**\r\n * Event class for STAT_EVENT.\r\n *\r\n * @param {goog.events.EventTarget} eventTarget The stat event target for\r\n the channel.\r\n * @param {requestStats.Stat} stat The stat.\r\n * @constructor\r\n * @extends {goog.events.Event}\r\n */\r\nrequestStats.StatEvent = function(eventTarget, stat) {\r\n goog.events.Event.call(this, requestStats.Event.STAT_EVENT, eventTarget);\r\n\r\n /**\r\n * The stat\r\n * @type {requestStats.Stat}\r\n */\r\n this.stat = stat;\r\n\r\n};\r\ngoog.inherits(requestStats.StatEvent, goog.events.Event);\r\n\r\n\r\n/**\r\n * Returns the singleton event target for stat events.\r\n * @return {goog.events.EventTarget} The event target for stat events.\r\n */\r\nrequestStats.getStatEventTarget = function() {\r\n return requestStats.statEventTarget_;\r\n};\r\n\r\n\r\n/**\r\n * Helper function to call the stat event callback.\r\n * @param {requestStats.Stat} stat The stat.\r\n */\r\nrequestStats.notifyStatEvent = function(stat) {\r\n var target = requestStats.statEventTarget_;\r\n target.dispatchEvent(new requestStats.StatEvent(target, stat));\r\n};\r\n\r\n\r\n/**\r\n * An event that fires when POST requests complete successfully, indicating\r\n * the size of the POST and the round trip time.\r\n */\r\nrequestStats.Event.TIMING_EVENT = 'timingevent';\r\n\r\n\r\n\r\n/**\r\n * Event class for requestStats.Event.TIMING_EVENT\r\n *\r\n * @param {goog.events.EventTarget} target The stat event target for\r\n the channel.\r\n * @param {number} size The number of characters in the POST data.\r\n * @param {number} rtt The total round trip time from POST to response in MS.\r\n * @param {number} retries The number of times the POST had to be retried.\r\n * @constructor\r\n * @extends {goog.events.Event}\r\n */\r\nrequestStats.TimingEvent = function(target, size, rtt, retries) {\r\n goog.events.Event.call(this, requestStats.Event.TIMING_EVENT, target);\r\n\r\n /**\r\n * @type {number}\r\n */\r\n this.size = size;\r\n\r\n /**\r\n * @type {number}\r\n */\r\n this.rtt = rtt;\r\n\r\n /**\r\n * @type {number}\r\n */\r\n this.retries = retries;\r\n\r\n};\r\ngoog.inherits(requestStats.TimingEvent, goog.events.Event);\r\n\r\n\r\n/**\r\n * Helper function to notify listeners about POST request performance.\r\n *\r\n * @param {number} size Number of characters in the POST data.\r\n * @param {number} rtt The amount of time from POST start to response.\r\n * @param {number} retries The number of times the POST had to be retried.\r\n */\r\nrequestStats.notifyTimingEvent = function(size, rtt, retries) {\r\n var target = requestStats.statEventTarget_;\r\n target.dispatchEvent(\r\n new requestStats.TimingEvent(target, size, rtt, retries));\r\n};\r\n\r\n\r\n/**\r\n * Allows the application to set an execution hooks for when a channel\r\n * starts processing requests. This is useful to track timing or logging\r\n * special information. The function takes no parameters and return void.\r\n * @param {Function} startHook The function for the start hook.\r\n */\r\nrequestStats.setStartThreadExecutionHook = function(startHook) {\r\n requestStats.startExecutionHook_ = startHook;\r\n};\r\n\r\n\r\n/**\r\n * Allows the application to set an execution hooks for when a channel\r\n * stops processing requests. This is useful to track timing or logging\r\n * special information. The function takes no parameters and return void.\r\n * @param {Function} endHook The function for the end hook.\r\n */\r\nrequestStats.setEndThreadExecutionHook = function(endHook) {\r\n requestStats.endExecutionHook_ = endHook;\r\n};\r\n\r\n\r\n/**\r\n * Application provided execution hook for the start hook.\r\n *\r\n * @type {Function}\r\n * @private\r\n */\r\nrequestStats.startExecutionHook_ = function() {};\r\n\r\n\r\n/**\r\n * Application provided execution hook for the end hook.\r\n *\r\n * @type {Function}\r\n * @private\r\n */\r\nrequestStats.endExecutionHook_ = function() {};\r\n\r\n\r\n/**\r\n * Helper function to call the start hook\r\n */\r\nrequestStats.onStartExecution = function() {\r\n requestStats.startExecutionHook_();\r\n};\r\n\r\n\r\n/**\r\n * Helper function to call the end hook\r\n */\r\nrequestStats.onEndExecution = function() {\r\n requestStats.endExecutionHook_();\r\n};\r\n\r\n\r\n/**\r\n * Wrapper around SafeTimeout which calls the start and end execution hooks\r\n * with a try...finally block.\r\n * @param {Function} fn The callback function.\r\n * @param {number} ms The time in MS for the timer.\r\n * @return {number} The ID of the timer.\r\n */\r\nrequestStats.setTimeout = function(fn, ms) {\r\n if (!goog.isFunction(fn)) {\r\n throw new Error('Fn must not be null and must be a function');\r\n }\r\n return goog.global.setTimeout(function() {\r\n requestStats.onStartExecution();\r\n try {\r\n fn();\r\n } finally {\r\n requestStats.onEndExecution();\r\n }\r\n }, ms);\r\n};\r\n}); // goog.scope\r\n","// Copyright 2007 The Closure Library Authors. All Rights Reserved.\r\n//\r\n// Licensed under the Apache License, Version 2.0 (the \"License\");\r\n// you may not use this file except in compliance with the License.\r\n// You may obtain a copy of the License at\r\n//\r\n// http://www.apache.org/licenses/LICENSE-2.0\r\n//\r\n// Unless required by applicable law or agreed to in writing, software\r\n// distributed under the License is distributed on an \"AS-IS\" BASIS,\r\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n// See the License for the specific language governing permissions and\r\n// limitations under the License.\r\n\r\n/**\r\n * @fileoverview Error codes shared between goog.net.IframeIo and\r\n * goog.net.XhrIo.\r\n */\r\n\r\ngoog.provide('goog.net.ErrorCode');\r\n\r\n\r\n/**\r\n * Error codes\r\n * @enum {number}\r\n */\r\ngoog.net.ErrorCode = {\r\n\r\n /**\r\n * There is no error condition.\r\n */\r\n NO_ERROR: 0,\r\n\r\n /**\r\n * The most common error from iframeio, unfortunately, is that the browser\r\n * responded with an error page that is classed as a different domain. The\r\n * situations, are when a browser error page is shown -- 404, access denied,\r\n * DNS failure, connection reset etc.)\r\n *\r\n */\r\n ACCESS_DENIED: 1,\r\n\r\n /**\r\n * Currently the only case where file not found will be caused is when the\r\n * code is running on the local file system and a non-IE browser makes a\r\n * request to a file that doesn't exist.\r\n */\r\n FILE_NOT_FOUND: 2,\r\n\r\n /**\r\n * If Firefox shows a browser error page, such as a connection reset by\r\n * server or access denied, then it will fail silently without the error or\r\n * load handlers firing.\r\n */\r\n FF_SILENT_ERROR: 3,\r\n\r\n /**\r\n * Custom error provided by the client through the error check hook.\r\n */\r\n CUSTOM_ERROR: 4,\r\n\r\n /**\r\n * Exception was thrown while processing the request.\r\n */\r\n EXCEPTION: 5,\r\n\r\n /**\r\n * The Http response returned a non-successful http status code.\r\n */\r\n HTTP_ERROR: 6,\r\n\r\n /**\r\n * The request was aborted.\r\n */\r\n ABORT: 7,\r\n\r\n /**\r\n * The request timed out.\r\n */\r\n TIMEOUT: 8,\r\n\r\n /**\r\n * The resource is not available offline.\r\n */\r\n OFFLINE: 9\r\n};\r\n\r\n\r\n/**\r\n * Returns a friendly error message for an error code. These messages are for\r\n * debugging and are not localized.\r\n * @param {goog.net.ErrorCode} errorCode An error code.\r\n * @return {string} A message for debugging.\r\n */\r\ngoog.net.ErrorCode.getDebugMessage = function(errorCode) {\r\n switch (errorCode) {\r\n case goog.net.ErrorCode.NO_ERROR:\r\n return 'No Error';\r\n\r\n case goog.net.ErrorCode.ACCESS_DENIED:\r\n return 'Access denied to content document';\r\n\r\n case goog.net.ErrorCode.FILE_NOT_FOUND:\r\n return 'File not found';\r\n\r\n case goog.net.ErrorCode.FF_SILENT_ERROR:\r\n return 'Firefox silently errored';\r\n\r\n case goog.net.ErrorCode.CUSTOM_ERROR:\r\n return 'Application custom error';\r\n\r\n case goog.net.ErrorCode.EXCEPTION:\r\n return 'An exception occurred';\r\n\r\n case goog.net.ErrorCode.HTTP_ERROR:\r\n return 'Http response at 400 or 500 level';\r\n\r\n case goog.net.ErrorCode.ABORT:\r\n return 'Request was aborted';\r\n\r\n case goog.net.ErrorCode.TIMEOUT:\r\n return 'Request timed out';\r\n\r\n case goog.net.ErrorCode.OFFLINE:\r\n return 'The resource is not available offline';\r\n\r\n default:\r\n return 'Unrecognized error code';\r\n }\r\n};\r\n","// Copyright 2006 The Closure Library Authors. All Rights Reserved.\r\n//\r\n// Licensed under the Apache License, Version 2.0 (the \"License\");\r\n// you may not use this file except in compliance with the License.\r\n// You may obtain a copy of the License at\r\n//\r\n// http://www.apache.org/licenses/LICENSE-2.0\r\n//\r\n// Unless required by applicable law or agreed to in writing, software\r\n// distributed under the License is distributed on an \"AS-IS\" BASIS,\r\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n// See the License for the specific language governing permissions and\r\n// limitations under the License.\r\n\r\n/**\r\n * @fileoverview Common events for the network classes.\r\n */\r\n\r\n\r\ngoog.provide('goog.net.EventType');\r\n\r\n\r\n/**\r\n * Event names for network events\r\n * @enum {string}\r\n */\r\ngoog.net.EventType = {\r\n COMPLETE: 'complete',\r\n SUCCESS: 'success',\r\n ERROR: 'error',\r\n ABORT: 'abort',\r\n READY: 'ready',\r\n READY_STATE_CHANGE: 'readystatechange',\r\n TIMEOUT: 'timeout',\r\n INCREMENTAL_DATA: 'incrementaldata',\r\n PROGRESS: 'progress',\r\n // DOWNLOAD_PROGRESS and UPLOAD_PROGRESS are special events dispatched by\r\n // goog.net.XhrIo to allow binding listeners specific to each type of\r\n // progress.\r\n DOWNLOAD_PROGRESS: 'downloadprogress',\r\n UPLOAD_PROGRESS: 'uploadprogress'\r\n};\r\n","// Copyright 2010 The Closure Library Authors. All Rights Reserved.\r\n//\r\n// Licensed under the Apache License, Version 2.0 (the \"License\");\r\n// you may not use this file except in compliance with the License.\r\n// You may obtain a copy of the License at\r\n//\r\n// http://www.apache.org/licenses/LICENSE-2.0\r\n//\r\n// Unless required by applicable law or agreed to in writing, software\r\n// distributed under the License is distributed on an \"AS-IS\" BASIS,\r\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n// See the License for the specific language governing permissions and\r\n// limitations under the License.\r\n\r\n/**\r\n * @fileoverview Interface for a factory for creating XMLHttpRequest objects\r\n * and metadata about them.\r\n * @author dbk@google.com (David Barrett-Kahn)\r\n */\r\n\r\ngoog.provide('goog.net.XmlHttpFactory');\r\n\r\n/** @suppress {extraRequire} Typedef. */\r\ngoog.require('goog.net.XhrLike');\r\n\r\n\r\n\r\n/**\r\n * Abstract base class for an XmlHttpRequest factory.\r\n * @constructor\r\n */\r\ngoog.net.XmlHttpFactory = function() {};\r\n\r\n\r\n/**\r\n * Cache of options - we only actually call internalGetOptions once.\r\n * @type {?Object}\r\n * @private\r\n */\r\ngoog.net.XmlHttpFactory.prototype.cachedOptions_ = null;\r\n\r\n\r\n/**\r\n * @return {!goog.net.XhrLike.OrNative} A new XhrLike instance.\r\n */\r\ngoog.net.XmlHttpFactory.prototype.createInstance = goog.abstractMethod;\r\n\r\n\r\n/**\r\n * @return {Object} Options describing how xhr objects obtained from this\r\n * factory should be used.\r\n */\r\ngoog.net.XmlHttpFactory.prototype.getOptions = function() {\r\n return this.cachedOptions_ ||\r\n (this.cachedOptions_ = this.internalGetOptions());\r\n};\r\n\r\n\r\n/**\r\n * Override this method in subclasses to preserve the caching offered by\r\n * getOptions().\r\n * @return {Object} Options describing how xhr objects obtained from this\r\n * factory should be used.\r\n * @protected\r\n */\r\ngoog.net.XmlHttpFactory.prototype.internalGetOptions = goog.abstractMethod;\r\n","// Copyright 2006 The Closure Library Authors. All Rights Reserved.\r\n//\r\n// Licensed under the Apache License, Version 2.0 (the \"License\");\r\n// you may not use this file except in compliance with the License.\r\n// You may obtain a copy of the License at\r\n//\r\n// http://www.apache.org/licenses/LICENSE-2.0\r\n//\r\n// Unless required by applicable law or agreed to in writing, software\r\n// distributed under the License is distributed on an \"AS-IS\" BASIS,\r\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n// See the License for the specific language governing permissions and\r\n// limitations under the License.\r\n\r\n/**\r\n * @fileoverview Low level handling of XMLHttpRequest.\r\n * @author arv@google.com (Erik Arvidsson)\r\n * @author dbk@google.com (David Barrett-Kahn)\r\n */\r\n\r\ngoog.provide('goog.net.DefaultXmlHttpFactory');\r\ngoog.provide('goog.net.XmlHttp');\r\ngoog.provide('goog.net.XmlHttp.OptionType');\r\ngoog.provide('goog.net.XmlHttp.ReadyState');\r\ngoog.provide('goog.net.XmlHttpDefines');\r\n\r\ngoog.require('goog.asserts');\r\ngoog.require('goog.net.WrapperXmlHttpFactory');\r\ngoog.require('goog.net.XmlHttpFactory');\r\n\r\n\r\n/**\r\n * Static class for creating XMLHttpRequest objects.\r\n * @return {!goog.net.XhrLike.OrNative} A new XMLHttpRequest object.\r\n */\r\ngoog.net.XmlHttp = function() {\r\n return goog.net.XmlHttp.factory_.createInstance();\r\n};\r\n\r\n\r\n/**\r\n * @define {boolean} Whether to assume XMLHttpRequest exists. Setting this to\r\n * true bypasses the ActiveX probing code.\r\n * NOTE(ruilopes): Due to the way JSCompiler works, this define *will not* strip\r\n * out the ActiveX probing code from binaries. To achieve this, use\r\n * `goog.net.XmlHttpDefines.ASSUME_NATIVE_XHR` instead.\r\n * TODO(ruilopes): Collapse both defines.\r\n */\r\ngoog.net.XmlHttp.ASSUME_NATIVE_XHR =\r\n goog.define('goog.net.XmlHttp.ASSUME_NATIVE_XHR', false);\r\n\r\n\r\n/** @const */\r\ngoog.net.XmlHttpDefines = {};\r\n\r\n\r\n/**\r\n * @define {boolean} Whether to assume XMLHttpRequest exists. Setting this to\r\n * true eliminates the ActiveX probing code.\r\n */\r\ngoog.net.XmlHttpDefines.ASSUME_NATIVE_XHR =\r\n goog.define('goog.net.XmlHttpDefines.ASSUME_NATIVE_XHR', false);\r\n\r\n\r\n/**\r\n * Gets the options to use with the XMLHttpRequest objects obtained using\r\n * the static methods.\r\n * @return {Object} The options.\r\n */\r\ngoog.net.XmlHttp.getOptions = function() {\r\n return goog.net.XmlHttp.factory_.getOptions();\r\n};\r\n\r\n\r\n/**\r\n * Type of options that an XmlHttp object can have.\r\n * @enum {number}\r\n */\r\ngoog.net.XmlHttp.OptionType = {\r\n /**\r\n * Whether a goog.nullFunction should be used to clear the onreadystatechange\r\n * handler instead of null.\r\n */\r\n USE_NULL_FUNCTION: 0,\r\n\r\n /**\r\n * NOTE(user): In IE if send() errors on a *local* request the readystate\r\n * is still changed to COMPLETE. We need to ignore it and allow the\r\n * try/catch around send() to pick up the error.\r\n */\r\n LOCAL_REQUEST_ERROR: 1\r\n};\r\n\r\n\r\n/**\r\n * Status constants for XMLHTTP, matches:\r\n * https://msdn.microsoft.com/en-us/library/ms534361(v=vs.85).aspx\r\n * @enum {number}\r\n */\r\ngoog.net.XmlHttp.ReadyState = {\r\n /**\r\n * Constant for when xmlhttprequest.readyState is uninitialized\r\n */\r\n UNINITIALIZED: 0,\r\n\r\n /**\r\n * Constant for when xmlhttprequest.readyState is loading.\r\n */\r\n LOADING: 1,\r\n\r\n /**\r\n * Constant for when xmlhttprequest.readyState is loaded.\r\n */\r\n LOADED: 2,\r\n\r\n /**\r\n * Constant for when xmlhttprequest.readyState is in an interactive state.\r\n */\r\n INTERACTIVE: 3,\r\n\r\n /**\r\n * Constant for when xmlhttprequest.readyState is completed\r\n */\r\n COMPLETE: 4\r\n};\r\n\r\n\r\n/**\r\n * The global factory instance for creating XMLHttpRequest objects.\r\n * @type {goog.net.XmlHttpFactory}\r\n * @private\r\n */\r\ngoog.net.XmlHttp.factory_;\r\n\r\n\r\n/**\r\n * Sets the factories for creating XMLHttpRequest objects and their options.\r\n * @param {Function} factory The factory for XMLHttpRequest objects.\r\n * @param {Function} optionsFactory The factory for options.\r\n * @deprecated Use setGlobalFactory instead.\r\n */\r\ngoog.net.XmlHttp.setFactory = function(factory, optionsFactory) {\r\n goog.net.XmlHttp.setGlobalFactory(\r\n new goog.net.WrapperXmlHttpFactory(\r\n goog.asserts.assert(factory), goog.asserts.assert(optionsFactory)));\r\n};\r\n\r\n\r\n/**\r\n * Sets the global factory object.\r\n * @param {!goog.net.XmlHttpFactory} factory New global factory object.\r\n */\r\ngoog.net.XmlHttp.setGlobalFactory = function(factory) {\r\n goog.net.XmlHttp.factory_ = factory;\r\n};\r\n\r\n\r\n\r\n/**\r\n * Default factory to use when creating xhr objects. You probably shouldn't be\r\n * instantiating this directly, but rather using it via goog.net.XmlHttp.\r\n * @extends {goog.net.XmlHttpFactory}\r\n * @constructor\r\n */\r\ngoog.net.DefaultXmlHttpFactory = function() {\r\n goog.net.XmlHttpFactory.call(this);\r\n};\r\ngoog.inherits(goog.net.DefaultXmlHttpFactory, goog.net.XmlHttpFactory);\r\n\r\n\r\n/** @override */\r\ngoog.net.DefaultXmlHttpFactory.prototype.createInstance = function() {\r\n var progId = this.getProgId_();\r\n if (progId) {\r\n return new ActiveXObject(progId);\r\n } else {\r\n return new XMLHttpRequest();\r\n }\r\n};\r\n\r\n\r\n/** @override */\r\ngoog.net.DefaultXmlHttpFactory.prototype.internalGetOptions = function() {\r\n var progId = this.getProgId_();\r\n var options = {};\r\n if (progId) {\r\n options[goog.net.XmlHttp.OptionType.USE_NULL_FUNCTION] = true;\r\n options[goog.net.XmlHttp.OptionType.LOCAL_REQUEST_ERROR] = true;\r\n }\r\n return options;\r\n};\r\n\r\n\r\n/**\r\n * The ActiveX PROG ID string to use to create xhr's in IE. Lazily initialized.\r\n * @type {string|undefined}\r\n * @private\r\n */\r\ngoog.net.DefaultXmlHttpFactory.prototype.ieProgId_;\r\n\r\n\r\n/**\r\n * Initialize the private state used by other functions.\r\n * @return {string} The ActiveX PROG ID string to use to create xhr's in IE.\r\n * @private\r\n */\r\ngoog.net.DefaultXmlHttpFactory.prototype.getProgId_ = function() {\r\n if (goog.net.XmlHttp.ASSUME_NATIVE_XHR ||\r\n goog.net.XmlHttpDefines.ASSUME_NATIVE_XHR) {\r\n return '';\r\n }\r\n\r\n // The following blog post describes what PROG IDs to use to create the\r\n // XMLHTTP object in Internet Explorer:\r\n // http://blogs.msdn.com/xmlteam/archive/2006/10/23/using-the-right-version-of-msxml-in-internet-explorer.aspx\r\n // However we do not (yet) fully trust that this will be OK for old versions\r\n // of IE on Win9x so we therefore keep the last 2.\r\n if (!this.ieProgId_ && typeof XMLHttpRequest == 'undefined' &&\r\n typeof ActiveXObject != 'undefined') {\r\n // Candidate Active X types.\r\n var ACTIVE_X_IDENTS = [\r\n 'MSXML2.XMLHTTP.6.0', 'MSXML2.XMLHTTP.3.0', 'MSXML2.XMLHTTP',\r\n 'Microsoft.XMLHTTP'\r\n ];\r\n for (var i = 0; i < ACTIVE_X_IDENTS.length; i++) {\r\n var candidate = ACTIVE_X_IDENTS[i];\r\n\r\n try {\r\n new ActiveXObject(candidate);\r\n // NOTE(user): cannot assign progid and return candidate in one line\r\n // because JSCompiler complaings: BUG 658126\r\n this.ieProgId_ = candidate;\r\n return candidate;\r\n } catch (e) {\r\n // do nothing; try next choice\r\n }\r\n }\r\n\r\n // couldn't find any matches\r\n throw new Error(\r\n 'Could not create ActiveXObject. ActiveX might be disabled,' +\r\n ' or MSXML might not be installed');\r\n }\r\n\r\n return /** @type {string} */ (this.ieProgId_);\r\n};\r\n\r\n\r\n// Set the global factory to an instance of the default factory.\r\ngoog.net.XmlHttp.setGlobalFactory(new goog.net.DefaultXmlHttpFactory());\r\n","// Copyright 2013 The Closure Library Authors. All Rights Reserved.\r\n//\r\n// Licensed under the Apache License, Version 2.0 (the \"License\");\r\n// you may not use this file except in compliance with the License.\r\n// You may obtain a copy of the License at\r\n//\r\n// http://www.apache.org/licenses/LICENSE-2.0\r\n//\r\n// Unless required by applicable law or agreed to in writing, software\r\n// distributed under the License is distributed on an \"AS-IS\" BASIS,\r\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n// See the License for the specific language governing permissions and\r\n// limitations under the License.\r\n\r\n/**\r\n * @fileoverview The API spec for the WebChannel messaging library.\r\n *\r\n * Similar to HTML5 WebSocket and Closure BrowserChannel, WebChannel\r\n * offers an abstraction for point-to-point socket-like communication between\r\n * a browser client and a remote origin.\r\n *\r\n * WebChannels are created via <code>WebChannel</code>. Multiple WebChannels\r\n * may be multiplexed over the same WebChannelTransport, which represents\r\n * the underlying physical connectivity over standard wire protocols\r\n * such as HTTP and SPDY.\r\n *\r\n * A WebChannels in turn represents a logical communication channel between\r\n * the client and server end point. A WebChannel remains open for\r\n * as long as the client or server end-point allows.\r\n *\r\n * Messages may be delivered in-order or out-of-order, reliably or unreliably\r\n * over the same WebChannel. Message delivery guarantees of a WebChannel is\r\n * to be specified by the application code; and the choice of the\r\n * underlying wire protocols is completely transparent to the API users.\r\n *\r\n * Client-to-client messaging via WebRTC based transport may also be support\r\n * via the same WebChannel API in future.\r\n *\r\n * Note that we have no immediate plan to move this API out of labs. While\r\n * the implementation is production ready, the API is subject to change\r\n * (addition only):\r\n * 1. Adopt new Web APIs (mainly whatwg streams) and goog.net.streams.\r\n * 2. New programming models for cloud (on the server-side) may require\r\n * new APIs to be defined.\r\n * 3. WebRTC DataChannel alignment\r\n *\r\n */\r\n\r\ngoog.provide('goog.net.WebChannel');\r\n\r\ngoog.require('goog.events');\r\ngoog.require('goog.events.Event');\r\ngoog.require('goog.events.Listenable');\r\ngoog.require('goog.net.XmlHttpFactory');\r\n\r\n\r\n\r\n/**\r\n * A WebChannel represents a logical bi-directional channel over which the\r\n * client communicates with a remote server that holds the other endpoint\r\n * of the channel. A WebChannel is always created in the context of a shared\r\n * {@link WebChannelTransport} instance. It is up to the underlying client-side\r\n * and server-side implementations to decide how or when multiplexing is\r\n * to be enabled.\r\n *\r\n * @interface\r\n * @extends {EventTarget}\r\n * @extends {goog.events.Listenable}\r\n */\r\ngoog.net.WebChannel = function() {};\r\n\r\n\r\n\r\n/**\r\n * This interface defines a pluggable API to allow WebChannel runtime to support\r\n * customized algorithms in order to recover from transient failures such as\r\n * those failures caused by network or proxies (intermediaries).\r\n *\r\n * The algorithm may also choose to fail-fast, e.g. switch the client to some\r\n * offline mode.\r\n *\r\n * Extra measurements and logging could also be implemented in the custom\r\n * module, which has the full knowledge of all the state transitions\r\n * (due to failures).\r\n *\r\n * A default algorithm will be provided by the webchannel library itself. Custom\r\n * algorithms are expected to be tailored to specific client platforms or\r\n * networking environments, e.g. mobile, cellular network.\r\n *\r\n * @interface\r\n */\r\ngoog.net.WebChannel.FailureRecovery = function() {};\r\n\r\n\r\n/**\r\n * Configuration spec for newly created WebChannel instances.\r\n *\r\n * WebChannels are configured in the context of the containing\r\n * {@link WebChannelTransport}. The configuration parameters are specified\r\n * when a new instance of WebChannel is created via {@link WebChannelTransport}.\r\n *\r\n * messageHeaders: custom headers to be added to every message sent to the\r\n * server. This object is mutable, and custom headers may be changed, removed,\r\n * or added during the runtime after a channel has been opened.\r\n *\r\n * initMessageHeaders: similar to messageHeaders, but any custom headers will\r\n * be sent only once when the channel is opened. Typical usage is to send\r\n * an auth header to the server, which only checks the auth header at the time\r\n * when the channel is opened.\r\n *\r\n * messageContentType: sent as initMessageHeaders via X-WebChannel-Content-Type,\r\n * to inform the server the MIME type of WebChannel messages.\r\n *\r\n * messageUrlParams: custom url query parameters to be added to every message\r\n * sent to the server. This object is mutable, and custom parameters may be\r\n * changed, removed or added during the runtime after a channel has been opened.\r\n *\r\n * clientProtocolHeaderRequired: whether a special header should be added to\r\n * each message so that the server can dispatch webchannel messages without\r\n * knowing the URL path prefix. Defaults to false.\r\n *\r\n * concurrentRequestLimit: the maximum number of in-flight HTTP requests allowed\r\n * when SPDY is enabled. Currently we only detect SPDY in Chrome.\r\n * This parameter defaults to 10. When SPDY is not enabled, this parameter\r\n * will have no effect.\r\n *\r\n * supportsCrossDomainXhr: setting this to true to allow the use of sub-domains\r\n * (as configured by the server) to send XHRs with the CORS withCredentials\r\n * bit set to true.\r\n *\r\n * testUrl: the test URL for detecting connectivity during the initial\r\n * handshake. This parameter defaults to \"/<channel_url>/test\".\r\n *\r\n * sendRawJson: whether to bypass v8 encoding of client-sent messages.\r\n * This defaults to false now due to legacy servers. New applications should\r\n * always configure this option to true.\r\n *\r\n * httpSessionIdParam: the URL parameter name that contains the session id (\r\n * for sticky routing of HTTP requests). When this param is specified, a server\r\n * that supports this option will respond with an opaque session id as part of\r\n * the initial handshake (via the X-HTTP-Session-Id header); and all the\r\n * subsequent requests will contain the httpSessionIdParam. This option will\r\n * take precedence over any duplicated parameter specified with\r\n * messageUrlParams, whose value will be ignored.\r\n *\r\n * httpHeadersOverwriteParam: the URL parameter name to allow custom HTTP\r\n * headers to be overwritten as a URL param to bypass CORS preflight.\r\n * goog.net.rpc.HttpCors is used to encode the HTTP headers.\r\n *\r\n * backgroundChannelTest: whether to run the channel test (detecting networking\r\n * conditions) as a background process so the OPEN event will be fired sooner\r\n * to reduce the initial handshake delay. This option defaults to true.\r\n * The actual background channel test is not fully implemented.\r\n *\r\n * forceLongPolling: whether to force long-polling from client to server.\r\n * This defaults to false. Long-polling may be necessary when a (MITM) proxy\r\n * is buffering data sent by the server.\r\n *\r\n * fastHandshake: enable true 0-RTT message delivery, including\r\n * leveraging QUIC 0-RTT (which requires GET to be used). This option\r\n * defaults to false. Note it is allowed to send messages before Open event is\r\n * received, after a channel has been opened. In order to enable 0-RTT,\r\n * messages will be encoded as part of URL and therefore there needs be a size\r\n * limit for those initial messages that are sent immediately as part of the\r\n * GET handshake request. With sendRawJson=true, this limit is currently set\r\n * to 4K chars and data beyond this limit will be buffered till the handshake\r\n * (1-RTT) finishes. With sendRawJson=false, it's up to the application\r\n * to limit the amount of data that is sent as part of the handshake.\r\n *\r\n * disableRedact: whether to disable logging redact. By default, redact is\r\n * enabled to remove any message payload or user-provided info\r\n * from closure logs.\r\n *\r\n * clientProfile: inform the server about the client profile to enable\r\n * customized configs that are optimized for certain clients or environments.\r\n * Currently this information is sent via X-WebChannel-Client-Profile header.\r\n *\r\n * internalChannelParams: the internal channel parameter name to allow\r\n * experimental channel configurations. Supported options include fastfail,\r\n * baseRetryDelayMs, retryDelaySeedMs, forwardChannelMaxRetries and\r\n * forwardChannelRequestTimeoutMs. Note that these options are subject to\r\n * change.\r\n *\r\n * xmlHttpFactory: allows the caller to override the factory used to create\r\n * XMLHttpRequest objects. This is introduced to disable CORS on firefox OS.\r\n *\r\n * requestRefreshThresholds: client-side thresholds that decide when to refresh\r\n * an underlying HTTP request, to limit memory consumption due to XHR buffering\r\n * or compression context. The client-side thresholds should be signficantly\r\n * smaller than the server-side thresholds. This allows the client to eliminate\r\n * any latency introduced by request refreshing, i.e. an RTT window during which\r\n * messages may be buffered on the server-side. Supported params include\r\n * totalBytesReceived, totalDurationMs.\r\n *\r\n * @typedef {{\r\n * messageHeaders: (!Object<string, string>|undefined),\r\n * initMessageHeaders: (!Object<string, string>|undefined),\r\n * messageContentType: (string|undefined),\r\n * messageUrlParams: (!Object<string, string>|undefined),\r\n * clientProtocolHeaderRequired: (boolean|undefined),\r\n * concurrentRequestLimit: (number|undefined),\r\n * supportsCrossDomainXhr: (boolean|undefined),\r\n * testUrl: (string|undefined),\r\n * sendRawJson: (boolean|undefined),\r\n * httpSessionIdParam: (string|undefined),\r\n * httpHeadersOverwriteParam: (string|undefined),\r\n * backgroundChannelTest: (boolean|undefined),\r\n * forceLongPolling: (boolean|undefined),\r\n * fastHandshake: (boolean|undefined),\r\n * disableRedact: (boolean|undefined),\r\n * clientProfile: (string|undefined),\r\n * internalChannelParams: (!Object<string, boolean|number>|undefined),\r\n * xmlHttpFactory: (!goog.net.XmlHttpFactory|undefined),\r\n * requestRefreshThresholds: (!Object<string, number>|undefined),\r\n * }}\r\n */\r\ngoog.net.WebChannel.Options;\r\n\r\n\r\n/**\r\n * Types that are allowed as message data.\r\n *\r\n * Note that JS objects (sent by the client) can only have string encoded\r\n * values due to the limitation of the current wire protocol.\r\n *\r\n * Unicode strings (sent by the server) may or may not need be escaped, as\r\n * decided by the server.\r\n *\r\n * @typedef {(!ArrayBuffer|!Blob|!Object<string, !Object|string>|!Array|string)}\r\n */\r\ngoog.net.WebChannel.MessageData;\r\n\r\n\r\n/**\r\n * Open the WebChannel against the URI specified in the constructor.\r\n */\r\ngoog.net.WebChannel.prototype.open = goog.abstractMethod;\r\n\r\n\r\n/**\r\n * Close the WebChannel.\r\n *\r\n * This is a full close (shutdown) with no guarantee of FIFO delivery in respect\r\n * to any in-flight messages sent to the server.\r\n *\r\n * If you need such a guarantee, see the Half the halfClose() method.\r\n */\r\ngoog.net.WebChannel.prototype.close = goog.abstractMethod;\r\n\r\n\r\n/**\r\n * Half-close the WebChannel.\r\n *\r\n * Half-close semantics:\r\n * 1. delivered as a regular message in FIFO programming order\r\n * 2. the server is expected to return a half-close too (with or without\r\n * application involved), which will trigger a full close (shutdown)\r\n * on the client side\r\n * 3. for now, the half-close event defined for server-initiated\r\n * half-close is not exposed to the client application\r\n * 4. a client-side half-close may be triggered internally when the client\r\n * receives a half-close from the server; and the client is expected to\r\n * do a full close after the half-close is acked and delivered\r\n * on the server-side.\r\n * 5. Full close is always a forced one. See the close() method.\r\n *\r\n * New messages sent after halfClose() will be dropped.\r\n *\r\n * NOTE: This is not yet implemented, and will throw an exception if called.\r\n */\r\ngoog.net.WebChannel.prototype.halfClose = goog.abstractMethod;\r\n\r\n\r\n/**\r\n * Sends a message to the server that maintains the other end point of\r\n * the WebChannel.\r\n *\r\n * O-RTT behavior:\r\n * 1. messages sent before open() is called will always be delivered as\r\n * part of the handshake, i.e. with 0-RTT\r\n * 2. messages sent after open() is called but before the OPEN event\r\n * is received will be delivered as part of the handshake if\r\n * send() is called from the same execution context as open().\r\n * 3. otherwise, those messages will be buffered till the handshake\r\n * is completed (which will fire the OPEN event).\r\n *\r\n * @param {!goog.net.WebChannel.MessageData} message The message to send.\r\n */\r\ngoog.net.WebChannel.prototype.send = goog.abstractMethod;\r\n\r\n\r\n/**\r\n * Common events fired by WebChannels.\r\n * @enum {string}\r\n */\r\ngoog.net.WebChannel.EventType = {\r\n /** Dispatched when the channel is opened. */\r\n OPEN: goog.events.getUniqueId('open'),\r\n\r\n /** Dispatched when the channel is closed. */\r\n CLOSE: goog.events.getUniqueId('close'),\r\n\r\n /**\r\n * Dispatched when the channel is aborted due to errors.\r\n *\r\n * For backward compatibility reasons, a CLOSE event will also be\r\n * dispatched, following the ERROR event, which indicates that the channel\r\n * has been completely shutdown .\r\n */\r\n ERROR: goog.events.getUniqueId('error'),\r\n\r\n /** Dispatched when the channel has received a new message. */\r\n MESSAGE: goog.events.getUniqueId('message')\r\n};\r\n\r\n\r\n\r\n/**\r\n * The event interface for the MESSAGE event.\r\n *\r\n * @constructor\r\n * @extends {goog.events.Event}\r\n */\r\ngoog.net.WebChannel.MessageEvent = function() {\r\n goog.net.WebChannel.MessageEvent.base(\r\n this, 'constructor', goog.net.WebChannel.EventType.MESSAGE);\r\n};\r\ngoog.inherits(goog.net.WebChannel.MessageEvent, goog.events.Event);\r\n\r\n\r\n/**\r\n * The content of the message received from the server.\r\n *\r\n * @type {!goog.net.WebChannel.MessageData}\r\n */\r\ngoog.net.WebChannel.MessageEvent.prototype.data;\r\n\r\n\r\n/**\r\n * The metadata key when the MESSAGE event represents a metadata message.\r\n *\r\n * @type {string|undefined}\r\n */\r\ngoog.net.WebChannel.MessageEvent.prototype.metadataKey;\r\n\r\n\r\n/**\r\n * WebChannel level error conditions.\r\n *\r\n * Summary of error debugging and reporting in WebChannel:\r\n *\r\n * Network Error\r\n * 1. By default the webchannel library will set the error status to\r\n * NETWORK_ERROR when a channel has to be aborted or closed. NETWORK_ERROR\r\n * may be recovered by the application by retrying and opening a new channel.\r\n * 2. There may be lost messages (not acked by the server) when a channel is\r\n * aborted. Currently we don't have a public API to retrieve messages that\r\n * are waiting to be acked on the client side. File a bug if you think it\r\n * is useful to expose such an API.\r\n * 3. Details of why a channel fails are available via closure debug logs,\r\n * and stats events (see webchannel/requeststats.js). Those are internal\r\n * stats and are subject to change. File a bug if you think it's useful to\r\n * version and expose such stats as part of the WebChannel API.\r\n *\r\n * Server Error\r\n * 1. SERVER_ERROR is intended to indicate a non-recoverable condition, e.g.\r\n * when auth fails.\r\n * 2. We don't currently generate any such errors, because most of the time\r\n * it's the responsibility of upper-layer frameworks or the application\r\n * itself to indicate to the client why a webchannel has been failed\r\n * by the server.\r\n * 3. When a channel is failed by the server explicitly, we still signal\r\n * NETWORK_ERROR to the client. Explicit server failure may happen when the\r\n * server does a fail-over, or becomes overloaded, or conducts a forced\r\n * shutdown etc.\r\n * 4. We use some heuristic to decide if the network (aka cloud) is down\r\n * v.s. the actual server is down.\r\n *\r\n * RuntimeProperties.getLastStatusCode is a useful state that we expose to\r\n * the client to indicate the HTTP response status code of the last HTTP\r\n * request initiated by the WebChannel client library, for debugging\r\n * purposes only.\r\n *\r\n * See WebChannel.Options.backChannelFailureRecovery and\r\n * WebChannel.FailureRecovery to install a custom failure-recovery algorithm.\r\n *\r\n * @enum {number}\r\n */\r\ngoog.net.WebChannel.ErrorStatus = {\r\n /** No error has occurred. */\r\n OK: 0,\r\n\r\n /** Communication to the server has failed. */\r\n NETWORK_ERROR: 1,\r\n\r\n /** The server fails to accept or process the WebChannel. */\r\n SERVER_ERROR: 2\r\n};\r\n\r\n\r\n\r\n/**\r\n * The event interface for the ERROR event.\r\n *\r\n * @constructor\r\n * @extends {goog.events.Event}\r\n */\r\ngoog.net.WebChannel.ErrorEvent = function() {\r\n goog.net.WebChannel.ErrorEvent.base(\r\n this, 'constructor', goog.net.WebChannel.EventType.ERROR);\r\n};\r\ngoog.inherits(goog.net.WebChannel.ErrorEvent, goog.events.Event);\r\n\r\n\r\n/**\r\n * The error status.\r\n *\r\n * @type {!goog.net.WebChannel.ErrorStatus}\r\n */\r\ngoog.net.WebChannel.ErrorEvent.prototype.status;\r\n\r\n\r\n/**\r\n * @return {!goog.net.WebChannel.RuntimeProperties} The runtime properties\r\n * of the WebChannel instance.\r\n */\r\ngoog.net.WebChannel.prototype.getRuntimeProperties = goog.abstractMethod;\r\n\r\n\r\n\r\n/**\r\n * The runtime properties of the WebChannel instance.\r\n *\r\n * This class is defined for debugging and monitoring purposes, as well as for\r\n * runtime functions that the application may choose to manage by itself.\r\n *\r\n * @interface\r\n */\r\ngoog.net.WebChannel.RuntimeProperties = function() {};\r\n\r\n\r\n/**\r\n * @return {number} The effective limit for the number of concurrent HTTP\r\n * requests that are allowed to be made for sending messages from the client\r\n * to the server. When SPDY is not enabled, this limit will be one.\r\n */\r\ngoog.net.WebChannel.RuntimeProperties.prototype.getConcurrentRequestLimit =\r\n goog.abstractMethod;\r\n\r\n\r\n/**\r\n * For applications that need support multiple channels (e.g. from\r\n * different tabs) to the same origin, use this method to decide if SPDY is\r\n * enabled and therefore it is safe to open multiple channels.\r\n *\r\n * If SPDY is disabled, the application may choose to limit the number of active\r\n * channels to one or use other means such as sub-domains to work around\r\n * the browser connection limit.\r\n *\r\n * @return {boolean} Whether SPDY is enabled for the origin against which\r\n * the channel is created.\r\n */\r\ngoog.net.WebChannel.RuntimeProperties.prototype.isSpdyEnabled =\r\n goog.abstractMethod;\r\n\r\n\r\n/**\r\n * @return {number} The number of requests (for sending messages to the server)\r\n * that are pending. If this number is approaching the value of\r\n * getConcurrentRequestLimit(), client-to-server message delivery may experience\r\n * a higher latency.\r\n */\r\ngoog.net.WebChannel.RuntimeProperties.prototype.getPendingRequestCount =\r\n goog.abstractMethod;\r\n\r\n\r\n/**\r\n * For applications to query the current HTTP session id, sent by the server\r\n * during the initial handshake.\r\n *\r\n * @return {?string} the HTTP session id or null if no HTTP session is in use.\r\n */\r\ngoog.net.WebChannel.RuntimeProperties.prototype.getHttpSessionId =\r\n goog.abstractMethod;\r\n\r\n\r\n/**\r\n * Experimental API.\r\n *\r\n * This method generates an in-band commit request to the server, which will\r\n * ack the commit request as soon as all messages sent prior to this commit\r\n * request have been committed by the application.\r\n *\r\n * Committing a message has a stronger semantics than delivering a message\r\n * to the application. Detail spec:\r\n * https://github.com/bidiweb/webchannel/blob/master/commit.md\r\n *\r\n * Timeout or cancellation is not supported and the application is expected to\r\n * abort the channel if the commit-ack fails to arrive in time.\r\n *\r\n * ===\r\n *\r\n * This is currently implemented only in the client layer and the commit\r\n * callback will be invoked after all the pending client-sent messages have been\r\n * delivered by the server-side webchannel end-point. This semantics is\r\n * different and weaker than what's required for end-to-end ack which requires\r\n * the server application to ack the in-order delivery of messages that are sent\r\n * before the commit request is issued.\r\n *\r\n * Commit should only be called after the channel open event is received.\r\n * Duplicated commits are allowed and only the last callback is guaranteed.\r\n * Commit called after the channel has been closed will be ignored.\r\n *\r\n * @param {function()} callback The callback will be invoked once an\r\n * ack has been received for the current commit or any newly issued commit.\r\n */\r\ngoog.net.WebChannel.RuntimeProperties.prototype.commit = goog.abstractMethod;\r\n\r\n\r\n/**\r\n * This method may be used by the application to recover from a peer failure\r\n * or to enable sender-initiated flow-control.\r\n *\r\n * Detail spec: https://github.com/bidiweb/webchannel/blob/master/commit.md\r\n *\r\n * This is not yet implemented.\r\n *\r\n * @return {number} The total number of messages that have not received\r\n * commit-ack from the server; or if no commit has been issued, the number\r\n * of messages that have not been delivered to the server application.\r\n */\r\ngoog.net.WebChannel.RuntimeProperties.prototype.getNonAckedMessageCount =\r\n goog.abstractMethod;\r\n\r\n\r\n/**\r\n * A low water-mark message count to notify the application when the\r\n * flow-control condition is cleared, that is, when the application is\r\n * able to send more messages.\r\n *\r\n * We expect the application to configure a high water-mark message count,\r\n * which is checked via getNonAckedMessageCount(). When the high water-mark\r\n * is exceeded, the application should install a callback via this method\r\n * to be notified when to start to send new messages.\r\n *\r\n * This is not yet implemented.\r\n *\r\n * @param {number} count The low water-mark count. It is an error to pass\r\n * a non-positive value.\r\n * @param {function()} callback The call back to notify the application\r\n * when NonAckedMessageCount is below the specified low water-mark count.\r\n * Any previously registered callback is cleared. This new callback will\r\n * be cleared once it has been fired, or when the channel is closed or aborted.\r\n */\r\ngoog.net.WebChannel.RuntimeProperties.prototype.notifyNonAckedMessageCount =\r\n goog.abstractMethod;\r\n\r\n\r\n/**\r\n * Experimental API.\r\n *\r\n * This method registers a callback to handle the commit request sent\r\n * by the server. Commit protocol spec:\r\n * https://github.com/bidiweb/webchannel/blob/master/commit.md\r\n *\r\n * This is not yet implemented.\r\n *\r\n * @param {function(!Object)} callback The callback will take an opaque\r\n * commitId which needs be passed back to the server when an ack-commit\r\n * response is generated by the client application, via ackCommit().\r\n */\r\ngoog.net.WebChannel.RuntimeProperties.prototype.onCommit = goog.abstractMethod;\r\n\r\n\r\n/**\r\n * Experimental API.\r\n *\r\n * This method is used by the application to generate an ack-commit response\r\n * for the given commitId. Commit protocol spec:\r\n * https://github.com/bidiweb/webchannel/blob/master/commit.md\r\n *\r\n * This is not yet implemented.\r\n *\r\n * @param {!Object} commitId The commitId which denotes the commit request\r\n * from the server that needs be ack'ed.\r\n */\r\ngoog.net.WebChannel.RuntimeProperties.prototype.ackCommit = goog.abstractMethod;\r\n\r\n\r\n/**\r\n * @return {number} The last HTTP status code received by the channel.\r\n */\r\ngoog.net.WebChannel.RuntimeProperties.prototype.getLastStatusCode =\r\n goog.abstractMethod;\r\n\r\n\r\n/**\r\n * Enum to indicate the current recovery state.\r\n *\r\n * @enum {string}\r\n */\r\ngoog.net.WebChannel.FailureRecovery.State = {\r\n /** Initial state. */\r\n INIT: 'init',\r\n\r\n /** Once a failure has been detected. */\r\n FAILED: 'failed',\r\n\r\n /**\r\n * Once a recovery operation has been issued, e.g. a new request to resume\r\n * communication.\r\n */\r\n RECOVERING: 'recovering',\r\n\r\n /** The channel has been closed. */\r\n CLOSED: 'closed'\r\n};\r\n\r\n\r\n/**\r\n * Enum to indicate different failure conditions as detected by the webchannel\r\n * runtime.\r\n *\r\n * This enum is to be used only between the runtime and FailureRecovery module,\r\n * and new states are expected to be introduced in future.\r\n *\r\n * @enum {string}\r\n */\r\ngoog.net.WebChannel.FailureRecovery.FailureCondition = {\r\n /**\r\n * The HTTP response returned a non-successful http status code.\r\n */\r\n HTTP_ERROR: 'http_error',\r\n\r\n /**\r\n * The request was aborted.\r\n */\r\n ABORT: 'abort',\r\n\r\n /**\r\n * The request timed out.\r\n */\r\n TIMEOUT: 'timeout',\r\n\r\n /**\r\n * Exception was thrown while processing the request/response.\r\n */\r\n EXCEPTION: 'exception'\r\n};\r\n\r\n\r\n/**\r\n * @return {!goog.net.WebChannel.FailureRecovery.State} the current state,\r\n * mainly for debugging use.\r\n */\r\ngoog.net.WebChannel.FailureRecovery.prototype.getState = goog.abstractMethod;\r\n\r\n\r\n/**\r\n * This method is for WebChannel runtime to set the current failure condition\r\n * and to provide a callback for the algorithm to signal to the runtime\r\n * when it is time to issue a recovery operation, e.g. a new request to the\r\n * server.\r\n *\r\n * Supported transitions include:\r\n * INIT->FAILED\r\n * FAILED->FAILED (re-entry ok)\r\n * RECOVERY->FAILED.\r\n *\r\n * Ignored if state == CLOSED.\r\n *\r\n * Advanced implementations are expected to track all the state transitions\r\n * and their timestamps for monitoring purposes.\r\n *\r\n * @param {!goog.net.WebChannel.FailureRecovery.FailureCondition} failure The\r\n * new failure condition generated by the WebChannel runtime.\r\n * @param {!Function} operation The callback function to the WebChannel\r\n * runtime to issue a recovery operation, e.g. a new request. E.g. the default\r\n * recovery algorithm will issue timeout-based recovery operations.\r\n * Post-condition for the callback: state transition to RECOVERING.\r\n *\r\n * @return {!goog.net.WebChannel.FailureRecovery.State} The updated state\r\n * as decided by the failure recovery module. Upon a recoverable failure event,\r\n * the state is transitioned to RECOVERING; or the state is transitioned to\r\n * FAILED which indicates a fail-fast decision for the runtime to execute.\r\n */\r\ngoog.net.WebChannel.FailureRecovery.prototype.setFailure = goog.abstractMethod;\r\n\r\n\r\n/**\r\n * The Webchannel runtime needs call this method when webchannel is closed or\r\n * aborted.\r\n *\r\n * Once the instance is closed, any access to the instance will be a no-op.\r\n */\r\ngoog.net.WebChannel.FailureRecovery.prototype.close = goog.abstractMethod;\r\n\r\n\r\n/**\r\n * A request header to indicate to the server the messaging protocol\r\n * each HTTP message is speaking.\r\n *\r\n * @type {string}\r\n */\r\ngoog.net.WebChannel.X_CLIENT_PROTOCOL = 'X-Client-Protocol';\r\n\r\n\r\n/**\r\n * The value for x-client-protocol when the messaging protocol is WebChannel.\r\n *\r\n * @type {string}\r\n */\r\ngoog.net.WebChannel.X_CLIENT_PROTOCOL_WEB_CHANNEL = 'webchannel';\r\n\r\n\r\n/**\r\n * A response header for the server to signal the wire-protocol that\r\n * the browser establishes with the server (or proxy), e.g. \"spdy\" (aka http/2)\r\n * \"quic\". This information avoids the need to use private APIs to decide if\r\n * HTTP requests are multiplexed etc.\r\n *\r\n * @type {string}\r\n */\r\ngoog.net.WebChannel.X_CLIENT_WIRE_PROTOCOL = 'X-Client-Wire-Protocol';\r\n\r\n\r\n/**\r\n * A response header for the server to send back the HTTP session id as part of\r\n * the initial handshake. The value of the HTTP session id is opaque to the\r\n * WebChannel protocol.\r\n *\r\n * @type {string}\r\n */\r\ngoog.net.WebChannel.X_HTTP_SESSION_ID = 'X-HTTP-Session-Id';\r\n\r\n\r\n/**\r\n * A response header for the server to send back any initial response data as a\r\n * header to avoid any possible buffering by an intermediary, which may\r\n * be undesired during the handshake.\r\n *\r\n * @type {string}\r\n */\r\ngoog.net.WebChannel.X_HTTP_INITIAL_RESPONSE = 'X-HTTP-Initial-Response';\r\n\r\n\r\n/**\r\n * A request header for specifying the content-type of WebChannel messages,\r\n * e.g. application-defined JSON encoding styles. Currently this header\r\n * is sent by the client via initMessageHeaders when the channel is opened.\r\n *\r\n * @type {string}\r\n */\r\ngoog.net.WebChannel.X_WEBCHANNEL_CONTENT_TYPE = 'X-WebChannel-Content-Type';\r\n\r\n\r\n/**\r\n * A request header for specifying the client profile in order to apply\r\n * customized config params on the server side, e.g. timeouts.\r\n *\r\n * @type {string}\r\n */\r\ngoog.net.WebChannel.X_WEBCHANNEL_CLIENT_PROFILE = 'X-WebChannel-Client-Profile';\r\n","// Copyright 2006 The Closure Library Authors. All Rights Reserved.\r\n//\r\n// Licensed under the Apache License, Version 2.0 (the \"License\");\r\n// you may not use this file except in compliance with the License.\r\n// You may obtain a copy of the License at\r\n//\r\n// http://www.apache.org/licenses/LICENSE-2.0\r\n//\r\n// Unless required by applicable law or agreed to in writing, software\r\n// distributed under the License is distributed on an \"AS-IS\" BASIS,\r\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n// See the License for the specific language governing permissions and\r\n// limitations under the License.\r\n\r\n/**\r\n * @fileoverview Definition of the ChannelRequest class. The request\r\n * object encapsulates the logic for making a single request, either for the\r\n * forward channel, back channel, or test channel, to the server. It contains\r\n * the logic for the two types of transports we use:\r\n * XMLHTTP and Image request. It provides timeout detection. More transports\r\n * to be added in future, such as Fetch, WebSocket.\r\n */\r\n\r\n\r\ngoog.provide('goog.labs.net.webChannel.ChannelRequest');\r\n\r\ngoog.require('goog.Timer');\r\ngoog.require('goog.async.Throttle');\r\ngoog.require('goog.events.EventHandler');\r\ngoog.require('goog.labs.net.webChannel.Channel');\r\ngoog.require('goog.labs.net.webChannel.WebChannelDebug');\r\ngoog.require('goog.labs.net.webChannel.environment');\r\ngoog.require('goog.labs.net.webChannel.requestStats');\r\ngoog.require('goog.net.ErrorCode');\r\ngoog.require('goog.net.EventType');\r\ngoog.require('goog.net.WebChannel');\r\ngoog.require('goog.net.XmlHttp');\r\ngoog.require('goog.object');\r\ngoog.require('goog.string');\r\ngoog.require('goog.userAgent');\r\n\r\ngoog.forwardDeclare('goog.Uri');\r\ngoog.forwardDeclare('goog.net.XhrIo');\r\n\r\n\r\n\r\n/**\r\n * A new ChannelRequest is created for each request to the server.\r\n *\r\n * @param {goog.labs.net.webChannel.Channel} channel\r\n * The channel that owns this request.\r\n * @param {goog.labs.net.webChannel.WebChannelDebug} channelDebug A\r\n * WebChannelDebug to use for logging.\r\n * @param {string=} opt_sessionId The session id for the channel.\r\n * @param {string|number=} opt_requestId The request id for this request.\r\n * @param {number=} opt_retryId The retry id for this request.\r\n * @constructor\r\n * @struct\r\n * @final\r\n */\r\ngoog.labs.net.webChannel.ChannelRequest = function(\r\n channel, channelDebug, opt_sessionId, opt_requestId, opt_retryId) {\r\n /**\r\n * The channel object that owns the request.\r\n * @private {goog.labs.net.webChannel.Channel}\r\n */\r\n this.channel_ = channel;\r\n\r\n /**\r\n * The channel debug to use for logging\r\n * @private {goog.labs.net.webChannel.WebChannelDebug}\r\n */\r\n this.channelDebug_ = channelDebug;\r\n\r\n /**\r\n * The Session ID for the channel.\r\n * @private {string|undefined}\r\n */\r\n this.sid_ = opt_sessionId;\r\n\r\n /**\r\n * The RID (request ID) for the request.\r\n * @private {string|number|undefined}\r\n */\r\n this.rid_ = opt_requestId;\r\n\r\n /**\r\n * The attempt number of the current request.\r\n * @private {number}\r\n */\r\n this.retryId_ = opt_retryId || 1;\r\n\r\n /**\r\n * An object to keep track of the channel request event listeners.\r\n * @private {!goog.events.EventHandler<\r\n * !goog.labs.net.webChannel.ChannelRequest>}\r\n */\r\n this.eventHandler_ = new goog.events.EventHandler(this);\r\n\r\n /**\r\n * The timeout in ms before failing the request.\r\n * @private {number}\r\n */\r\n this.timeout_ = goog.labs.net.webChannel.ChannelRequest.TIMEOUT_MS_;\r\n\r\n /**\r\n * A timer for polling responseText in browsers that don't fire\r\n * onreadystatechange during incremental loading of responseText.\r\n * @private {goog.Timer}\r\n */\r\n this.pollingTimer_ =\r\n new goog.Timer(goog.labs.net.webChannel.environment.getPollingInterval());\r\n\r\n /**\r\n * Extra HTTP headers to add to all the requests sent to the server.\r\n * @private {Object}\r\n */\r\n this.extraHeaders_ = null;\r\n\r\n\r\n /**\r\n * Whether the request was successful. This is only set to true after the\r\n * request successfully completes.\r\n * @private {boolean}\r\n */\r\n this.successful_ = false;\r\n\r\n\r\n /**\r\n * The TimerID of the timer used to detect if the request has timed-out.\r\n * @type {?number}\r\n * @private\r\n */\r\n this.watchDogTimerId_ = null;\r\n\r\n /**\r\n * The time in the future when the request will timeout.\r\n * @private {?number}\r\n */\r\n this.watchDogTimeoutTime_ = null;\r\n\r\n /**\r\n * The time the request started.\r\n * @private {?number}\r\n */\r\n this.requestStartTime_ = null;\r\n\r\n /**\r\n * The type of request (XMLHTTP, IMG)\r\n * @private {?number}\r\n */\r\n this.type_ = null;\r\n\r\n /**\r\n * The base Uri for the request. The includes all the parameters except the\r\n * one that indicates the retry number.\r\n * @private {goog.Uri}\r\n */\r\n this.baseUri_ = null;\r\n\r\n /**\r\n * The request Uri that was actually used for the most recent request attempt.\r\n * @private {goog.Uri}\r\n */\r\n this.requestUri_ = null;\r\n\r\n /**\r\n * The post data, if the request is a post.\r\n * @private {?string}\r\n */\r\n this.postData_ = null;\r\n\r\n /**\r\n * An array of pending messages that we have either received a non-successful\r\n * response for, or no response at all, and which therefore may or may not\r\n * have been received by the server.\r\n * @private {!Array<goog.labs.net.webChannel.Wire.QueuedMap>}\r\n */\r\n this.pendingMessages_ = [];\r\n\r\n /**\r\n * The XhrLte request if the request is using XMLHTTP\r\n * @private {goog.net.XhrIo}\r\n */\r\n this.xmlHttp_ = null;\r\n\r\n /**\r\n * The position of where the next unprocessed chunk starts in the response\r\n * text.\r\n * @private {number}\r\n */\r\n this.xmlHttpChunkStart_ = 0;\r\n\r\n /**\r\n * The verb (Get or Post) for the request.\r\n * @private {?string}\r\n */\r\n this.verb_ = null;\r\n\r\n /**\r\n * The last error if the request failed.\r\n * @private {?goog.labs.net.webChannel.ChannelRequest.Error}\r\n */\r\n this.lastError_ = null;\r\n\r\n /**\r\n * The last status code received.\r\n * @private {number}\r\n */\r\n this.lastStatusCode_ = -1;\r\n\r\n /**\r\n * Whether the request has been cancelled due to a call to cancel.\r\n * @private {boolean}\r\n */\r\n this.cancelled_ = false;\r\n\r\n /**\r\n * A throttle time in ms for readystatechange events for the backchannel.\r\n * Useful for throttling when ready state is INTERACTIVE (partial data).\r\n * If set to zero no throttle is used.\r\n *\r\n * See WebChannelBase.prototype.readyStateChangeThrottleMs_\r\n *\r\n * @private {number}\r\n */\r\n this.readyStateChangeThrottleMs_ = 0;\r\n\r\n /**\r\n * The throttle for readystatechange events for the current request, or null\r\n * if there is none.\r\n * @private {goog.async.Throttle}\r\n */\r\n this.readyStateChangeThrottle_ = null;\r\n\r\n /**\r\n * Whether to the result is expected to be encoded for chunking and thus\r\n * requires decoding.\r\n * @private {boolean}\r\n */\r\n this.decodeChunks_ = false;\r\n\r\n /**\r\n * Whether to decode x-http-initial-response.\r\n * @private {boolean}\r\n */\r\n this.decodeInitialResponse_ = false;\r\n\r\n /**\r\n * Whether x-http-initial-response has been decoded (dispatched).\r\n * @private {boolean}\r\n */\r\n this.initialResponseDecoded_ = false;\r\n};\r\n\r\n\r\ngoog.scope(function() {\r\nvar WebChannel = goog.net.WebChannel;\r\nvar Channel = goog.labs.net.webChannel.Channel;\r\nvar ChannelRequest = goog.labs.net.webChannel.ChannelRequest;\r\nvar requestStats = goog.labs.net.webChannel.requestStats;\r\nvar WebChannelDebug = goog.labs.net.webChannel.WebChannelDebug;\r\nvar environment = goog.labs.net.webChannel.environment;\r\n\r\n\r\n/**\r\n * Default timeout in MS for a request. The server must return data within this\r\n * time limit for the request to not timeout.\r\n * @private {number}\r\n */\r\nChannelRequest.TIMEOUT_MS_ = 45 * 1000;\r\n\r\n\r\n/**\r\n * Enum for channel requests type\r\n * @enum {number}\r\n * @private\r\n */\r\nChannelRequest.Type_ = {\r\n /**\r\n * XMLHTTP requests.\r\n */\r\n XML_HTTP: 1,\r\n\r\n /**\r\n * IMG requests.\r\n */\r\n CLOSE_REQUEST: 2\r\n};\r\n\r\n\r\n/**\r\n * Enum type for identifying an error.\r\n * @enum {number}\r\n */\r\nChannelRequest.Error = {\r\n /**\r\n * Errors due to a non-200 status code.\r\n */\r\n STATUS: 0,\r\n\r\n /**\r\n * Errors due to no data being returned.\r\n */\r\n NO_DATA: 1,\r\n\r\n /**\r\n * Errors due to a timeout.\r\n */\r\n TIMEOUT: 2,\r\n\r\n /**\r\n * Errors due to the server returning an unknown.\r\n */\r\n UNKNOWN_SESSION_ID: 3,\r\n\r\n /**\r\n * Errors due to bad data being received.\r\n */\r\n BAD_DATA: 4,\r\n\r\n /**\r\n * Errors due to the handler throwing an exception.\r\n */\r\n HANDLER_EXCEPTION: 5,\r\n\r\n /**\r\n * The browser declared itself offline during the request.\r\n */\r\n BROWSER_OFFLINE: 6\r\n};\r\n\r\n\r\n/**\r\n * Returns a useful error string for debugging based on the specified error\r\n * code.\r\n * @param {?ChannelRequest.Error} errorCode The error code.\r\n * @param {number} statusCode The HTTP status code.\r\n * @return {string} The error string for the given code combination.\r\n */\r\nChannelRequest.errorStringFromCode = function(errorCode, statusCode) {\r\n switch (errorCode) {\r\n case ChannelRequest.Error.STATUS:\r\n return 'Non-200 return code (' + statusCode + ')';\r\n case ChannelRequest.Error.NO_DATA:\r\n return 'XMLHTTP failure (no data)';\r\n case ChannelRequest.Error.TIMEOUT:\r\n return 'HttpConnection timeout';\r\n default:\r\n return 'Unknown error';\r\n }\r\n};\r\n\r\n\r\n/**\r\n * Sentinel value used to indicate an invalid chunk in a multi-chunk response.\r\n * @private {Object}\r\n */\r\nChannelRequest.INVALID_CHUNK_ = {};\r\n\r\n\r\n/**\r\n * Sentinel value used to indicate an incomplete chunk in a multi-chunk\r\n * response.\r\n * @private {Object}\r\n */\r\nChannelRequest.INCOMPLETE_CHUNK_ = {};\r\n\r\n\r\n/**\r\n * Returns whether XHR streaming is supported on this browser.\r\n *\r\n * @return {boolean} Whether XHR streaming is supported.\r\n * @see http://code.google.com/p/closure-library/issues/detail?id=346\r\n */\r\nChannelRequest.supportsXhrStreaming = function() {\r\n return !goog.userAgent.IE || goog.userAgent.isDocumentModeOrHigher(10);\r\n};\r\n\r\n\r\n/**\r\n * Sets extra HTTP headers to add to all the requests sent to the server.\r\n *\r\n * @param {Object} extraHeaders The HTTP headers.\r\n */\r\nChannelRequest.prototype.setExtraHeaders = function(extraHeaders) {\r\n this.extraHeaders_ = extraHeaders;\r\n};\r\n\r\n\r\n/**\r\n * Overrides the default HTTP method.\r\n *\r\n * @param {string} verb The HTTP method\r\n */\r\nChannelRequest.prototype.setVerb = function(verb) {\r\n this.verb_ = verb;\r\n};\r\n\r\n\r\n/**\r\n * Sets the timeout for a request\r\n *\r\n * @param {number} timeout The timeout in MS for when we fail the request.\r\n */\r\nChannelRequest.prototype.setTimeout = function(timeout) {\r\n this.timeout_ = timeout;\r\n};\r\n\r\n\r\n/**\r\n * Sets the throttle for handling onreadystatechange events for the request.\r\n *\r\n * @param {number} throttle The throttle in ms. A value of zero indicates\r\n * no throttle.\r\n */\r\nChannelRequest.prototype.setReadyStateChangeThrottle = function(throttle) {\r\n this.readyStateChangeThrottleMs_ = throttle;\r\n};\r\n\r\n\r\n/**\r\n * Sets the pending messages that this request is handling.\r\n *\r\n * @param {!Array<goog.labs.net.webChannel.Wire.QueuedMap>} pendingMessages\r\n * The pending messages for this request.\r\n */\r\nChannelRequest.prototype.setPendingMessages = function(pendingMessages) {\r\n this.pendingMessages_ = pendingMessages;\r\n};\r\n\r\n\r\n/**\r\n * Gets the pending messages that this request is handling, in case of a retry.\r\n *\r\n * @return {!Array<goog.labs.net.webChannel.Wire.QueuedMap>} The pending\r\n * messages for this request.\r\n */\r\nChannelRequest.prototype.getPendingMessages = function() {\r\n return this.pendingMessages_;\r\n};\r\n\r\n\r\n/**\r\n * Uses XMLHTTP to send an HTTP POST to the server.\r\n *\r\n * @param {goog.Uri} uri The uri of the request.\r\n * @param {?string} postData The data for the post body.\r\n * @param {boolean} decodeChunks Whether to the result is expected to be\r\n * encoded for chunking and thus requires decoding.\r\n */\r\nChannelRequest.prototype.xmlHttpPost = function(uri, postData, decodeChunks) {\r\n this.type_ = ChannelRequest.Type_.XML_HTTP;\r\n this.baseUri_ = uri.clone().makeUnique();\r\n this.postData_ = postData;\r\n this.decodeChunks_ = decodeChunks;\r\n this.sendXmlHttp_(null /* hostPrefix */);\r\n};\r\n\r\n\r\n/**\r\n * Uses XMLHTTP to send an HTTP GET to the server.\r\n *\r\n * @param {goog.Uri} uri The uri of the request.\r\n * @param {boolean} decodeChunks Whether to the result is expected to be\r\n * encoded for chunking and thus requires decoding.\r\n * @param {?string} hostPrefix The host prefix, if we might be using a\r\n * secondary domain. Note that it should also be in the URL, adding this\r\n * won't cause it to be added to the URL.\r\n */\r\nChannelRequest.prototype.xmlHttpGet = function(uri, decodeChunks, hostPrefix) {\r\n this.type_ = ChannelRequest.Type_.XML_HTTP;\r\n this.baseUri_ = uri.clone().makeUnique();\r\n this.postData_ = null;\r\n this.decodeChunks_ = decodeChunks;\r\n\r\n this.sendXmlHttp_(hostPrefix);\r\n};\r\n\r\n\r\n/**\r\n * Sends a request via XMLHTTP according to the current state of the request\r\n * object.\r\n *\r\n * @param {?string} hostPrefix The host prefix, if we might be using a secondary\r\n * domain.\r\n * @private\r\n */\r\nChannelRequest.prototype.sendXmlHttp_ = function(hostPrefix) {\r\n this.requestStartTime_ = goog.now();\r\n this.ensureWatchDogTimer_();\r\n\r\n // clone the base URI to create the request URI. The request uri has the\r\n // attempt number as a parameter which helps in debugging.\r\n this.requestUri_ = this.baseUri_.clone();\r\n this.requestUri_.setParameterValues('t', this.retryId_);\r\n\r\n // send the request either as a POST or GET\r\n this.xmlHttpChunkStart_ = 0;\r\n var useSecondaryDomains = this.channel_.shouldUseSecondaryDomains();\r\n this.xmlHttp_ =\r\n this.channel_.createXhrIo(useSecondaryDomains ? hostPrefix : null);\r\n\r\n if (this.readyStateChangeThrottleMs_ > 0) {\r\n this.readyStateChangeThrottle_ = new goog.async.Throttle(\r\n goog.bind(this.xmlHttpHandler_, this, this.xmlHttp_),\r\n this.readyStateChangeThrottleMs_);\r\n }\r\n\r\n this.eventHandler_.listen(\r\n this.xmlHttp_, goog.net.EventType.READY_STATE_CHANGE,\r\n this.readyStateChangeHandler_);\r\n\r\n var headers = this.extraHeaders_ ? goog.object.clone(this.extraHeaders_) : {};\r\n if (this.postData_) {\r\n if (!this.verb_) {\r\n this.verb_ = 'POST';\r\n }\r\n headers['Content-Type'] = 'application/x-www-form-urlencoded';\r\n this.xmlHttp_.send(this.requestUri_, this.verb_, this.postData_, headers);\r\n } else {\r\n this.verb_ = 'GET';\r\n this.xmlHttp_.send(this.requestUri_, this.verb_, null, headers);\r\n }\r\n requestStats.notifyServerReachabilityEvent(\r\n requestStats.ServerReachability.REQUEST_MADE);\r\n this.channelDebug_.xmlHttpChannelRequest(\r\n this.verb_, this.requestUri_, this.rid_, this.retryId_, this.postData_);\r\n};\r\n\r\n\r\n/**\r\n * Handles a readystatechange event.\r\n * @param {goog.events.Event} evt The event.\r\n * @private\r\n */\r\nChannelRequest.prototype.readyStateChangeHandler_ = function(evt) {\r\n var xhr = /** @type {goog.net.XhrIo} */ (evt.target);\r\n var throttle = this.readyStateChangeThrottle_;\r\n if (throttle &&\r\n xhr.getReadyState() == goog.net.XmlHttp.ReadyState.INTERACTIVE) {\r\n // Only throttle in the partial data case.\r\n this.channelDebug_.debug('Throttling readystatechange.');\r\n throttle.fire();\r\n } else {\r\n // If we haven't throttled, just handle response directly.\r\n this.xmlHttpHandler_(xhr);\r\n }\r\n};\r\n\r\n\r\n/**\r\n * XmlHttp handler\r\n * @param {goog.net.XhrIo} xmlhttp The XhrIo object for the current request.\r\n * @private\r\n */\r\nChannelRequest.prototype.xmlHttpHandler_ = function(xmlhttp) {\r\n requestStats.onStartExecution();\r\n\r\n\r\n try {\r\n if (xmlhttp == this.xmlHttp_) {\r\n this.onXmlHttpReadyStateChanged_();\r\n } else {\r\n this.channelDebug_.warning(\r\n 'Called back with an ' +\r\n 'unexpected xmlhttp');\r\n }\r\n } catch (ex) {\r\n this.channelDebug_.debug('Failed call to OnXmlHttpReadyStateChanged_');\r\n if (this.xmlHttp_ && this.xmlHttp_.getResponseText()) {\r\n var channelRequest = this;\r\n this.channelDebug_.dumpException(ex, function() {\r\n return 'ResponseText: ' + channelRequest.xmlHttp_.getResponseText();\r\n });\r\n } else {\r\n this.channelDebug_.dumpException(ex, 'No response text');\r\n }\r\n } finally {\r\n requestStats.onEndExecution();\r\n }\r\n};\r\n\r\n\r\n/**\r\n * Called by the readystate handler for XMLHTTP requests.\r\n *\r\n * @private\r\n */\r\nChannelRequest.prototype.onXmlHttpReadyStateChanged_ = function() {\r\n var readyState = this.xmlHttp_.getReadyState();\r\n var errorCode = this.xmlHttp_.getLastErrorCode();\r\n var statusCode = this.xmlHttp_.getStatus();\r\n\r\n // we get partial results in browsers that support ready state interactive.\r\n // We also make sure that getResponseText is not null in interactive mode\r\n // before we continue.\r\n if (readyState < goog.net.XmlHttp.ReadyState.INTERACTIVE ||\r\n (readyState == goog.net.XmlHttp.ReadyState.INTERACTIVE &&\r\n !environment.isPollingRequired() && // otherwise, go on to startPolling\r\n !this.xmlHttp_.getResponseText())) {\r\n return; // not yet ready\r\n }\r\n\r\n // Dispatch any appropriate network events.\r\n if (!this.cancelled_ && readyState == goog.net.XmlHttp.ReadyState.COMPLETE &&\r\n errorCode != goog.net.ErrorCode.ABORT) {\r\n // Pretty conservative, these are the only known scenarios which we'd\r\n // consider indicative of a truly non-functional network connection.\r\n if (errorCode == goog.net.ErrorCode.TIMEOUT || statusCode <= 0) {\r\n requestStats.notifyServerReachabilityEvent(\r\n requestStats.ServerReachability.REQUEST_FAILED);\r\n } else {\r\n requestStats.notifyServerReachabilityEvent(\r\n requestStats.ServerReachability.REQUEST_SUCCEEDED);\r\n }\r\n }\r\n\r\n // got some data so cancel the watchdog timer\r\n this.cancelWatchDogTimer_();\r\n\r\n var status = this.xmlHttp_.getStatus();\r\n this.lastStatusCode_ = status;\r\n var responseText = this.xmlHttp_.getResponseText();\r\n if (!responseText) {\r\n var channelRequest = this;\r\n this.channelDebug_.debug(function() {\r\n return 'No response text for uri ' + channelRequest.requestUri_ +\r\n ' status ' + status;\r\n });\r\n }\r\n this.successful_ = (status == 200);\r\n\r\n this.channelDebug_.xmlHttpChannelResponseMetaData(\r\n /** @type {string} */ (this.verb_), this.requestUri_, this.rid_,\r\n this.retryId_, readyState, status);\r\n\r\n if (!this.successful_) {\r\n if (status == 400 && responseText.indexOf('Unknown SID') > 0) {\r\n // the server error string will include 'Unknown SID' which indicates the\r\n // server doesn't know about the session (maybe it got restarted, maybe\r\n // the user got moved to another server, etc.,). Handlers can special\r\n // case this error\r\n this.lastError_ = ChannelRequest.Error.UNKNOWN_SESSION_ID;\r\n requestStats.notifyStatEvent(\r\n requestStats.Stat.REQUEST_UNKNOWN_SESSION_ID);\r\n this.channelDebug_.warning('XMLHTTP Unknown SID (' + this.rid_ + ')');\r\n } else {\r\n this.lastError_ = ChannelRequest.Error.STATUS;\r\n requestStats.notifyStatEvent(requestStats.Stat.REQUEST_BAD_STATUS);\r\n this.channelDebug_.warning(\r\n 'XMLHTTP Bad status ' + status + ' (' + this.rid_ + ')');\r\n }\r\n this.cleanup_();\r\n this.dispatchFailure_();\r\n return;\r\n }\r\n\r\n if (this.shouldCheckInitialResponse_()) {\r\n var initialResponse = this.getInitialResponse_();\r\n if (initialResponse) {\r\n this.channelDebug_.xmlHttpChannelResponseText(\r\n this.rid_, initialResponse,\r\n 'Initial handshake response via ' +\r\n WebChannel.X_HTTP_INITIAL_RESPONSE);\r\n this.initialResponseDecoded_ = true;\r\n this.safeOnRequestData_(initialResponse);\r\n } else {\r\n this.successful_ = false;\r\n this.lastError_ = ChannelRequest.Error.UNKNOWN_SESSION_ID; // fail-fast\r\n requestStats.notifyStatEvent(\r\n requestStats.Stat.REQUEST_UNKNOWN_SESSION_ID);\r\n this.channelDebug_.warning(\r\n 'XMLHTTP Missing X_HTTP_INITIAL_RESPONSE' +\r\n ' (' + this.rid_ + ')');\r\n this.cleanup_();\r\n this.dispatchFailure_();\r\n return;\r\n }\r\n }\r\n\r\n if (this.decodeChunks_) {\r\n this.decodeNextChunks_(readyState, responseText);\r\n if (environment.isPollingRequired() && this.successful_ &&\r\n readyState == goog.net.XmlHttp.ReadyState.INTERACTIVE) {\r\n this.startPolling_();\r\n }\r\n } else {\r\n this.channelDebug_.xmlHttpChannelResponseText(\r\n this.rid_, responseText, null);\r\n this.safeOnRequestData_(responseText);\r\n }\r\n\r\n if (readyState == goog.net.XmlHttp.ReadyState.COMPLETE) {\r\n this.cleanup_();\r\n }\r\n\r\n if (!this.successful_) {\r\n return;\r\n }\r\n\r\n if (!this.cancelled_) {\r\n if (readyState == goog.net.XmlHttp.ReadyState.COMPLETE) {\r\n this.channel_.onRequestComplete(this);\r\n } else {\r\n // The default is false, the result from this callback shouldn't carry\r\n // over to the next callback, otherwise the request looks successful if\r\n // the watchdog timer gets called\r\n this.successful_ = false;\r\n this.ensureWatchDogTimer_();\r\n }\r\n }\r\n};\r\n\r\n\r\n/**\r\n * Whether we need check the initial-response header that is sent during the\r\n * fast handshake.\r\n *\r\n * @return {boolean} true if the initial-response header is yet to be processed.\r\n * @private\r\n */\r\nChannelRequest.prototype.shouldCheckInitialResponse_ = function() {\r\n return this.decodeInitialResponse_ && !this.initialResponseDecoded_;\r\n};\r\n\r\n\r\n/**\r\n * Queries the initial response header that is sent during the handshake.\r\n *\r\n * @return {?string} The non-empty header value or null.\r\n * @private\r\n */\r\nChannelRequest.prototype.getInitialResponse_ = function() {\r\n if (this.xmlHttp_) {\r\n var value = this.xmlHttp_.getStreamingResponseHeader(\r\n WebChannel.X_HTTP_INITIAL_RESPONSE);\r\n if (value && !goog.string.isEmptyOrWhitespace(value)) {\r\n return value;\r\n }\r\n }\r\n\r\n return null;\r\n};\r\n\r\n\r\n/**\r\n * Check if the initial response header has been handled.\r\n *\r\n * @return {boolean} true if X_HTTP_INITIAL_RESPONSE has been handled.\r\n */\r\nChannelRequest.prototype.isInitialResponseDecoded = function() {\r\n return this.initialResponseDecoded_;\r\n};\r\n\r\n\r\n/**\r\n * Decodes X_HTTP_INITIAL_RESPONSE if present.\r\n */\r\nChannelRequest.prototype.setDecodeInitialResponse = function() {\r\n this.decodeInitialResponse_ = true;\r\n};\r\n\r\n\r\n/**\r\n * Decodes the next set of available chunks in the response.\r\n * @param {number} readyState The value of readyState.\r\n * @param {string} responseText The value of responseText.\r\n * @private\r\n */\r\nChannelRequest.prototype.decodeNextChunks_ = function(\r\n readyState, responseText) {\r\n var decodeNextChunksSuccessful = true;\r\n while (!this.cancelled_ && this.xmlHttpChunkStart_ < responseText.length) {\r\n var chunkText = this.getNextChunk_(responseText);\r\n if (chunkText == ChannelRequest.INCOMPLETE_CHUNK_) {\r\n if (readyState == goog.net.XmlHttp.ReadyState.COMPLETE) {\r\n // should have consumed entire response when the request is done\r\n this.lastError_ = ChannelRequest.Error.BAD_DATA;\r\n requestStats.notifyStatEvent(requestStats.Stat.REQUEST_INCOMPLETE_DATA);\r\n decodeNextChunksSuccessful = false;\r\n }\r\n this.channelDebug_.xmlHttpChannelResponseText(\r\n this.rid_, null, '[Incomplete Response]');\r\n break;\r\n } else if (chunkText == ChannelRequest.INVALID_CHUNK_) {\r\n this.lastError_ = ChannelRequest.Error.BAD_DATA;\r\n requestStats.notifyStatEvent(requestStats.Stat.REQUEST_BAD_DATA);\r\n this.channelDebug_.xmlHttpChannelResponseText(\r\n this.rid_, responseText, '[Invalid Chunk]');\r\n decodeNextChunksSuccessful = false;\r\n break;\r\n } else {\r\n this.channelDebug_.xmlHttpChannelResponseText(\r\n this.rid_, /** @type {string} */ (chunkText), null);\r\n this.safeOnRequestData_(/** @type {string} */ (chunkText));\r\n }\r\n }\r\n if (readyState == goog.net.XmlHttp.ReadyState.COMPLETE &&\r\n responseText.length == 0) {\r\n // also an error if we didn't get any response\r\n this.lastError_ = ChannelRequest.Error.NO_DATA;\r\n requestStats.notifyStatEvent(requestStats.Stat.REQUEST_NO_DATA);\r\n decodeNextChunksSuccessful = false;\r\n }\r\n this.successful_ = this.successful_ && decodeNextChunksSuccessful;\r\n if (!decodeNextChunksSuccessful) {\r\n // malformed response - we make this trigger retry logic\r\n this.channelDebug_.xmlHttpChannelResponseText(\r\n this.rid_, responseText, '[Invalid Chunked Response]');\r\n this.cleanup_();\r\n this.dispatchFailure_();\r\n }\r\n};\r\n\r\n\r\n/**\r\n * Polls the response for new data.\r\n * @private\r\n */\r\nChannelRequest.prototype.pollResponse_ = function() {\r\n if (!this.xmlHttp_) {\r\n return; // already closed\r\n }\r\n var readyState = this.xmlHttp_.getReadyState();\r\n var responseText = this.xmlHttp_.getResponseText();\r\n if (this.xmlHttpChunkStart_ < responseText.length) {\r\n this.cancelWatchDogTimer_();\r\n this.decodeNextChunks_(readyState, responseText);\r\n if (this.successful_ &&\r\n readyState != goog.net.XmlHttp.ReadyState.COMPLETE) {\r\n this.ensureWatchDogTimer_();\r\n }\r\n }\r\n};\r\n\r\n\r\n/**\r\n * Starts a polling interval for changes to responseText of the\r\n * XMLHttpRequest, for browsers that don't fire onreadystatechange\r\n * as data comes in incrementally. This timer is disabled in\r\n * cleanup_().\r\n * @private\r\n */\r\nChannelRequest.prototype.startPolling_ = function() {\r\n this.eventHandler_.listen(\r\n this.pollingTimer_, goog.Timer.TICK, this.pollResponse_);\r\n this.pollingTimer_.start();\r\n};\r\n\r\n\r\n/**\r\n * Returns the next chunk of a chunk-encoded response. This is not standard\r\n * HTTP chunked encoding because browsers don't expose the chunk boundaries to\r\n * the application through XMLHTTP. So we have an additional chunk encoding at\r\n * the application level that lets us tell where the beginning and end of\r\n * individual responses are so that we can only try to eval a complete JS array.\r\n *\r\n * The encoding is the size of the chunk encoded as a decimal string followed\r\n * by a newline followed by the data.\r\n *\r\n * @param {string} responseText The response text from the XMLHTTP response.\r\n * @return {string|Object} The next chunk string or a sentinel object\r\n * indicating a special condition.\r\n * @private\r\n */\r\nChannelRequest.prototype.getNextChunk_ = function(responseText) {\r\n var sizeStartIndex = this.xmlHttpChunkStart_;\r\n var sizeEndIndex = responseText.indexOf('\\n', sizeStartIndex);\r\n if (sizeEndIndex == -1) {\r\n return ChannelRequest.INCOMPLETE_CHUNK_;\r\n }\r\n\r\n var sizeAsString = responseText.substring(sizeStartIndex, sizeEndIndex);\r\n var size = Number(sizeAsString);\r\n if (isNaN(size)) {\r\n return ChannelRequest.INVALID_CHUNK_;\r\n }\r\n\r\n var chunkStartIndex = sizeEndIndex + 1;\r\n if (chunkStartIndex + size > responseText.length) {\r\n return ChannelRequest.INCOMPLETE_CHUNK_;\r\n }\r\n\r\n var chunkText = responseText.substr(chunkStartIndex, size);\r\n this.xmlHttpChunkStart_ = chunkStartIndex + size;\r\n return chunkText;\r\n};\r\n\r\n\r\n/**\r\n * Uses an IMG tag or navigator.sendBeacon to send an HTTP get to the server.\r\n *\r\n * This is only currently used to terminate the connection, as an IMG tag is\r\n * the most reliable way to send something to the server while the page\r\n * is getting torn down.\r\n *\r\n * Navigator.sendBeacon is available on Chrome and Firefox as a formal\r\n * solution to ensure delivery without blocking window close. See\r\n * https://developer.mozilla.org/en-US/docs/Web/API/Navigator/sendBeacon\r\n *\r\n * For Chrome Apps, sendBeacon is always necessary due to Content Security\r\n * Policy (CSP) violation of using an IMG tag.\r\n *\r\n * For react-native, we use xhr to send the actual close request, and assume\r\n * there is no page-close issue with react-native.\r\n *\r\n * @param {goog.Uri} uri The uri to send a request to.\r\n */\r\nChannelRequest.prototype.sendCloseRequest = function(uri) {\r\n this.type_ = ChannelRequest.Type_.CLOSE_REQUEST;\r\n this.baseUri_ = uri.clone().makeUnique();\r\n\r\n var requestSent = false;\r\n\r\n if (goog.global.navigator && goog.global.navigator.sendBeacon) {\r\n // empty string body to avoid 413 error on chrome < 41\r\n requestSent =\r\n goog.global.navigator.sendBeacon(this.baseUri_.toString(), '');\r\n }\r\n\r\n if (!requestSent && goog.global.Image) {\r\n var eltImg = new Image();\r\n eltImg.src = this.baseUri_;\r\n requestSent = true;\r\n }\r\n\r\n if (!requestSent) {\r\n // no handler is set to match the sendBeacon/Image behavior\r\n this.xmlHttp_ = this.channel_.createXhrIo(null);\r\n this.xmlHttp_.send(this.baseUri_);\r\n }\r\n\r\n this.requestStartTime_ = goog.now();\r\n this.ensureWatchDogTimer_();\r\n};\r\n\r\n\r\n/**\r\n * Cancels the request no matter what the underlying transport is.\r\n */\r\nChannelRequest.prototype.cancel = function() {\r\n this.cancelled_ = true;\r\n this.cleanup_();\r\n};\r\n\r\n\r\n/**\r\n * Resets the timeout.\r\n *\r\n * @param {number=} opt_timeout The new timeout\r\n */\r\nChannelRequest.prototype.resetTimeout = function(opt_timeout) {\r\n if (opt_timeout) {\r\n this.setTimeout(opt_timeout);\r\n }\r\n // restart only if a timer is currently set\r\n if (this.watchDogTimerId_) {\r\n this.cancelWatchDogTimer_();\r\n this.ensureWatchDogTimer_();\r\n }\r\n};\r\n\r\n\r\n/**\r\n * Ensures that there is watchdog timeout which is used to ensure that\r\n * the connection completes in time.\r\n *\r\n * @private\r\n */\r\nChannelRequest.prototype.ensureWatchDogTimer_ = function() {\r\n this.watchDogTimeoutTime_ = goog.now() + this.timeout_;\r\n this.startWatchDogTimer_(this.timeout_);\r\n};\r\n\r\n\r\n/**\r\n * Starts the watchdog timer which is used to ensure that the connection\r\n * completes in time.\r\n * @param {number} time The number of milliseconds to wait.\r\n * @private\r\n */\r\nChannelRequest.prototype.startWatchDogTimer_ = function(time) {\r\n if (this.watchDogTimerId_ != null) {\r\n // assertion\r\n throw new Error('WatchDog timer not null');\r\n }\r\n this.watchDogTimerId_ =\r\n requestStats.setTimeout(goog.bind(this.onWatchDogTimeout_, this), time);\r\n};\r\n\r\n\r\n/**\r\n * Cancels the watchdog timer if it has been started.\r\n *\r\n * @private\r\n */\r\nChannelRequest.prototype.cancelWatchDogTimer_ = function() {\r\n if (this.watchDogTimerId_) {\r\n goog.global.clearTimeout(this.watchDogTimerId_);\r\n this.watchDogTimerId_ = null;\r\n }\r\n};\r\n\r\n\r\n/**\r\n * Called when the watchdog timer is triggered. It also handles a case where it\r\n * is called too early which we suspect may be happening sometimes\r\n * (not sure why)\r\n *\r\n * @private\r\n */\r\nChannelRequest.prototype.onWatchDogTimeout_ = function() {\r\n this.watchDogTimerId_ = null;\r\n var now = goog.now();\r\n if (now - this.watchDogTimeoutTime_ >= 0) {\r\n this.handleTimeout_();\r\n } else {\r\n // got called too early for some reason\r\n this.channelDebug_.warning('WatchDog timer called too early');\r\n this.startWatchDogTimer_(this.watchDogTimeoutTime_ - now);\r\n }\r\n};\r\n\r\n\r\n/**\r\n * Called when the request has actually timed out. Will cleanup and notify the\r\n * channel of the failure.\r\n *\r\n * @private\r\n */\r\nChannelRequest.prototype.handleTimeout_ = function() {\r\n if (this.successful_) {\r\n // Should never happen.\r\n this.channelDebug_.severe(\r\n 'Received watchdog timeout even though request loaded successfully');\r\n }\r\n\r\n this.channelDebug_.timeoutResponse(this.requestUri_);\r\n\r\n // IMG or SendBeacon requests never notice if they were successful,\r\n // and always 'time out'. This fact says nothing about reachability.\r\n if (this.type_ != ChannelRequest.Type_.CLOSE_REQUEST) {\r\n requestStats.notifyServerReachabilityEvent(\r\n requestStats.ServerReachability.REQUEST_FAILED);\r\n requestStats.notifyStatEvent(requestStats.Stat.REQUEST_TIMEOUT);\r\n }\r\n\r\n this.cleanup_();\r\n\r\n // Set error and dispatch failure.\r\n // This is called for CLOSE_REQUEST too to ensure channel_.onRequestComplete.\r\n this.lastError_ = ChannelRequest.Error.TIMEOUT;\r\n this.dispatchFailure_();\r\n};\r\n\r\n\r\n/**\r\n * Notifies the channel that this request failed.\r\n * @private\r\n */\r\nChannelRequest.prototype.dispatchFailure_ = function() {\r\n if (this.channel_.isClosed() || this.cancelled_) {\r\n return;\r\n }\r\n\r\n this.channel_.onRequestComplete(this);\r\n};\r\n\r\n\r\n/**\r\n * Cleans up the objects used to make the request. This function is\r\n * idempotent.\r\n *\r\n * @private\r\n */\r\nChannelRequest.prototype.cleanup_ = function() {\r\n this.cancelWatchDogTimer_();\r\n\r\n goog.dispose(this.readyStateChangeThrottle_);\r\n this.readyStateChangeThrottle_ = null;\r\n\r\n // Stop the polling timer, if necessary.\r\n this.pollingTimer_.stop();\r\n\r\n // Unhook all event handlers.\r\n this.eventHandler_.removeAll();\r\n\r\n if (this.xmlHttp_) {\r\n // clear out this.xmlHttp_ before aborting so we handle getting reentered\r\n // inside abort\r\n var xmlhttp = this.xmlHttp_;\r\n this.xmlHttp_ = null;\r\n xmlhttp.abort();\r\n xmlhttp.dispose();\r\n }\r\n};\r\n\r\n\r\n/**\r\n * Indicates whether the request was successful. Only valid after the handler\r\n * is called to indicate completion of the request.\r\n *\r\n * @return {boolean} True if the request succeeded.\r\n */\r\nChannelRequest.prototype.getSuccess = function() {\r\n return this.successful_;\r\n};\r\n\r\n\r\n/**\r\n * If the request was not successful, returns the reason.\r\n *\r\n * @return {?ChannelRequest.Error} The last error.\r\n */\r\nChannelRequest.prototype.getLastError = function() {\r\n return this.lastError_;\r\n};\r\n\r\n\r\n/**\r\n * Returns the status code of the last request.\r\n * @return {number} The status code of the last request.\r\n */\r\nChannelRequest.prototype.getLastStatusCode = function() {\r\n return this.lastStatusCode_;\r\n};\r\n\r\n\r\n/**\r\n * Returns the session id for this channel.\r\n *\r\n * @return {string|undefined} The session ID.\r\n */\r\nChannelRequest.prototype.getSessionId = function() {\r\n return this.sid_;\r\n};\r\n\r\n\r\n/**\r\n * Returns the request id for this request. Each request has a unique request\r\n * id and the request IDs are a sequential increasing count.\r\n *\r\n * @return {string|number|undefined} The request ID.\r\n */\r\nChannelRequest.prototype.getRequestId = function() {\r\n return this.rid_;\r\n};\r\n\r\n\r\n/**\r\n * Returns the data for a post, if this request is a post.\r\n *\r\n * @return {?string} The POST data provided by the request initiator.\r\n */\r\nChannelRequest.prototype.getPostData = function() {\r\n return this.postData_;\r\n};\r\n\r\n\r\n/**\r\n * Returns the XhrIo request object.\r\n *\r\n * @return {?goog.net.XhrIo} Any XhrIo request created for this object.\r\n */\r\nChannelRequest.prototype.getXhr = function() {\r\n return this.xmlHttp_;\r\n};\r\n\r\n\r\n/**\r\n * Returns the time that the request started, if it has started.\r\n *\r\n * @return {?number} The time the request started, as returned by goog.now().\r\n */\r\nChannelRequest.prototype.getRequestStartTime = function() {\r\n return this.requestStartTime_;\r\n};\r\n\r\n\r\n/**\r\n * Helper to call the callback's onRequestData, which catches any\r\n * exception.\r\n * @param {string} data The request data.\r\n * @private\r\n */\r\nChannelRequest.prototype.safeOnRequestData_ = function(data) {\r\n try {\r\n this.channel_.onRequestData(this, data);\r\n var stats = requestStats.ServerReachability;\r\n requestStats.notifyServerReachabilityEvent(stats.BACK_CHANNEL_ACTIVITY);\r\n } catch (e) {\r\n // Dump debug info, but keep going without closing the channel.\r\n this.channelDebug_.dumpException(e, 'Error in httprequest callback');\r\n }\r\n};\r\n\r\n\r\n/**\r\n * Convenience factory method.\r\n *\r\n * @param {Channel} channel The channel object that owns this request.\r\n * @param {WebChannelDebug} channelDebug A WebChannelDebug to use for logging.\r\n * @param {string=} opt_sessionId The session id for the channel.\r\n * @param {string|number=} opt_requestId The request id for this request.\r\n * @param {number=} opt_retryId The retry id for this request.\r\n * @return {!ChannelRequest} The created channel request.\r\n */\r\nChannelRequest.createChannelRequest = function(\r\n channel, channelDebug, opt_sessionId, opt_requestId, opt_retryId) {\r\n return new ChannelRequest(\r\n channel, channelDebug, opt_sessionId, opt_requestId, opt_retryId);\r\n};\r\n}); // goog.scope\r\n","// Copyright 2018 The Closure Library Authors. All Rights Reserved.\r\n//\r\n// Licensed under the Apache License, Version 2.0 (the \"License\");\r\n// you may not use this file except in compliance with the License.\r\n// You may obtain a copy of the License at\r\n//\r\n// http://www.apache.org/licenses/LICENSE-2.0\r\n//\r\n// Unless required by applicable law or agreed to in writing, software\r\n// distributed under the License is distributed on an \"AS-IS\" BASIS,\r\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n// See the License for the specific language governing permissions and\r\n// limitations under the License.\r\n\r\n/**\r\n * @fileoverview A single module to define user-agent specific environment\r\n * details.\r\n */\r\n\r\ngoog.module('goog.labs.net.webChannel.environment');\r\n\r\ngoog.module.declareLegacyNamespace();\r\n\r\nvar userAgent = goog.require('goog.userAgent');\r\n\r\n\r\n/**\r\n * The default polling interval in millis for Edge.\r\n *\r\n * Currently on edge, new-chunk events may be not be fired (at all) if a new\r\n * chunk arrives within 50ms following the previous chunk. This may be fixed\r\n * in future, which requires changes to the whatwg spec too.\r\n *\r\n * @private @const {number}\r\n */\r\nvar EDGE_POLLING_INTERVAL_ = 125;\r\n\r\n\r\n/**\r\n * History:\r\n *\r\n * IE11 is still using Trident, the traditional engine for IE.\r\n * Edge is using EdgeHTML, a fork of Trident. We are seeing the same issue\r\n * on IE-11 (reported in 2017), so treat IE the same as Edge for now.\r\n *\r\n * We used to do polling for Opera (only) with an 250ms interval, because Opera\r\n * only fires readyState == INTERACTIVE once. Opera switched to WebKit in 2013,\r\n * and then to Blink (chrome).\r\n *\r\n * TODO(user): check the raw UA string to keep polling for old, mobile operas\r\n * that may still be affected. For old Opera, double the polling interval\r\n * to 250ms.\r\n *\r\n * @return {boolean} True if polling is required with XHR.\r\n */\r\nexports.isPollingRequired = function() {\r\n return userAgent.EDGE_OR_IE;\r\n};\r\n\r\n\r\n/**\r\n * How often to poll (in MS) for changes to responseText in browsers that don't\r\n * fire onreadystatechange during incremental loading of the response body.\r\n *\r\n * @return {number|undefined} The polling interval (MS) for the current U-A;\r\n * or undefined if polling is not supposed to be enabled.\r\n */\r\nexports.getPollingInterval = function() {\r\n if (userAgent.EDGE_OR_IE) {\r\n return EDGE_POLLING_INTERVAL_;\r\n }\r\n\r\n return undefined;\r\n};\r\n","// Copyright 2006 The Closure Library Authors. All Rights Reserved.\r\n//\r\n// Licensed under the Apache License, Version 2.0 (the \"License\");\r\n// you may not use this file except in compliance with the License.\r\n// You may obtain a copy of the License at\r\n//\r\n// http://www.apache.org/licenses/LICENSE-2.0\r\n//\r\n// Unless required by applicable law or agreed to in writing, software\r\n// distributed under the License is distributed on an \"AS-IS\" BASIS,\r\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n// See the License for the specific language governing permissions and\r\n// limitations under the License.\r\n\r\n/**\r\n * @fileoverview Base WebChannel implementation.\r\n *\r\n */\r\n\r\n\r\ngoog.provide('goog.labs.net.webChannel.WebChannelBase');\r\n\r\ngoog.require('goog.Uri');\r\ngoog.require('goog.array');\r\ngoog.require('goog.asserts');\r\ngoog.require('goog.async.run');\r\ngoog.require('goog.debug.TextFormatter');\r\ngoog.require('goog.json');\r\ngoog.require('goog.labs.net.webChannel.BaseTestChannel');\r\ngoog.require('goog.labs.net.webChannel.Channel');\r\ngoog.require('goog.labs.net.webChannel.ChannelRequest');\r\ngoog.require('goog.labs.net.webChannel.ConnectionState');\r\ngoog.require('goog.labs.net.webChannel.ForwardChannelRequestPool');\r\ngoog.require('goog.labs.net.webChannel.WebChannelDebug');\r\ngoog.require('goog.labs.net.webChannel.Wire');\r\ngoog.require('goog.labs.net.webChannel.WireV8');\r\ngoog.require('goog.labs.net.webChannel.netUtils');\r\ngoog.require('goog.labs.net.webChannel.requestStats');\r\ngoog.require('goog.log');\r\ngoog.require('goog.net.WebChannel');\r\ngoog.require('goog.net.XhrIo');\r\ngoog.require('goog.net.XmlHttpFactory');\r\ngoog.require('goog.net.rpc.HttpCors');\r\ngoog.require('goog.object');\r\ngoog.require('goog.string');\r\ngoog.require('goog.structs');\r\ngoog.require('goog.structs.CircularBuffer');\r\n\r\ngoog.scope(function() {\r\nvar WebChannel = goog.net.WebChannel;\r\nvar BaseTestChannel = goog.labs.net.webChannel.BaseTestChannel;\r\nvar ChannelRequest = goog.labs.net.webChannel.ChannelRequest;\r\nvar ConnectionState = goog.labs.net.webChannel.ConnectionState;\r\nvar ForwardChannelRequestPool =\r\n goog.labs.net.webChannel.ForwardChannelRequestPool;\r\nvar WebChannelDebug = goog.labs.net.webChannel.WebChannelDebug;\r\nvar Wire = goog.labs.net.webChannel.Wire;\r\nvar WireV8 = goog.labs.net.webChannel.WireV8;\r\nvar netUtils = goog.labs.net.webChannel.netUtils;\r\nvar requestStats = goog.labs.net.webChannel.requestStats;\r\n\r\nvar httpCors = goog.module.get('goog.net.rpc.HttpCors');\r\n\r\n\r\n/**\r\n * This WebChannel implementation is branched off goog.net.BrowserChannel\r\n * for now. Ongoing changes to goog.net.BrowserChannel will be back\r\n * ported to this implementation as needed.\r\n *\r\n * @param {!goog.net.WebChannel.Options=} opt_options Configuration for the\r\n * WebChannel instance.\r\n * @param {number=} opt_clientVersion An application-specific version number\r\n * that is sent to the server when connected.\r\n * @param {!ConnectionState=} opt_conn Previously determined connection\r\n * conditions.\r\n * @constructor\r\n * @struct\r\n * @implements {goog.labs.net.webChannel.Channel}\r\n */\r\ngoog.labs.net.webChannel.WebChannelBase = function(\r\n opt_options, opt_clientVersion, opt_conn) {\r\n /**\r\n * The client library version (capabilities).\r\n * @private {number}\r\n */\r\n this.clientVersion_ = opt_clientVersion || 0;\r\n\r\n /**\r\n * The server library version (capabilities).\r\n * @private {number}\r\n */\r\n this.serverVersion_ = 0;\r\n\r\n\r\n /**\r\n * An array of queued maps that need to be sent to the server.\r\n * @private {!Array<Wire.QueuedMap>}\r\n */\r\n this.outgoingMaps_ = [];\r\n\r\n /**\r\n * The channel debug used for logging\r\n * @private {!WebChannelDebug}\r\n */\r\n this.channelDebug_ = new WebChannelDebug();\r\n\r\n /**\r\n * Previous connectivity test results.\r\n * @private {!ConnectionState}\r\n */\r\n this.connState_ = opt_conn || new ConnectionState();\r\n\r\n /**\r\n * Extra HTTP headers to add to all the requests sent to the server.\r\n * @private {Object}\r\n */\r\n this.extraHeaders_ = null;\r\n\r\n /**\r\n * Extra HTTP headers to add to the init request(s) sent to the server.\r\n * @private {Object}\r\n */\r\n this.initHeaders_ = null;\r\n\r\n /**\r\n * @private {?string} The URL param name to overwrite custom HTTP headers\r\n * to bypass CORS preflight.\r\n */\r\n this.httpHeadersOverwriteParam_ = null;\r\n\r\n /**\r\n * Extra parameters to add to all the requests sent to the server.\r\n * @private {Object}\r\n */\r\n this.extraParams_ = null;\r\n\r\n /**\r\n * Parameter name for the http session id.\r\n * @private {?string}\r\n */\r\n this.httpSessionIdParam_ = null;\r\n\r\n /**\r\n * The http session id, to be sent with httpSessionIdParam_ with each\r\n * request after the initial handshake.\r\n * @private {?string}\r\n */\r\n this.httpSessionId_ = null;\r\n\r\n /**\r\n * The ChannelRequest object for the backchannel.\r\n * @private {ChannelRequest}\r\n */\r\n this.backChannelRequest_ = null;\r\n\r\n /**\r\n * The relative path (in the context of the the page hosting the browser\r\n * channel) for making requests to the server.\r\n * @private {?string}\r\n */\r\n this.path_ = null;\r\n\r\n /**\r\n * The absolute URI for the forwardchannel request.\r\n * @private {goog.Uri}\r\n */\r\n this.forwardChannelUri_ = null;\r\n\r\n /**\r\n * The absolute URI for the backchannel request.\r\n * @private {goog.Uri}\r\n */\r\n this.backChannelUri_ = null;\r\n\r\n /**\r\n * A subdomain prefix for using a subdomain in IE for the backchannel\r\n * requests.\r\n * @private {?string}\r\n */\r\n this.hostPrefix_ = null;\r\n\r\n /**\r\n * Whether we allow the use of a subdomain in IE for the backchannel requests.\r\n * @private {boolean}\r\n */\r\n this.allowHostPrefix_ = true;\r\n\r\n /**\r\n * The next id to use for the RID (request identifier) parameter. This\r\n * identifier uniquely identifies the forward channel request.\r\n * @private {number}\r\n */\r\n this.nextRid_ = 0;\r\n\r\n /**\r\n * The id to use for the next outgoing map. This identifier uniquely\r\n * identifies a sent map.\r\n * @private {number}\r\n */\r\n this.nextMapId_ = 0;\r\n\r\n /**\r\n * Whether to fail forward-channel requests after one try or a few tries.\r\n * @private {boolean}\r\n */\r\n this.failFast_ =\r\n !!goog.getObjectByName('internalChannelParams.failFast', opt_options);\r\n\r\n /**\r\n * The handler that receive callbacks for state changes and data.\r\n * @private {goog.labs.net.webChannel.WebChannelBase.Handler}\r\n */\r\n this.handler_ = null;\r\n\r\n /**\r\n * Timer identifier for asynchronously making a forward channel request.\r\n * This is set to true if the func is scheduled with async.run, which\r\n * is equivalent to setTimeout(0).\r\n * @private {?number|?boolean}\r\n */\r\n this.forwardChannelTimerId_ = null;\r\n\r\n /**\r\n * Timer identifier for asynchronously making a back channel request.\r\n * @private {?number}\r\n */\r\n this.backChannelTimerId_ = null;\r\n\r\n /**\r\n * Timer identifier for the timer that waits for us to retry the backchannel\r\n * in the case where it is dead and no longer receiving data.\r\n * @private {?number}\r\n */\r\n this.deadBackChannelTimerId_ = null;\r\n\r\n /**\r\n * The TestChannel object which encapsulates the logic for determining\r\n * interesting network conditions about the client.\r\n * @private {BaseTestChannel}\r\n */\r\n this.connectionTest_ = null;\r\n\r\n /**\r\n * Whether the client's network conditions can support chunked responses.\r\n * @private {?boolean}\r\n */\r\n this.useChunked_ = null;\r\n\r\n /**\r\n * Whether chunked mode is allowed. In certain debugging situations, it's\r\n * useful to disable this.\r\n * @private {boolean}\r\n */\r\n this.allowChunkedMode_ = true;\r\n\r\n /**\r\n * The array identifier of the last array received from the server for the\r\n * backchannel request.\r\n * @private {number}\r\n */\r\n this.lastArrayId_ = -1;\r\n\r\n /**\r\n * The array id of the last array sent by the server that we know about.\r\n * @private {number}\r\n */\r\n this.lastPostResponseArrayId_ = -1;\r\n\r\n /**\r\n * The last status code received.\r\n * @private {number}\r\n */\r\n this.lastStatusCode_ = -1;\r\n\r\n /**\r\n * Number of times we have retried the current forward channel request.\r\n * @private {number}\r\n */\r\n this.forwardChannelRetryCount_ = 0;\r\n\r\n /**\r\n * Number of times in a row that we have retried the current back channel\r\n * request and received no data.\r\n * @private {number}\r\n */\r\n this.backChannelRetryCount_ = 0;\r\n\r\n /**\r\n * The attempt id for the current back channel request. Starts at 1 and\r\n * increments for each reconnect. The server uses this to log if our\r\n * connection is flaky or not.\r\n * @private {number}\r\n */\r\n this.backChannelAttemptId_ = 0;\r\n\r\n /**\r\n * The base part of the time before firing next retry request. Default is 5\r\n * seconds. Note that a random delay is added (see {@link retryDelaySeedMs_})\r\n * for all retries, and linear backoff is applied to the sum for subsequent\r\n * retries.\r\n * @private {number}\r\n */\r\n this.baseRetryDelayMs_ =\r\n goog.getObjectByName(\r\n 'internalChannelParams.baseRetryDelayMs', opt_options) ||\r\n 5 * 1000;\r\n\r\n /**\r\n * A random time between 0 and this number of MS is added to the\r\n * {@link baseRetryDelayMs_}. Default is 10 seconds.\r\n * @private {number}\r\n */\r\n this.retryDelaySeedMs_ =\r\n goog.getObjectByName(\r\n 'internalChannelParams.retryDelaySeedMs', opt_options) ||\r\n 10 * 1000;\r\n\r\n /**\r\n * Maximum number of attempts to connect to the server for forward channel\r\n * requests. Defaults to 2.\r\n * @private {number}\r\n */\r\n this.forwardChannelMaxRetries_ =\r\n goog.getObjectByName(\r\n 'internalChannelParams.forwardChannelMaxRetries', opt_options) ||\r\n 2;\r\n\r\n /**\r\n * The timeout in milliseconds for a forward channel request. Defaults to 20\r\n * seconds. Note that part of this timeout can be randomized.\r\n * @private {number}\r\n */\r\n this.forwardChannelRequestTimeoutMs_ =\r\n goog.getObjectByName(\r\n 'internalChannelParams.forwardChannelRequestTimeoutMs',\r\n opt_options) ||\r\n 20 * 1000;\r\n\r\n /**\r\n * The custom factory used to create XMLHttpRequest objects.\r\n * @private {!goog.net.XmlHttpFactory | undefined}\r\n */\r\n this.xmlHttpFactory_ =\r\n (opt_options && opt_options.xmlHttpFactory) || undefined;\r\n\r\n /**\r\n * The timeout in milliseconds for a back channel request. Defaults to using\r\n * the timeout configured in ChannelRequest (45s). If server-side\r\n * keepaliveInterval is known to the client, set the backchannel request\r\n * timeout to 1.5 * keepaliveInterval (ms).\r\n *\r\n * @private {number|undefined}\r\n */\r\n this.backChannelRequestTimeoutMs_ = undefined;\r\n\r\n /**\r\n * A throttle time in ms for readystatechange events for the backchannel.\r\n * Useful for throttling when ready state is INTERACTIVE (partial data).\r\n *\r\n * This throttle is useful if the server sends large data chunks down the\r\n * backchannel. It prevents examining XHR partial data on every readystate\r\n * change event. This is useful because large chunks can trigger hundreds\r\n * of readystatechange events, each of which takes ~5ms or so to handle,\r\n * in turn making the UI unresponsive for a significant period.\r\n *\r\n * If set to zero no throttle is used.\r\n * @private {number}\r\n */\r\n this.readyStateChangeThrottleMs_ = 0;\r\n\r\n /**\r\n * Whether cross origin requests are supported for the channel.\r\n *\r\n * See {@link goog.net.XhrIo#setWithCredentials}.\r\n * @private {boolean}\r\n */\r\n this.supportsCrossDomainXhrs_ =\r\n (opt_options && opt_options.supportsCrossDomainXhr) || false;\r\n\r\n /**\r\n * The current session id.\r\n * @private {string}\r\n */\r\n this.sid_ = '';\r\n\r\n /**\r\n * The current ChannelRequest pool for the forward channel.\r\n * @private {!ForwardChannelRequestPool}\r\n */\r\n this.forwardChannelRequestPool_ = new ForwardChannelRequestPool(\r\n opt_options && opt_options.concurrentRequestLimit);\r\n\r\n /**\r\n * The V8 codec.\r\n * @private {!WireV8}\r\n */\r\n this.wireCodec_ = new WireV8();\r\n\r\n /**\r\n * Whether to run the channel test as a background process to not block\r\n * the OPEN event.\r\n *\r\n * @private {boolean}\r\n */\r\n this.backgroundChannelTest_ =\r\n opt_options && goog.isDef(opt_options.backgroundChannelTest) ?\r\n opt_options.backgroundChannelTest :\r\n true;\r\n\r\n /**\r\n * Whether to turn on the fast handshake behavior.\r\n *\r\n * @private {boolean}\r\n */\r\n this.fastHandshake_ = (opt_options && opt_options.fastHandshake) || false;\r\n\r\n if (this.fastHandshake_ && !this.backgroundChannelTest_) {\r\n this.channelDebug_.warning(\r\n 'Force backgroundChannelTest when fastHandshake is enabled.');\r\n this.backgroundChannelTest_ = true;\r\n }\r\n\r\n if (opt_options && opt_options.disableRedact) {\r\n this.channelDebug_.disableRedact();\r\n }\r\n\r\n if (opt_options && opt_options.forceLongPolling) {\r\n this.allowChunkedMode_ = false;\r\n }\r\n\r\n /**\r\n * Callback when all the pending client-sent messages have been flushed.\r\n *\r\n * @private {function()|undefined}\r\n */\r\n this.forwardChannelFlushedCallback_ = undefined;\r\n};\r\n\r\nvar WebChannelBase = goog.labs.net.webChannel.WebChannelBase;\r\n\r\n\r\n/**\r\n * The channel version that we negotiated with the server for this session.\r\n * Starts out as the version we request, and then is changed to the negotiated\r\n * version after the initial open.\r\n * @private {number}\r\n */\r\nWebChannelBase.prototype.channelVersion_ = Wire.LATEST_CHANNEL_VERSION;\r\n\r\n\r\n/**\r\n * Enum type for the channel state machine.\r\n * @enum {number}\r\n */\r\nWebChannelBase.State = {\r\n /** The channel is closed. */\r\n CLOSED: 0,\r\n\r\n /** The channel has been initialized but hasn't yet initiated a connection. */\r\n INIT: 1,\r\n\r\n /** The channel is in the process of opening a connection to the server. */\r\n OPENING: 2,\r\n\r\n /** The channel is open. */\r\n OPENED: 3\r\n};\r\n\r\n\r\n/**\r\n * The current state of the WebChannel.\r\n * @private {!WebChannelBase.State}\r\n */\r\nWebChannelBase.prototype.state_ = WebChannelBase.State.INIT;\r\n\r\n\r\n/**\r\n * The timeout in milliseconds for a forward channel request.\r\n * @type {number}\r\n */\r\nWebChannelBase.FORWARD_CHANNEL_RETRY_TIMEOUT = 20 * 1000;\r\n\r\n\r\n/**\r\n * Maximum number of attempts to connect to the server for back channel\r\n * requests.\r\n * @type {number}\r\n */\r\nWebChannelBase.BACK_CHANNEL_MAX_RETRIES = 3;\r\n\r\n\r\n/**\r\n * A number in MS of how long we guess the maxmium amount of time a round trip\r\n * to the server should take. In the future this could be substituted with a\r\n * real measurement of the RTT.\r\n * @type {number}\r\n */\r\nWebChannelBase.RTT_ESTIMATE = 3 * 1000;\r\n\r\n\r\n/**\r\n * When retrying for an inactive channel, we will multiply the total delay by\r\n * this number.\r\n * @type {number}\r\n */\r\nWebChannelBase.INACTIVE_CHANNEL_RETRY_FACTOR = 2;\r\n\r\n\r\n/**\r\n * Enum type for identifying an error.\r\n * @enum {number}\r\n */\r\nWebChannelBase.Error = {\r\n /** Value that indicates no error has occurred. */\r\n OK: 0,\r\n\r\n /** An error due to a request failing. */\r\n REQUEST_FAILED: 2,\r\n\r\n /** An error due to the user being logged out. */\r\n LOGGED_OUT: 4,\r\n\r\n /** An error due to server response which contains no data. */\r\n NO_DATA: 5,\r\n\r\n /** An error due to a server response indicating an unknown session id */\r\n UNKNOWN_SESSION_ID: 6,\r\n\r\n /** An error due to a server response requesting to stop the channel. */\r\n STOP: 7,\r\n\r\n /** A general network error. */\r\n NETWORK: 8,\r\n\r\n /** An error due to bad data being returned from the server. */\r\n BAD_DATA: 10,\r\n\r\n /** An error due to a response that is not parsable. */\r\n BAD_RESPONSE: 11\r\n};\r\n\r\n\r\n/**\r\n * Internal enum type for the two channel types.\r\n * @enum {number}\r\n * @private\r\n */\r\nWebChannelBase.ChannelType_ = {\r\n FORWARD_CHANNEL: 1,\r\n\r\n BACK_CHANNEL: 2\r\n};\r\n\r\n\r\n/**\r\n * The maximum number of maps that can be sent in one POST. Should match\r\n * MAX_MAPS_PER_REQUEST on the server code.\r\n * @type {number}\r\n * @private\r\n */\r\nWebChannelBase.MAX_MAPS_PER_REQUEST_ = 1000;\r\n\r\n\r\n/**\r\n * The maximum number of utf-8 chars that can be sent in one GET to enable 0-RTT\r\n * handshake.\r\n *\r\n * @const @private {number}\r\n */\r\nWebChannelBase.MAX_CHARS_PER_GET_ = 4 * 1024;\r\n\r\n\r\n/**\r\n * A guess at a cutoff at which to no longer assume the backchannel is dead\r\n * when we are slow to receive data. Number in bytes.\r\n *\r\n * Assumption: The worst bandwidth we work on is 50 kilobits/sec\r\n * 50kbits/sec * (1 byte / 8 bits) * 6 sec dead backchannel timeout\r\n * @type {number}\r\n */\r\nWebChannelBase.OUTSTANDING_DATA_BACKCHANNEL_RETRY_CUTOFF = 37500;\r\n\r\n\r\n/**\r\n * @return {number} The server version or 0 if undefined\r\n */\r\nWebChannelBase.prototype.getServerVersion = function() {\r\n return this.serverVersion_;\r\n};\r\n\r\n\r\n/**\r\n * @return {!ForwardChannelRequestPool} The forward channel request pool.\r\n */\r\nWebChannelBase.prototype.getForwardChannelRequestPool = function() {\r\n return this.forwardChannelRequestPool_;\r\n};\r\n\r\n\r\n/**\r\n * @return {!Object} The codec object, to be used for the test channel.\r\n */\r\nWebChannelBase.prototype.getWireCodec = function() {\r\n return this.wireCodec_;\r\n};\r\n\r\n\r\n/**\r\n * Returns the logger.\r\n *\r\n * @return {!WebChannelDebug} The channel debug object.\r\n */\r\nWebChannelBase.prototype.getChannelDebug = function() {\r\n return this.channelDebug_;\r\n};\r\n\r\n\r\n/**\r\n * Sets the logger.\r\n *\r\n * @param {!WebChannelDebug} channelDebug The channel debug object.\r\n */\r\nWebChannelBase.prototype.setChannelDebug = function(channelDebug) {\r\n this.channelDebug_ = channelDebug;\r\n};\r\n\r\n\r\n/**\r\n * Starts the channel. This initiates connections to the server.\r\n *\r\n * @param {string} testPath The path for the test connection.\r\n * @param {string} channelPath The path for the channel connection.\r\n * @param {!Object=} opt_extraParams Extra parameter keys and values to add to\r\n * the requests.\r\n * @param {string=} opt_oldSessionId Session ID from a previous session.\r\n * @param {number=} opt_oldArrayId The last array ID from a previous session.\r\n */\r\nWebChannelBase.prototype.connect = function(\r\n testPath, channelPath, opt_extraParams, opt_oldSessionId, opt_oldArrayId) {\r\n this.channelDebug_.debug('connect()');\r\n\r\n requestStats.notifyStatEvent(requestStats.Stat.CONNECT_ATTEMPT);\r\n\r\n this.path_ = channelPath;\r\n this.extraParams_ = opt_extraParams || {};\r\n\r\n // Attach parameters about the previous session if reconnecting.\r\n if (opt_oldSessionId && goog.isDef(opt_oldArrayId)) {\r\n this.extraParams_['OSID'] = opt_oldSessionId;\r\n this.extraParams_['OAID'] = opt_oldArrayId;\r\n }\r\n\r\n if (this.backgroundChannelTest_) {\r\n this.channelDebug_.debug('connect() bypassed channel-test.');\r\n this.connState_.handshakeResult = [];\r\n this.connState_.bufferingProxyResult = false;\r\n\r\n // TODO(user): merge states with background channel test\r\n // requestStats.setTimeout(goog.bind(this.connectTest_, this, testPath), 0);\r\n // this.connectChannel_();\r\n }\r\n\r\n this.connectTest_(testPath);\r\n};\r\n\r\n\r\n/**\r\n * Disconnects and closes the channel.\r\n */\r\nWebChannelBase.prototype.disconnect = function() {\r\n this.channelDebug_.debug('disconnect()');\r\n\r\n this.cancelRequests_();\r\n\r\n if (this.state_ == WebChannelBase.State.OPENED) {\r\n var rid = this.nextRid_++;\r\n var uri = this.forwardChannelUri_.clone();\r\n uri.setParameterValue('SID', this.sid_);\r\n uri.setParameterValue('RID', rid);\r\n uri.setParameterValue('TYPE', 'terminate');\r\n\r\n // Add the reconnect parameters.\r\n this.addAdditionalParams_(uri);\r\n\r\n var request = ChannelRequest.createChannelRequest(\r\n this, this.channelDebug_, this.sid_, rid);\r\n request.sendCloseRequest(uri);\r\n }\r\n\r\n this.onClose_();\r\n};\r\n\r\n\r\n/**\r\n * Returns the session id of the channel. Only available after the\r\n * channel has been opened.\r\n * @return {string} Session ID.\r\n */\r\nWebChannelBase.prototype.getSessionId = function() {\r\n return this.sid_;\r\n};\r\n\r\n\r\n/**\r\n * Starts the test channel to determine network conditions.\r\n *\r\n * @param {string} testPath The relative PATH for the test connection.\r\n * @private\r\n */\r\nWebChannelBase.prototype.connectTest_ = function(testPath) {\r\n this.channelDebug_.debug('connectTest_()');\r\n if (!this.okToMakeRequest_()) {\r\n return; // channel is cancelled\r\n }\r\n this.connectionTest_ = new BaseTestChannel(this, this.channelDebug_);\r\n\r\n if (this.httpHeadersOverwriteParam_ === null) {\r\n this.connectionTest_.setExtraHeaders(this.extraHeaders_);\r\n }\r\n\r\n var urlPath = testPath;\r\n if (this.httpHeadersOverwriteParam_ && this.extraHeaders_) {\r\n urlPath = httpCors.setHttpHeadersWithOverwriteParam(\r\n testPath, this.httpHeadersOverwriteParam_, this.extraHeaders_);\r\n }\r\n\r\n this.connectionTest_.connect(/** @type {string} */ (urlPath));\r\n};\r\n\r\n\r\n/**\r\n * Starts the regular channel which is run after the test channel is complete.\r\n * @private\r\n */\r\nWebChannelBase.prototype.connectChannel_ = function() {\r\n this.channelDebug_.debug('connectChannel_()');\r\n this.ensureInState_(WebChannelBase.State.INIT, WebChannelBase.State.CLOSED);\r\n this.forwardChannelUri_ =\r\n this.getForwardChannelUri(/** @type {string} */ (this.path_));\r\n this.ensureForwardChannel_();\r\n};\r\n\r\n\r\n/**\r\n * Cancels all outstanding requests.\r\n * @private\r\n */\r\nWebChannelBase.prototype.cancelRequests_ = function() {\r\n if (this.connectionTest_) {\r\n this.connectionTest_.abort();\r\n this.connectionTest_ = null;\r\n }\r\n\r\n if (this.backChannelRequest_) {\r\n this.backChannelRequest_.cancel();\r\n this.backChannelRequest_ = null;\r\n }\r\n\r\n if (this.backChannelTimerId_) {\r\n goog.global.clearTimeout(this.backChannelTimerId_);\r\n this.backChannelTimerId_ = null;\r\n }\r\n\r\n this.clearDeadBackchannelTimer_();\r\n\r\n this.forwardChannelRequestPool_.cancel();\r\n\r\n if (this.forwardChannelTimerId_) {\r\n this.clearForwardChannelTimer_();\r\n }\r\n};\r\n\r\n\r\n/**\r\n * Clears the forward channel timer.\r\n * @private\r\n */\r\nWebChannelBase.prototype.clearForwardChannelTimer_ = function() {\r\n if (goog.isNumber(this.forwardChannelTimerId_)) {\r\n goog.global.clearTimeout(this.forwardChannelTimerId_);\r\n }\r\n\r\n this.forwardChannelTimerId_ = null;\r\n};\r\n\r\n\r\n/**\r\n * Returns the extra HTTP headers to add to all the requests sent to the server.\r\n *\r\n * @return {Object} The HTTP headers, or null.\r\n */\r\nWebChannelBase.prototype.getExtraHeaders = function() {\r\n return this.extraHeaders_;\r\n};\r\n\r\n\r\n/**\r\n * Sets extra HTTP headers to add to all the requests sent to the server.\r\n *\r\n * @param {Object} extraHeaders The HTTP headers, or null.\r\n */\r\nWebChannelBase.prototype.setExtraHeaders = function(extraHeaders) {\r\n this.extraHeaders_ = extraHeaders;\r\n};\r\n\r\n\r\n/**\r\n * Returns the extra HTTP headers to add to the init requests\r\n * sent to the server.\r\n *\r\n * @return {Object} The HTTP headers, or null.\r\n */\r\nWebChannelBase.prototype.getInitHeaders = function() {\r\n return this.initHeaders_;\r\n};\r\n\r\n\r\n/**\r\n * Sets extra HTTP headers to add to the init requests sent to the server.\r\n *\r\n * @param {Object} initHeaders The HTTP headers, or null.\r\n */\r\nWebChannelBase.prototype.setInitHeaders = function(initHeaders) {\r\n this.initHeaders_ = initHeaders;\r\n};\r\n\r\n\r\n/**\r\n * Sets the URL param name to overwrite custom HTTP headers.\r\n *\r\n * @param {string} httpHeadersOverwriteParam The URL param name.\r\n */\r\nWebChannelBase.prototype.setHttpHeadersOverwriteParam = function(\r\n httpHeadersOverwriteParam) {\r\n this.httpHeadersOverwriteParam_ = httpHeadersOverwriteParam;\r\n};\r\n\r\n\r\n/**\r\n * @override\r\n */\r\nWebChannelBase.prototype.setHttpSessionIdParam = function(httpSessionIdParam) {\r\n this.httpSessionIdParam_ = httpSessionIdParam;\r\n};\r\n\r\n\r\n/**\r\n * @override\r\n */\r\nWebChannelBase.prototype.getHttpSessionIdParam = function() {\r\n return this.httpSessionIdParam_;\r\n};\r\n\r\n\r\n/**\r\n * @override\r\n */\r\nWebChannelBase.prototype.setHttpSessionId = function(httpSessionId) {\r\n this.httpSessionId_ = httpSessionId;\r\n};\r\n\r\n\r\n/**\r\n * @override\r\n */\r\nWebChannelBase.prototype.getHttpSessionId = function() {\r\n return this.httpSessionId_;\r\n};\r\n\r\n\r\n/**\r\n * @override\r\n */\r\nWebChannelBase.prototype.getBackgroundChannelTest = function() {\r\n return this.backgroundChannelTest_;\r\n};\r\n\r\n\r\n/**\r\n * Sets the throttle for handling onreadystatechange events for the request.\r\n *\r\n * @param {number} throttle The throttle in ms. A value of zero indicates\r\n * no throttle.\r\n */\r\nWebChannelBase.prototype.setReadyStateChangeThrottle = function(throttle) {\r\n this.readyStateChangeThrottleMs_ = throttle;\r\n};\r\n\r\n\r\n/**\r\n * Sets whether cross origin requests are supported for the channel.\r\n *\r\n * Setting this allows the creation of requests to secondary domains and\r\n * sends XHRs with the CORS withCredentials bit set to true.\r\n *\r\n * In order for cross-origin requests to work, the server will also need to set\r\n * CORS response headers as per:\r\n * https://developer.mozilla.org/en-US/docs/HTTP_access_control\r\n *\r\n * See {@link goog.net.XhrIo#setWithCredentials}.\r\n * @param {boolean} supportCrossDomain Whether cross domain XHRs are supported.\r\n */\r\nWebChannelBase.prototype.setSupportsCrossDomainXhrs = function(\r\n supportCrossDomain) {\r\n this.supportsCrossDomainXhrs_ = supportCrossDomain;\r\n};\r\n\r\n\r\n/**\r\n * Returns the handler used for channel callback events.\r\n *\r\n * @return {WebChannelBase.Handler} The handler.\r\n */\r\nWebChannelBase.prototype.getHandler = function() {\r\n return this.handler_;\r\n};\r\n\r\n\r\n/**\r\n * Sets the handler used for channel callback events.\r\n * @param {WebChannelBase.Handler} handler The handler to set.\r\n */\r\nWebChannelBase.prototype.setHandler = function(handler) {\r\n this.handler_ = handler;\r\n};\r\n\r\n\r\n/**\r\n * Returns whether the channel allows the use of a subdomain. There may be\r\n * cases where this isn't allowed.\r\n * @return {boolean} Whether a host prefix is allowed.\r\n */\r\nWebChannelBase.prototype.getAllowHostPrefix = function() {\r\n return this.allowHostPrefix_;\r\n};\r\n\r\n\r\n/**\r\n * Sets whether the channel allows the use of a subdomain. There may be cases\r\n * where this isn't allowed, for example, logging in with troutboard where\r\n * using a subdomain causes Apache to force the user to authenticate twice.\r\n * @param {boolean} allowHostPrefix Whether a host prefix is allowed.\r\n */\r\nWebChannelBase.prototype.setAllowHostPrefix = function(allowHostPrefix) {\r\n this.allowHostPrefix_ = allowHostPrefix;\r\n};\r\n\r\n\r\n/**\r\n * Returns whether the channel is buffered or not. This state is valid for\r\n * querying only after the test connection has completed. This may be\r\n * queried in the WebChannelBase.okToMakeRequest() callback.\r\n * A channel may be buffered if the test connection determines that\r\n * a chunked response could not be sent down within a suitable time.\r\n * @return {boolean} Whether the channel is buffered.\r\n */\r\nWebChannelBase.prototype.isBuffered = function() {\r\n return !this.useChunked_;\r\n};\r\n\r\n\r\n/**\r\n * Returns whether chunked mode is allowed. In certain debugging situations,\r\n * it's useful for the application to have a way to disable chunked mode for a\r\n * user.\r\n\r\n * @return {boolean} Whether chunked mode is allowed.\r\n */\r\nWebChannelBase.prototype.getAllowChunkedMode = function() {\r\n return this.allowChunkedMode_;\r\n};\r\n\r\n\r\n/**\r\n * Sets whether chunked mode is allowed. In certain debugging situations, it's\r\n * useful for the application to have a way to disable chunked mode for a user.\r\n * @param {boolean} allowChunkedMode Whether chunked mode is allowed.\r\n */\r\nWebChannelBase.prototype.setAllowChunkedMode = function(allowChunkedMode) {\r\n this.allowChunkedMode_ = allowChunkedMode;\r\n};\r\n\r\n\r\n/**\r\n * Sends a request to the server. The format of the request is a Map data\r\n * structure of key/value pairs. These maps are then encoded in a format\r\n * suitable for the wire and then reconstituted as a Map data structure that\r\n * the server can process.\r\n * @param {!Object|!goog.structs.Map} map The map to send.\r\n * @param {!Object=} opt_context The context associated with the map.\r\n */\r\nWebChannelBase.prototype.sendMap = function(map, opt_context) {\r\n goog.asserts.assert(\r\n this.state_ != WebChannelBase.State.CLOSED,\r\n 'Invalid operation: sending map when state is closed');\r\n\r\n // We can only send 1000 maps per POST, but typically we should never have\r\n // that much to send, so warn if we exceed that (we still send all the maps).\r\n if (this.outgoingMaps_.length == WebChannelBase.MAX_MAPS_PER_REQUEST_) {\r\n // severe() is temporary so that we get these uploaded and can figure out\r\n // what's causing them. Afterwards can change to warning().\r\n this.channelDebug_.severe(function() {\r\n return 'Already have ' + WebChannelBase.MAX_MAPS_PER_REQUEST_ +\r\n ' queued maps upon queueing ' + goog.json.serialize(map);\r\n });\r\n }\r\n\r\n this.outgoingMaps_.push(\r\n new Wire.QueuedMap(this.nextMapId_++, map, opt_context));\r\n\r\n // Messages need be buffered during OPENING to avoid server-side race\r\n if (this.state_ == WebChannelBase.State.OPENED) {\r\n this.ensureForwardChannel_();\r\n }\r\n};\r\n\r\n\r\n/**\r\n * When set to true, this changes the behavior of the forward channel so it\r\n * will not retry requests; it will fail after one network failure, and if\r\n * there was already one network failure, the request will fail immediately.\r\n * @param {boolean} failFast Whether or not to fail fast.\r\n */\r\nWebChannelBase.prototype.setFailFast = function(failFast) {\r\n this.failFast_ = failFast;\r\n this.channelDebug_.info('setFailFast: ' + failFast);\r\n if ((this.forwardChannelRequestPool_.hasPendingRequest() ||\r\n this.forwardChannelTimerId_) &&\r\n this.forwardChannelRetryCount_ > this.getForwardChannelMaxRetries()) {\r\n var self = this;\r\n this.channelDebug_.info(function() {\r\n return 'Retry count ' + self.forwardChannelRetryCount_ +\r\n ' > new maxRetries ' + self.getForwardChannelMaxRetries() +\r\n '. Fail immediately!';\r\n });\r\n\r\n if (!this.forwardChannelRequestPool_.forceComplete(\r\n goog.bind(this.onRequestComplete, this))) {\r\n // i.e., this.forwardChannelTimerId_\r\n this.clearForwardChannelTimer_();\r\n // The error code from the last failed request is gone, so just use a\r\n // generic one.\r\n this.signalError_(WebChannelBase.Error.REQUEST_FAILED);\r\n }\r\n }\r\n};\r\n\r\n\r\n/**\r\n * @return {number} The max number of forward-channel retries, which will be 0\r\n * in fail-fast mode.\r\n */\r\nWebChannelBase.prototype.getForwardChannelMaxRetries = function() {\r\n return this.failFast_ ? 0 : this.forwardChannelMaxRetries_;\r\n};\r\n\r\n\r\n/**\r\n * Sets the maximum number of attempts to connect to the server for forward\r\n * channel requests.\r\n * @param {number} retries The maximum number of attempts.\r\n */\r\nWebChannelBase.prototype.setForwardChannelMaxRetries = function(retries) {\r\n this.forwardChannelMaxRetries_ = retries;\r\n};\r\n\r\n\r\n/**\r\n * Sets the timeout for a forward channel request.\r\n * @param {number} timeoutMs The timeout in milliseconds.\r\n */\r\nWebChannelBase.prototype.setForwardChannelRequestTimeout = function(timeoutMs) {\r\n this.forwardChannelRequestTimeoutMs_ = timeoutMs;\r\n};\r\n\r\n\r\n/**\r\n * @return {number} The max number of back-channel retries, which is a constant.\r\n */\r\nWebChannelBase.prototype.getBackChannelMaxRetries = function() {\r\n // Back-channel retries is a constant.\r\n return WebChannelBase.BACK_CHANNEL_MAX_RETRIES;\r\n};\r\n\r\n\r\n/**\r\n * @override\r\n */\r\nWebChannelBase.prototype.isClosed = function() {\r\n return this.state_ == WebChannelBase.State.CLOSED;\r\n};\r\n\r\n\r\n/**\r\n * Returns the channel state.\r\n * @return {WebChannelBase.State} The current state of the channel.\r\n */\r\nWebChannelBase.prototype.getState = function() {\r\n return this.state_;\r\n};\r\n\r\n\r\n/**\r\n * Return the last status code received for a request.\r\n * @return {number} The last status code received for a request.\r\n */\r\nWebChannelBase.prototype.getLastStatusCode = function() {\r\n return this.lastStatusCode_;\r\n};\r\n\r\n\r\n/**\r\n * @return {number} The last array id received.\r\n */\r\nWebChannelBase.prototype.getLastArrayId = function() {\r\n return this.lastArrayId_;\r\n};\r\n\r\n\r\n/**\r\n * Returns whether there are outstanding requests servicing the channel.\r\n * @return {boolean} true if there are outstanding requests.\r\n */\r\nWebChannelBase.prototype.hasOutstandingRequests = function() {\r\n return this.getOutstandingRequests_() != 0;\r\n};\r\n\r\n\r\n/**\r\n * Returns the number of outstanding requests.\r\n * @return {number} The number of outstanding requests to the server.\r\n * @private\r\n */\r\nWebChannelBase.prototype.getOutstandingRequests_ = function() {\r\n var count = 0;\r\n if (this.backChannelRequest_) {\r\n count++;\r\n }\r\n count += this.forwardChannelRequestPool_.getRequestCount();\r\n return count;\r\n};\r\n\r\n\r\n/**\r\n * Ensures that a forward channel request is scheduled.\r\n * @private\r\n */\r\nWebChannelBase.prototype.ensureForwardChannel_ = function() {\r\n if (this.forwardChannelRequestPool_.isFull()) {\r\n // enough connection in process - no need to start a new request\r\n return;\r\n }\r\n\r\n if (this.forwardChannelTimerId_) {\r\n // no need to start a new request - one is already scheduled\r\n return;\r\n }\r\n\r\n // Use async.run instead of setTimeout(0) to avoid the 1s message delay\r\n // from chrome/firefox background tabs\r\n this.forwardChannelTimerId_ = true;\r\n goog.async.run(this.onStartForwardChannelTimer_, this);\r\n\r\n this.forwardChannelRetryCount_ = 0;\r\n};\r\n\r\n\r\n/**\r\n * Schedules a forward-channel retry for the specified request, unless the max\r\n * retries has been reached.\r\n * @param {!ChannelRequest} request The failed request to retry.\r\n * @return {boolean} true iff a retry was scheduled.\r\n * @private\r\n */\r\nWebChannelBase.prototype.maybeRetryForwardChannel_ = function(request) {\r\n if (this.forwardChannelRequestPool_.getRequestCount() >=\r\n this.forwardChannelRequestPool_.getMaxSize() -\r\n (this.forwardChannelTimerId_ ? 1 : 0)) {\r\n // Should be impossible to be called in this state.\r\n this.channelDebug_.severe('Unexpected retry request is scheduled.');\r\n return false;\r\n }\r\n\r\n if (this.forwardChannelTimerId_) {\r\n this.channelDebug_.debug(\r\n 'Use the retry request that is already scheduled.');\r\n this.outgoingMaps_ =\r\n request.getPendingMessages().concat(this.outgoingMaps_);\r\n return true;\r\n }\r\n\r\n // No retry for open_() and fail-fast\r\n if (this.state_ == WebChannelBase.State.INIT ||\r\n this.state_ == WebChannelBase.State.OPENING ||\r\n (this.forwardChannelRetryCount_ >= this.getForwardChannelMaxRetries())) {\r\n return false;\r\n }\r\n\r\n this.channelDebug_.debug('Going to retry POST');\r\n\r\n this.forwardChannelTimerId_ = requestStats.setTimeout(\r\n goog.bind(this.onStartForwardChannelTimer_, this, request),\r\n this.getRetryTime_(this.forwardChannelRetryCount_));\r\n this.forwardChannelRetryCount_++;\r\n return true;\r\n};\r\n\r\n\r\n/**\r\n * Timer callback for ensureForwardChannel\r\n * @param {ChannelRequest=} opt_retryRequest A failed request\r\n * to retry.\r\n * @private\r\n */\r\nWebChannelBase.prototype.onStartForwardChannelTimer_ = function(\r\n opt_retryRequest) {\r\n // null is possible if scheduled with async.run\r\n if (this.forwardChannelTimerId_) {\r\n this.forwardChannelTimerId_ = null;\r\n this.startForwardChannel_(opt_retryRequest);\r\n }\r\n};\r\n\r\n\r\n/**\r\n * Begins a new forward channel operation to the server.\r\n * @param {ChannelRequest=} opt_retryRequest A failed request to retry.\r\n * @private\r\n */\r\nWebChannelBase.prototype.startForwardChannel_ = function(opt_retryRequest) {\r\n this.channelDebug_.debug('startForwardChannel_');\r\n if (!this.okToMakeRequest_()) {\r\n return; // channel is cancelled\r\n } else if (this.state_ == WebChannelBase.State.INIT) {\r\n if (opt_retryRequest) {\r\n this.channelDebug_.severe('Not supposed to retry the open');\r\n return;\r\n }\r\n this.open_();\r\n this.state_ = WebChannelBase.State.OPENING;\r\n } else if (this.state_ == WebChannelBase.State.OPENED) {\r\n if (opt_retryRequest) {\r\n this.makeForwardChannelRequest_(opt_retryRequest);\r\n return;\r\n }\r\n\r\n if (this.outgoingMaps_.length == 0) {\r\n this.channelDebug_.debug(\r\n 'startForwardChannel_ returned: ' +\r\n 'nothing to send');\r\n // no need to start a new forward channel request\r\n return;\r\n }\r\n\r\n if (this.forwardChannelRequestPool_.isFull()) {\r\n // Should be impossible to be called in this state.\r\n this.channelDebug_.severe(\r\n 'startForwardChannel_ returned: ' +\r\n 'connection already in progress');\r\n return;\r\n }\r\n\r\n this.makeForwardChannelRequest_();\r\n this.channelDebug_.debug('startForwardChannel_ finished, sent request');\r\n }\r\n};\r\n\r\n\r\n/**\r\n * Establishes a new channel session with the the server.\r\n * @private\r\n */\r\nWebChannelBase.prototype.open_ = function() {\r\n this.channelDebug_.debug('open_()');\r\n this.nextRid_ = Math.floor(Math.random() * 100000);\r\n\r\n var rid = this.nextRid_++;\r\n var request =\r\n ChannelRequest.createChannelRequest(this, this.channelDebug_, '', rid);\r\n\r\n // mix the init headers\r\n var extraHeaders = this.extraHeaders_;\r\n if (this.initHeaders_) {\r\n if (extraHeaders) {\r\n extraHeaders = goog.object.clone(extraHeaders);\r\n goog.object.extend(extraHeaders, this.initHeaders_);\r\n } else {\r\n extraHeaders = this.initHeaders_;\r\n }\r\n }\r\n\r\n if (this.httpHeadersOverwriteParam_ === null) {\r\n request.setExtraHeaders(extraHeaders);\r\n }\r\n\r\n var requestText = this.dequeueOutgoingMaps_(\r\n request,\r\n this.fastHandshake_ ? this.getMaxNumMessagesForFastHandshake_() :\r\n WebChannelBase.MAX_MAPS_PER_REQUEST_);\r\n\r\n var uri = this.forwardChannelUri_.clone();\r\n uri.setParameterValue('RID', rid);\r\n\r\n if (this.clientVersion_ > 0) {\r\n uri.setParameterValue('CVER', this.clientVersion_);\r\n }\r\n\r\n // http-session-id to be generated as the response\r\n if (this.getBackgroundChannelTest() && this.getHttpSessionIdParam()) {\r\n uri.setParameterValue(\r\n WebChannel.X_HTTP_SESSION_ID, this.getHttpSessionIdParam());\r\n }\r\n\r\n // Add the reconnect parameters.\r\n this.addAdditionalParams_(uri);\r\n\r\n if (this.httpHeadersOverwriteParam_ && extraHeaders) {\r\n httpCors.setHttpHeadersWithOverwriteParam(\r\n uri, this.httpHeadersOverwriteParam_, extraHeaders);\r\n }\r\n\r\n this.forwardChannelRequestPool_.addRequest(request);\r\n\r\n // Check the option and use GET to enable QUIC 0-RTT\r\n if (this.fastHandshake_) {\r\n uri.setParameterValue('$req', requestText);\r\n\r\n // enable handshake upgrade\r\n uri.setParameterValue('SID', 'null');\r\n request.setDecodeInitialResponse();\r\n\r\n request.xmlHttpPost(uri, null, true); // Send as a GET\r\n } else {\r\n request.xmlHttpPost(uri, requestText, true);\r\n }\r\n};\r\n\r\n\r\n/**\r\n * @return {number} The number of raw JSON messages to be encoded\r\n * with the fast-handshake (GET) request, including zero. If messages are not\r\n * encoded as raw JSON data, return WebChannelBase.MAX_MAPS_PER_REQUEST_\r\n * @private\r\n */\r\nWebChannelBase.prototype.getMaxNumMessagesForFastHandshake_ = function() {\r\n var total = 0;\r\n for (var i = 0; i < this.outgoingMaps_.length; i++) {\r\n var map = this.outgoingMaps_[i];\r\n var size = map.getRawDataSize();\r\n if (size === undefined) {\r\n break;\r\n }\r\n total += size;\r\n\r\n if (total > WebChannelBase.MAX_CHARS_PER_GET_) {\r\n return i;\r\n }\r\n\r\n if (total === WebChannelBase.MAX_CHARS_PER_GET_ ||\r\n i === this.outgoingMaps_.length - 1) {\r\n return i + 1;\r\n }\r\n }\r\n\r\n return WebChannelBase.MAX_MAPS_PER_REQUEST_;\r\n};\r\n\r\n\r\n\r\n/**\r\n * Makes a forward channel request using XMLHTTP.\r\n * @param {!ChannelRequest=} opt_retryRequest A failed request to retry.\r\n * @private\r\n */\r\nWebChannelBase.prototype.makeForwardChannelRequest_ = function(\r\n opt_retryRequest) {\r\n var rid;\r\n if (opt_retryRequest) {\r\n rid = opt_retryRequest.getRequestId(); // Reuse the same RID for a retry\r\n } else {\r\n rid = this.nextRid_++;\r\n }\r\n\r\n var uri = this.forwardChannelUri_.clone();\r\n uri.setParameterValue('SID', this.sid_);\r\n uri.setParameterValue('RID', rid);\r\n uri.setParameterValue('AID', this.lastArrayId_);\r\n // Add the additional reconnect parameters.\r\n this.addAdditionalParams_(uri);\r\n\r\n if (this.httpHeadersOverwriteParam_ && this.extraHeaders_) {\r\n httpCors.setHttpHeadersWithOverwriteParam(\r\n uri, this.httpHeadersOverwriteParam_, this.extraHeaders_);\r\n }\r\n\r\n var request = ChannelRequest.createChannelRequest(\r\n this, this.channelDebug_, this.sid_, rid,\r\n this.forwardChannelRetryCount_ + 1);\r\n\r\n if (this.httpHeadersOverwriteParam_ === null) {\r\n request.setExtraHeaders(this.extraHeaders_);\r\n }\r\n\r\n var requestText;\r\n if (opt_retryRequest) {\r\n this.requeuePendingMaps_(opt_retryRequest);\r\n }\r\n requestText =\r\n this.dequeueOutgoingMaps_(request, WebChannelBase.MAX_MAPS_PER_REQUEST_);\r\n\r\n // Randomize from 50%-100% of the forward channel timeout to avoid\r\n // a big hit if servers happen to die at once.\r\n request.setTimeout(\r\n Math.round(this.forwardChannelRequestTimeoutMs_ * 0.50) +\r\n Math.round(this.forwardChannelRequestTimeoutMs_ * 0.50 * Math.random()));\r\n this.forwardChannelRequestPool_.addRequest(request);\r\n request.xmlHttpPost(uri, requestText, true);\r\n};\r\n\r\n\r\n/**\r\n * Adds the additional parameters from the handler to the given URI.\r\n * @param {!goog.Uri} uri The URI to add the parameters to.\r\n * @private\r\n */\r\nWebChannelBase.prototype.addAdditionalParams_ = function(uri) {\r\n // Add the additional reconnect parameters as needed.\r\n if (this.handler_) {\r\n var params = this.handler_.getAdditionalParams(this);\r\n if (params) {\r\n goog.structs.forEach(params, function(value, key, coll) {\r\n uri.setParameterValue(key, value);\r\n });\r\n }\r\n }\r\n};\r\n\r\n\r\n/**\r\n * Returns the request text from the outgoing maps and resets it.\r\n * @param {!ChannelRequest} request The new request for sending the messages.\r\n * @param {number} maxNum The maximum number of messages to be encoded\r\n * @return {string} The encoded request text created from all the currently\r\n * queued outgoing maps.\r\n * @private\r\n */\r\nWebChannelBase.prototype.dequeueOutgoingMaps_ = function(request, maxNum) {\r\n var count = Math.min(this.outgoingMaps_.length, maxNum);\r\n\r\n var badMapHandler = this.handler_ ?\r\n goog.bind(this.handler_.badMapError, this.handler_, this) :\r\n null;\r\n var result = this.wireCodec_.encodeMessageQueue(\r\n this.outgoingMaps_, count, badMapHandler);\r\n\r\n request.setPendingMessages(this.outgoingMaps_.splice(0, count));\r\n\r\n return result;\r\n};\r\n\r\n\r\n/**\r\n * Requeues unacknowledged sent arrays for retransmission in the next forward\r\n * channel request.\r\n * @param {!ChannelRequest} retryRequest A failed request to retry.\r\n * @private\r\n */\r\nWebChannelBase.prototype.requeuePendingMaps_ = function(retryRequest) {\r\n this.outgoingMaps_ =\r\n retryRequest.getPendingMessages().concat(this.outgoingMaps_);\r\n};\r\n\r\n\r\n/**\r\n * Ensures there is a backchannel request for receiving data from the server.\r\n * @private\r\n */\r\nWebChannelBase.prototype.ensureBackChannel_ = function() {\r\n if (this.backChannelRequest_) {\r\n // already have one\r\n return;\r\n }\r\n\r\n if (this.backChannelTimerId_) {\r\n // no need to start a new request - one is already scheduled\r\n return;\r\n }\r\n\r\n this.backChannelAttemptId_ = 1;\r\n\r\n // Use async.run instead of setTimeout(0) to avoid the 1s message delay\r\n // from chrome/firefox background tabs\r\n // backChannelTimerId_ stays unset, as with setTimeout(0)\r\n goog.async.run(this.onStartBackChannelTimer_, this);\r\n\r\n this.backChannelRetryCount_ = 0;\r\n};\r\n\r\n\r\n/**\r\n * Schedules a back-channel retry, unless the max retries has been reached.\r\n * @return {boolean} true iff a retry was scheduled.\r\n * @private\r\n */\r\nWebChannelBase.prototype.maybeRetryBackChannel_ = function() {\r\n if (this.backChannelRequest_ || this.backChannelTimerId_) {\r\n // Should be impossible to be called in this state.\r\n this.channelDebug_.severe('Request already in progress');\r\n return false;\r\n }\r\n\r\n if (this.backChannelRetryCount_ >= this.getBackChannelMaxRetries()) {\r\n return false;\r\n }\r\n\r\n this.channelDebug_.debug('Going to retry GET');\r\n\r\n this.backChannelAttemptId_++;\r\n this.backChannelTimerId_ = requestStats.setTimeout(\r\n goog.bind(this.onStartBackChannelTimer_, this),\r\n this.getRetryTime_(this.backChannelRetryCount_));\r\n this.backChannelRetryCount_++;\r\n return true;\r\n};\r\n\r\n\r\n/**\r\n * Timer callback for ensureBackChannel_.\r\n * @private\r\n */\r\nWebChannelBase.prototype.onStartBackChannelTimer_ = function() {\r\n this.backChannelTimerId_ = null;\r\n this.startBackChannel_();\r\n};\r\n\r\n\r\n/**\r\n * Begins a new back channel operation to the server.\r\n * @private\r\n */\r\nWebChannelBase.prototype.startBackChannel_ = function() {\r\n if (!this.okToMakeRequest_()) {\r\n // channel is cancelled\r\n return;\r\n }\r\n\r\n this.channelDebug_.debug('Creating new HttpRequest');\r\n this.backChannelRequest_ = ChannelRequest.createChannelRequest(\r\n this, this.channelDebug_, this.sid_, 'rpc', this.backChannelAttemptId_);\r\n\r\n if (this.httpHeadersOverwriteParam_ === null) {\r\n this.backChannelRequest_.setExtraHeaders(this.extraHeaders_);\r\n }\r\n\r\n this.backChannelRequest_.setReadyStateChangeThrottle(\r\n this.readyStateChangeThrottleMs_);\r\n var uri = this.backChannelUri_.clone();\r\n uri.setParameterValue('RID', 'rpc');\r\n uri.setParameterValue('SID', this.sid_);\r\n uri.setParameterValue('CI', this.useChunked_ ? '0' : '1');\r\n uri.setParameterValue('AID', this.lastArrayId_);\r\n\r\n // Add the reconnect parameters.\r\n this.addAdditionalParams_(uri);\r\n\r\n uri.setParameterValue('TYPE', 'xmlhttp');\r\n\r\n if (this.httpHeadersOverwriteParam_ && this.extraHeaders_) {\r\n httpCors.setHttpHeadersWithOverwriteParam(\r\n uri, this.httpHeadersOverwriteParam_, this.extraHeaders_);\r\n }\r\n\r\n if (this.backChannelRequestTimeoutMs_) {\r\n this.backChannelRequest_.setTimeout(this.backChannelRequestTimeoutMs_);\r\n }\r\n\r\n this.backChannelRequest_.xmlHttpGet(\r\n uri, true /* decodeChunks */, this.hostPrefix_);\r\n\r\n this.channelDebug_.debug('New Request created');\r\n};\r\n\r\n\r\n/**\r\n * Gives the handler a chance to return an error code and stop channel\r\n * execution. A handler might want to do this to check that the user is still\r\n * logged in, for example.\r\n * @private\r\n * @return {boolean} If it's OK to make a request.\r\n */\r\nWebChannelBase.prototype.okToMakeRequest_ = function() {\r\n if (this.handler_) {\r\n var result = this.handler_.okToMakeRequest(this);\r\n if (result != WebChannelBase.Error.OK) {\r\n this.channelDebug_.debug(\r\n 'Handler returned error code from okToMakeRequest');\r\n this.signalError_(result);\r\n return false;\r\n }\r\n }\r\n return true;\r\n};\r\n\r\n\r\n/**\r\n * @override\r\n */\r\nWebChannelBase.prototype.testConnectionFinished = function(\r\n testChannel, useChunked) {\r\n this.channelDebug_.debug('Test Connection Finished');\r\n\r\n // Forward channel will not be used prior to this method is called\r\n var clientProtocol = testChannel.getClientProtocol();\r\n if (clientProtocol) {\r\n this.forwardChannelRequestPool_.applyClientProtocol(clientProtocol);\r\n }\r\n\r\n this.useChunked_ = this.allowChunkedMode_ && useChunked;\r\n this.lastStatusCode_ = testChannel.getLastStatusCode();\r\n\r\n this.connectChannel_();\r\n};\r\n\r\n\r\n/**\r\n * @override\r\n */\r\nWebChannelBase.prototype.testConnectionFailure = function(\r\n testChannel, errorCode) {\r\n this.channelDebug_.debug('Test Connection Failed');\r\n this.lastStatusCode_ = testChannel.getLastStatusCode();\r\n this.signalError_(WebChannelBase.Error.REQUEST_FAILED);\r\n};\r\n\r\n\r\n/**\r\n * @override\r\n */\r\nWebChannelBase.prototype.onRequestData = function(request, responseText) {\r\n if (this.state_ == WebChannelBase.State.CLOSED ||\r\n (this.backChannelRequest_ != request &&\r\n !this.forwardChannelRequestPool_.hasRequest(request))) {\r\n // either CLOSED or a request we don't know about (perhaps an old request)\r\n return;\r\n }\r\n this.lastStatusCode_ = request.getLastStatusCode();\r\n\r\n // first to check if request has been upgraded to backchannel\r\n if (!request.isInitialResponseDecoded() &&\r\n this.forwardChannelRequestPool_.hasRequest(request) &&\r\n this.state_ == WebChannelBase.State.OPENED) {\r\n var response;\r\n try {\r\n response = this.wireCodec_.decodeMessage(responseText);\r\n } catch (ex) {\r\n response = null;\r\n }\r\n if (goog.isArray(response) && response.length == 3) {\r\n this.handlePostResponse_(/** @type {!Array<?>} */ (response), request);\r\n this.onForwardChannelFlushed_();\r\n } else {\r\n this.channelDebug_.debug('Bad POST response data returned');\r\n this.signalError_(WebChannelBase.Error.BAD_RESPONSE);\r\n }\r\n } else {\r\n if (request.isInitialResponseDecoded() ||\r\n this.backChannelRequest_ == request) {\r\n this.clearDeadBackchannelTimer_();\r\n }\r\n if (!goog.string.isEmptyOrWhitespace(responseText)) {\r\n var response = this.wireCodec_.decodeMessage(responseText);\r\n this.onInput_(/** @type {!Array<?>} */ (response), request);\r\n }\r\n }\r\n};\r\n\r\n\r\n/**\r\n * Checks if we need call the flush callback.\r\n *\r\n * @private\r\n */\r\nWebChannelBase.prototype.onForwardChannelFlushed_ = function() {\r\n if (this.forwardChannelRequestPool_.getRequestCount() <= 1) {\r\n if (this.forwardChannelFlushedCallback_) {\r\n try {\r\n this.forwardChannelFlushedCallback_();\r\n } catch (ex) {\r\n this.channelDebug_.dumpException(\r\n ex, 'Exception from forwardChannelFlushedCallback_ ');\r\n }\r\n // reset\r\n this.forwardChannelFlushedCallback_ = undefined;\r\n }\r\n }\r\n};\r\n\r\n\r\n/**\r\n * Handles a POST response from the server.\r\n * @param {Array<number>} responseValues The key value pairs in\r\n * the POST response.\r\n * @param {!ChannelRequest} forwardReq The forward channel request that\r\n * triggers this function call.\r\n * @private\r\n */\r\nWebChannelBase.prototype.handlePostResponse_ = function(\r\n responseValues, forwardReq) {\r\n // The first response value is set to 0 if server is missing backchannel.\r\n if (responseValues[0] == 0) {\r\n this.handleBackchannelMissing_(forwardReq);\r\n return;\r\n }\r\n this.lastPostResponseArrayId_ = responseValues[1];\r\n var outstandingArrays = this.lastPostResponseArrayId_ - this.lastArrayId_;\r\n if (0 < outstandingArrays) {\r\n var numOutstandingBackchannelBytes = responseValues[2];\r\n this.channelDebug_.debug(\r\n numOutstandingBackchannelBytes + ' bytes (in ' + outstandingArrays +\r\n ' arrays) are outstanding on the BackChannel');\r\n if (!this.shouldRetryBackChannel_(numOutstandingBackchannelBytes)) {\r\n return;\r\n }\r\n if (!this.deadBackChannelTimerId_) {\r\n // We expect to receive data within 2 RTTs or we retry the backchannel.\r\n this.deadBackChannelTimerId_ = requestStats.setTimeout(\r\n goog.bind(this.onBackChannelDead_, this),\r\n 2 * WebChannelBase.RTT_ESTIMATE);\r\n }\r\n }\r\n};\r\n\r\n\r\n/**\r\n * Handles a POST response from the server telling us that it has detected that\r\n * we have no hanging GET connection.\r\n * @param {!ChannelRequest} forwardReq The forward channel request that\r\n * triggers this function call.\r\n * @private\r\n */\r\nWebChannelBase.prototype.handleBackchannelMissing_ = function(forwardReq) {\r\n // As long as the back channel was started before the POST was sent,\r\n // we should retry the backchannel. We give a slight buffer of RTT_ESTIMATE\r\n // so as not to excessively retry the backchannel\r\n this.channelDebug_.debug('Server claims our backchannel is missing.');\r\n if (this.backChannelTimerId_) {\r\n this.channelDebug_.debug('But we are currently starting the request.');\r\n return;\r\n } else if (!this.backChannelRequest_) {\r\n this.channelDebug_.warning('We do not have a BackChannel established');\r\n } else if (\r\n this.backChannelRequest_.getRequestStartTime() +\r\n WebChannelBase.RTT_ESTIMATE <\r\n forwardReq.getRequestStartTime()) {\r\n this.clearDeadBackchannelTimer_();\r\n this.backChannelRequest_.cancel();\r\n this.backChannelRequest_ = null;\r\n } else {\r\n return;\r\n }\r\n this.maybeRetryBackChannel_();\r\n requestStats.notifyStatEvent(requestStats.Stat.BACKCHANNEL_MISSING);\r\n};\r\n\r\n\r\n/**\r\n * Determines whether we should start the process of retrying a possibly\r\n * dead backchannel.\r\n * @param {number} outstandingBytes The number of bytes for which the server has\r\n * not yet received acknowledgement.\r\n * @return {boolean} Whether to start the backchannel retry timer.\r\n * @private\r\n */\r\nWebChannelBase.prototype.shouldRetryBackChannel_ = function(outstandingBytes) {\r\n // Not too many outstanding bytes, not buffered and not after a retry.\r\n return outstandingBytes <\r\n WebChannelBase.OUTSTANDING_DATA_BACKCHANNEL_RETRY_CUTOFF &&\r\n !this.isBuffered() && this.backChannelRetryCount_ == 0;\r\n};\r\n\r\n\r\n/**\r\n * Decides which host prefix should be used, if any. If there is a handler,\r\n * allows the handler to validate a host prefix provided by the server, and\r\n * optionally override it.\r\n * @param {?string} serverHostPrefix The host prefix provided by the server.\r\n * @return {?string} The host prefix to actually use, if any. Will return null\r\n * if the use of host prefixes was disabled via setAllowHostPrefix().\r\n * @override\r\n */\r\nWebChannelBase.prototype.correctHostPrefix = function(serverHostPrefix) {\r\n if (this.allowHostPrefix_) {\r\n if (this.handler_) {\r\n return this.handler_.correctHostPrefix(serverHostPrefix);\r\n }\r\n return serverHostPrefix;\r\n }\r\n return null;\r\n};\r\n\r\n\r\n/**\r\n * Handles the timer that indicates that our backchannel is no longer able to\r\n * successfully receive data from the server.\r\n * @private\r\n */\r\nWebChannelBase.prototype.onBackChannelDead_ = function() {\r\n if (goog.isDefAndNotNull(this.deadBackChannelTimerId_)) {\r\n this.deadBackChannelTimerId_ = null;\r\n this.backChannelRequest_.cancel();\r\n this.backChannelRequest_ = null;\r\n this.maybeRetryBackChannel_();\r\n requestStats.notifyStatEvent(requestStats.Stat.BACKCHANNEL_DEAD);\r\n }\r\n};\r\n\r\n\r\n/**\r\n * Clears the timer that indicates that our backchannel is no longer able to\r\n * successfully receive data from the server.\r\n * @private\r\n */\r\nWebChannelBase.prototype.clearDeadBackchannelTimer_ = function() {\r\n if (goog.isDefAndNotNull(this.deadBackChannelTimerId_)) {\r\n goog.global.clearTimeout(this.deadBackChannelTimerId_);\r\n this.deadBackChannelTimerId_ = null;\r\n }\r\n};\r\n\r\n\r\n/**\r\n * Returns whether or not the given error/status combination is fatal or not.\r\n * On fatal errors we immediately close the session rather than retrying the\r\n * failed request.\r\n * @param {?ChannelRequest.Error} error The error code for the\r\n * failed request.\r\n * @param {number} statusCode The last HTTP status code.\r\n * @return {boolean} Whether or not the error is fatal.\r\n * @private\r\n */\r\nWebChannelBase.isFatalError_ = function(error, statusCode) {\r\n return error == ChannelRequest.Error.UNKNOWN_SESSION_ID ||\r\n (error == ChannelRequest.Error.STATUS && statusCode > 0);\r\n};\r\n\r\n\r\n/**\r\n * @override\r\n */\r\nWebChannelBase.prototype.onRequestComplete = function(request) {\r\n this.channelDebug_.debug('Request complete');\r\n var type;\r\n var pendingMessages = null;\r\n if (this.backChannelRequest_ == request) {\r\n this.clearDeadBackchannelTimer_();\r\n this.backChannelRequest_ = null;\r\n type = WebChannelBase.ChannelType_.BACK_CHANNEL;\r\n } else if (this.forwardChannelRequestPool_.hasRequest(request)) {\r\n pendingMessages = request.getPendingMessages();\r\n this.forwardChannelRequestPool_.removeRequest(request);\r\n type = WebChannelBase.ChannelType_.FORWARD_CHANNEL;\r\n } else {\r\n // return if it was an old request from a previous session\r\n return;\r\n }\r\n\r\n this.lastStatusCode_ = request.getLastStatusCode();\r\n\r\n if (this.state_ == WebChannelBase.State.CLOSED) {\r\n return;\r\n }\r\n\r\n if (request.getSuccess()) {\r\n // Yay!\r\n if (type == WebChannelBase.ChannelType_.FORWARD_CHANNEL) {\r\n var size = request.getPostData() ? request.getPostData().length : 0;\r\n requestStats.notifyTimingEvent(\r\n size, goog.now() - request.getRequestStartTime(),\r\n this.forwardChannelRetryCount_);\r\n this.ensureForwardChannel_();\r\n this.onSuccess_(request);\r\n } else { // i.e., back-channel\r\n this.ensureBackChannel_();\r\n }\r\n return;\r\n }\r\n // Else unsuccessful. Fall through.\r\n\r\n var lastError = request.getLastError();\r\n if (!WebChannelBase.isFatalError_(lastError, this.lastStatusCode_)) {\r\n // Maybe retry.\r\n var self = this;\r\n this.channelDebug_.debug(function() {\r\n return 'Maybe retrying, last error: ' +\r\n ChannelRequest.errorStringFromCode(lastError, self.lastStatusCode_);\r\n });\r\n if (type == WebChannelBase.ChannelType_.FORWARD_CHANNEL) {\r\n if (this.maybeRetryForwardChannel_(request)) {\r\n return;\r\n }\r\n }\r\n if (type == WebChannelBase.ChannelType_.BACK_CHANNEL) {\r\n if (this.maybeRetryBackChannel_()) {\r\n return;\r\n }\r\n }\r\n // Else exceeded max retries. Fall through.\r\n this.channelDebug_.debug('Exceeded max number of retries');\r\n } else {\r\n // Else fatal error. Fall through and mark the pending maps as failed.\r\n this.channelDebug_.debug('Not retrying due to error type');\r\n }\r\n\r\n\r\n // Abort the channel now\r\n\r\n // Record pending messages from the failed request\r\n if (pendingMessages && pendingMessages.length > 0) {\r\n this.forwardChannelRequestPool_.addPendingMessages(pendingMessages);\r\n }\r\n\r\n this.channelDebug_.debug('Error: HTTP request failed');\r\n switch (lastError) {\r\n case ChannelRequest.Error.NO_DATA:\r\n this.signalError_(WebChannelBase.Error.NO_DATA);\r\n break;\r\n case ChannelRequest.Error.BAD_DATA:\r\n this.signalError_(WebChannelBase.Error.BAD_DATA);\r\n break;\r\n case ChannelRequest.Error.UNKNOWN_SESSION_ID:\r\n this.signalError_(WebChannelBase.Error.UNKNOWN_SESSION_ID);\r\n break;\r\n default:\r\n this.signalError_(WebChannelBase.Error.REQUEST_FAILED);\r\n break;\r\n }\r\n};\r\n\r\n\r\n/**\r\n * @param {number} retryCount Number of retries so far.\r\n * @return {number} Time in ms before firing next retry request.\r\n * @private\r\n */\r\nWebChannelBase.prototype.getRetryTime_ = function(retryCount) {\r\n var retryTime = this.baseRetryDelayMs_ +\r\n Math.floor(Math.random() * this.retryDelaySeedMs_);\r\n if (!this.isActive()) {\r\n this.channelDebug_.debug('Inactive channel');\r\n retryTime = retryTime * WebChannelBase.INACTIVE_CHANNEL_RETRY_FACTOR;\r\n }\r\n // Backoff for subsequent retries\r\n retryTime *= retryCount;\r\n return retryTime;\r\n};\r\n\r\n\r\n/**\r\n * @param {number} baseDelayMs The base part of the retry delay, in ms.\r\n * @param {number} delaySeedMs A random delay between 0 and this is added to\r\n * the base part.\r\n */\r\nWebChannelBase.prototype.setRetryDelay = function(baseDelayMs, delaySeedMs) {\r\n this.baseRetryDelayMs_ = baseDelayMs;\r\n this.retryDelaySeedMs_ = delaySeedMs;\r\n};\r\n\r\n\r\n/**\r\n * Apply any handshake control headers.\r\n * @param {!ChannelRequest} request The underlying request object\r\n * @private\r\n */\r\nWebChannelBase.prototype.applyControlHeaders_ = function(request) {\r\n if (!this.backgroundChannelTest_) {\r\n return;\r\n }\r\n\r\n var xhr = request.getXhr();\r\n if (xhr) {\r\n var clientProtocol =\r\n xhr.getStreamingResponseHeader(WebChannel.X_CLIENT_WIRE_PROTOCOL);\r\n if (clientProtocol) {\r\n this.forwardChannelRequestPool_.applyClientProtocol(clientProtocol);\r\n }\r\n\r\n if (this.getHttpSessionIdParam()) {\r\n var httpSessionIdHeader =\r\n xhr.getStreamingResponseHeader(WebChannel.X_HTTP_SESSION_ID);\r\n if (httpSessionIdHeader) {\r\n this.setHttpSessionId(httpSessionIdHeader);\r\n // update the cached uri\r\n var httpSessionIdParam = this.getHttpSessionIdParam();\r\n\r\n this.forwardChannelUri_.setParameterValue(\r\n /** @type {string} */ (httpSessionIdParam), // never null\r\n httpSessionIdHeader);\r\n } else {\r\n this.channelDebug_.warning(\r\n 'Missing X_HTTP_SESSION_ID in the handshake response');\r\n }\r\n }\r\n }\r\n};\r\n\r\n\r\n/**\r\n * Processes the data returned by the server.\r\n * @param {!Array<!Array<?>>} respArray The response array returned\r\n * by the server.\r\n * @param {!ChannelRequest} request The underlying request object\r\n * @private\r\n */\r\nWebChannelBase.prototype.onInput_ = function(respArray, request) {\r\n var batch =\r\n this.handler_ && this.handler_.channelHandleMultipleArrays ? [] : null;\r\n for (var i = 0; i < respArray.length; i++) {\r\n var nextArray = respArray[i];\r\n this.lastArrayId_ = nextArray[0];\r\n nextArray = nextArray[1];\r\n if (this.state_ == WebChannelBase.State.OPENING) {\r\n if (nextArray[0] == 'c') {\r\n this.sid_ = nextArray[1];\r\n this.hostPrefix_ = this.correctHostPrefix(nextArray[2]);\r\n\r\n var negotiatedVersion = nextArray[3];\r\n if (goog.isDefAndNotNull(negotiatedVersion)) {\r\n this.channelVersion_ = negotiatedVersion;\r\n this.channelDebug_.info('VER=' + this.channelVersion_);\r\n }\r\n\r\n var negotiatedServerVersion = nextArray[4];\r\n if (goog.isDefAndNotNull(negotiatedServerVersion)) {\r\n this.serverVersion_ = negotiatedServerVersion;\r\n this.channelDebug_.info('SVER=' + this.serverVersion_);\r\n }\r\n\r\n // CVER=22\r\n var serverKeepaliveMs = nextArray[5];\r\n if (goog.isDefAndNotNull(serverKeepaliveMs) &&\r\n goog.isNumber(serverKeepaliveMs) && serverKeepaliveMs > 0) {\r\n var timeout = 1.5 * serverKeepaliveMs;\r\n this.backChannelRequestTimeoutMs_ = timeout;\r\n this.channelDebug_.info('backChannelRequestTimeoutMs_=' + timeout);\r\n }\r\n\r\n this.applyControlHeaders_(request);\r\n\r\n this.state_ = WebChannelBase.State.OPENED;\r\n if (this.handler_) {\r\n this.handler_.channelOpened(this);\r\n }\r\n\r\n this.startBackchannelAfterHandshake_(request);\r\n\r\n if (this.outgoingMaps_.length > 0) {\r\n this.ensureForwardChannel_();\r\n }\r\n } else if (nextArray[0] == 'stop' || nextArray[0] == 'close') {\r\n // treat close also as an abort\r\n this.signalError_(WebChannelBase.Error.STOP);\r\n }\r\n } else if (this.state_ == WebChannelBase.State.OPENED) {\r\n if (nextArray[0] == 'stop' || nextArray[0] == 'close') {\r\n if (batch && !goog.array.isEmpty(batch)) {\r\n this.handler_.channelHandleMultipleArrays(this, batch);\r\n batch.length = 0;\r\n }\r\n if (nextArray[0] == 'stop') {\r\n this.signalError_(WebChannelBase.Error.STOP);\r\n } else {\r\n this.disconnect();\r\n }\r\n } else if (nextArray[0] == 'noop') {\r\n // ignore - noop to keep connection happy\r\n } else {\r\n if (batch) {\r\n batch.push(nextArray);\r\n } else if (this.handler_) {\r\n this.handler_.channelHandleArray(this, nextArray);\r\n }\r\n }\r\n // We have received useful data on the back-channel, so clear its retry\r\n // count. We do this because back-channels by design do not complete\r\n // quickly, so on a flaky connection we could have many fail to complete\r\n // fully but still deliver a lot of data before they fail. We don't want\r\n // to count such failures towards the retry limit, because we don't want\r\n // to give up on a session if we can still receive data.\r\n this.backChannelRetryCount_ = 0;\r\n }\r\n }\r\n if (batch && !goog.array.isEmpty(batch)) {\r\n this.handler_.channelHandleMultipleArrays(this, batch);\r\n }\r\n};\r\n\r\n\r\n/**\r\n * Starts the backchannel after the handshake.\r\n *\r\n * @param {!ChannelRequest} request The underlying request object\r\n * @private\r\n */\r\nWebChannelBase.prototype.startBackchannelAfterHandshake_ = function(request) {\r\n this.backChannelUri_ = this.getBackChannelUri(\r\n this.hostPrefix_, /** @type {string} */ (this.path_));\r\n\r\n if (request.isInitialResponseDecoded()) {\r\n this.channelDebug_.debug('Upgrade the handshake request to a backchannel.');\r\n this.forwardChannelRequestPool_.removeRequest(request);\r\n request.resetTimeout(this.backChannelRequestTimeoutMs_);\r\n this.backChannelRequest_ = request;\r\n } else {\r\n // Open connection to receive data\r\n this.ensureBackChannel_();\r\n }\r\n};\r\n\r\n\r\n/**\r\n * Helper to ensure the channel is in the expected state.\r\n * @param {...number} var_args The channel must be in one of the indicated\r\n * states.\r\n * @private\r\n */\r\nWebChannelBase.prototype.ensureInState_ = function(var_args) {\r\n goog.asserts.assert(\r\n goog.array.contains(arguments, this.state_),\r\n 'Unexpected channel state: %s', this.state_);\r\n};\r\n\r\n\r\n/**\r\n * Signals an error has occurred.\r\n * @param {WebChannelBase.Error} error The error code for the failure.\r\n * @private\r\n */\r\nWebChannelBase.prototype.signalError_ = function(error) {\r\n this.channelDebug_.info('Error code ' + error);\r\n if (error == WebChannelBase.Error.REQUEST_FAILED) {\r\n // Create a separate Internet connection to check\r\n // if it's a server error or user's network error.\r\n var imageUri = null;\r\n if (this.handler_) {\r\n imageUri = this.handler_.getNetworkTestImageUri(this);\r\n }\r\n netUtils.testNetwork(goog.bind(this.testNetworkCallback_, this), imageUri);\r\n } else {\r\n requestStats.notifyStatEvent(requestStats.Stat.ERROR_OTHER);\r\n }\r\n this.onError_(error);\r\n};\r\n\r\n\r\n/**\r\n * Callback for netUtils.testNetwork during error handling.\r\n * @param {boolean} networkUp Whether the network is up.\r\n * @private\r\n */\r\nWebChannelBase.prototype.testNetworkCallback_ = function(networkUp) {\r\n if (networkUp) {\r\n this.channelDebug_.info('Successfully pinged google.com');\r\n requestStats.notifyStatEvent(requestStats.Stat.ERROR_OTHER);\r\n } else {\r\n this.channelDebug_.info('Failed to ping google.com');\r\n requestStats.notifyStatEvent(requestStats.Stat.ERROR_NETWORK);\r\n // Do not call onError_ again to eliminate duplicated Error events.\r\n }\r\n};\r\n\r\n\r\n/**\r\n * Called when messages have been successfully sent from the queue.\r\n * @param {!ChannelRequest} request The request object\r\n * @private\r\n */\r\nWebChannelBase.prototype.onSuccess_ = function(request) {\r\n if (this.handler_) {\r\n this.handler_.channelSuccess(this, request);\r\n }\r\n};\r\n\r\n\r\n/**\r\n * Called when we've determined the final error for a channel. It closes the\r\n * notifiers the handler of the error and closes the channel.\r\n * @param {WebChannelBase.Error} error The error code for the failure.\r\n * @private\r\n */\r\nWebChannelBase.prototype.onError_ = function(error) {\r\n this.channelDebug_.debug('HttpChannel: error - ' + error);\r\n this.state_ = WebChannelBase.State.CLOSED;\r\n if (this.handler_) {\r\n this.handler_.channelError(this, error);\r\n }\r\n this.onClose_();\r\n this.cancelRequests_();\r\n};\r\n\r\n\r\n/**\r\n * Called when the channel has been closed. It notifiers the handler of the\r\n * event, and reports any pending or undelivered maps.\r\n * @private\r\n */\r\nWebChannelBase.prototype.onClose_ = function() {\r\n this.state_ = WebChannelBase.State.CLOSED;\r\n this.lastStatusCode_ = -1;\r\n if (this.handler_) {\r\n var pendingMessages = this.forwardChannelRequestPool_.getPendingMessages();\r\n\r\n if (pendingMessages.length == 0 && this.outgoingMaps_.length == 0) {\r\n this.handler_.channelClosed(this);\r\n } else {\r\n var self = this;\r\n this.channelDebug_.debug(function() {\r\n return 'Number of undelivered maps' +\r\n ', pending: ' + pendingMessages.length +\r\n ', outgoing: ' + self.outgoingMaps_.length;\r\n });\r\n\r\n this.forwardChannelRequestPool_.clearPendingMessages();\r\n\r\n var copyOfUndeliveredMaps = goog.array.clone(this.outgoingMaps_);\r\n this.outgoingMaps_.length = 0;\r\n\r\n this.handler_.channelClosed(this, pendingMessages, copyOfUndeliveredMaps);\r\n }\r\n }\r\n};\r\n\r\n\r\n/**\r\n * @override\r\n */\r\nWebChannelBase.prototype.getForwardChannelUri = function(path) {\r\n var uri = this.createDataUri(null, path);\r\n this.channelDebug_.debug('GetForwardChannelUri: ' + uri);\r\n return uri;\r\n};\r\n\r\n\r\n/**\r\n * @override\r\n */\r\nWebChannelBase.prototype.getConnectionState = function() {\r\n return this.connState_;\r\n};\r\n\r\n\r\n/**\r\n * @override\r\n */\r\nWebChannelBase.prototype.getBackChannelUri = function(hostPrefix, path) {\r\n var uri = this.createDataUri(\r\n this.shouldUseSecondaryDomains() ? hostPrefix : null, path);\r\n this.channelDebug_.debug('GetBackChannelUri: ' + uri);\r\n return uri;\r\n};\r\n\r\n\r\n/**\r\n * @override\r\n */\r\nWebChannelBase.prototype.createDataUri = function(\r\n hostPrefix, path, opt_overridePort) {\r\n var uri = goog.Uri.parse(path);\r\n var uriAbsolute = (uri.getDomain() != '');\r\n if (uriAbsolute) {\r\n if (hostPrefix) {\r\n uri.setDomain(hostPrefix + '.' + uri.getDomain());\r\n }\r\n\r\n uri.setPort(opt_overridePort || uri.getPort());\r\n } else {\r\n var locationPage = goog.global.location;\r\n var hostName;\r\n if (hostPrefix) {\r\n hostName = hostPrefix + '.' + locationPage.hostname;\r\n } else {\r\n hostName = locationPage.hostname;\r\n }\r\n\r\n var port = opt_overridePort || +locationPage.port;\r\n\r\n uri = goog.Uri.create(locationPage.protocol, null, hostName, port, path);\r\n }\r\n\r\n if (this.extraParams_) {\r\n goog.object.forEach(this.extraParams_, function(value, key) {\r\n uri.setParameterValue(key, value);\r\n });\r\n }\r\n\r\n var param = this.getHttpSessionIdParam();\r\n var value = this.getHttpSessionId();\r\n if (param && value) {\r\n uri.setParameterValue(param, value);\r\n }\r\n\r\n // Add the protocol version to the URI.\r\n uri.setParameterValue('VER', this.channelVersion_);\r\n\r\n // Add the reconnect parameters.\r\n this.addAdditionalParams_(uri);\r\n\r\n return uri;\r\n};\r\n\r\n\r\n/**\r\n * @override\r\n */\r\nWebChannelBase.prototype.createXhrIo = function(hostPrefix) {\r\n if (hostPrefix && !this.supportsCrossDomainXhrs_) {\r\n throw new Error('Can\\'t create secondary domain capable XhrIo object.');\r\n }\r\n var xhr = new goog.net.XhrIo(this.xmlHttpFactory_);\r\n xhr.setWithCredentials(this.supportsCrossDomainXhrs_);\r\n return xhr;\r\n};\r\n\r\n\r\n/**\r\n * @override\r\n */\r\nWebChannelBase.prototype.isActive = function() {\r\n return !!this.handler_ && this.handler_.isActive(this);\r\n};\r\n\r\n\r\n/**\r\n * @override\r\n */\r\nWebChannelBase.prototype.shouldUseSecondaryDomains = function() {\r\n return this.supportsCrossDomainXhrs_;\r\n};\r\n\r\n\r\n/**\r\n * Sets (overwrites) the forward channel flush callback.\r\n *\r\n * @param {function()} callback The callback to be invoked.\r\n */\r\nWebChannelBase.prototype.setForwardChannelFlushCallback = function(callback) {\r\n this.forwardChannelFlushedCallback_ = callback;\r\n};\r\n\r\n\r\n/**\r\n * A LogSaver that can be used to accumulate all the debug logs so they\r\n * can be sent to the server when a problem is detected.\r\n * @const\r\n */\r\nWebChannelBase.LogSaver = {};\r\n\r\n\r\n/**\r\n * Buffer for accumulating the debug log\r\n * @type {goog.structs.CircularBuffer}\r\n * @private\r\n */\r\nWebChannelBase.LogSaver.buffer_ = new goog.structs.CircularBuffer(1000);\r\n\r\n\r\n/**\r\n * Whether we're currently accumulating the debug log.\r\n * @type {boolean}\r\n * @private\r\n */\r\nWebChannelBase.LogSaver.enabled_ = false;\r\n\r\n\r\n/**\r\n * Formatter for saving logs.\r\n * @type {goog.debug.Formatter}\r\n * @private\r\n */\r\nWebChannelBase.LogSaver.formatter_ = new goog.debug.TextFormatter();\r\n\r\n\r\n/**\r\n * Returns whether the LogSaver is enabled.\r\n * @return {boolean} Whether saving is enabled or disabled.\r\n */\r\nWebChannelBase.LogSaver.isEnabled = function() {\r\n return WebChannelBase.LogSaver.enabled_;\r\n};\r\n\r\n\r\n/**\r\n * Enables of disables the LogSaver.\r\n * @param {boolean} enable Whether to enable or disable saving.\r\n */\r\nWebChannelBase.LogSaver.setEnabled = function(enable) {\r\n if (enable == WebChannelBase.LogSaver.enabled_) {\r\n return;\r\n }\r\n\r\n var fn = WebChannelBase.LogSaver.addLogRecord;\r\n var logger = goog.log.getLogger('goog.net');\r\n if (enable) {\r\n goog.log.addHandler(logger, fn);\r\n } else {\r\n goog.log.removeHandler(logger, fn);\r\n }\r\n};\r\n\r\n\r\n/**\r\n * Adds a log record.\r\n * @param {goog.log.LogRecord} logRecord the LogRecord.\r\n */\r\nWebChannelBase.LogSaver.addLogRecord = function(logRecord) {\r\n WebChannelBase.LogSaver.buffer_.add(\r\n WebChannelBase.LogSaver.formatter_.formatRecord(logRecord));\r\n};\r\n\r\n\r\n/**\r\n * Returns the log as a single string.\r\n * @return {string} The log as a single string.\r\n */\r\nWebChannelBase.LogSaver.getBuffer = function() {\r\n return WebChannelBase.LogSaver.buffer_.getValues().join('');\r\n};\r\n\r\n\r\n/**\r\n * Clears the buffer\r\n */\r\nWebChannelBase.LogSaver.clearBuffer = function() {\r\n WebChannelBase.LogSaver.buffer_.clear();\r\n};\r\n\r\n\r\n\r\n/**\r\n * Abstract base class for the channel handler\r\n * @constructor\r\n * @struct\r\n */\r\nWebChannelBase.Handler = function() {};\r\n\r\n\r\n/**\r\n * Callback handler for when a batch of response arrays is received from the\r\n * server. When null, batched dispatching is disabled.\r\n * @type {?function(!WebChannelBase, !Array<!Array<?>>)}\r\n */\r\nWebChannelBase.Handler.prototype.channelHandleMultipleArrays = null;\r\n\r\n\r\n/**\r\n * Whether it's okay to make a request to the server. A handler can return\r\n * false if the channel should fail. For example, if the user has logged out,\r\n * the handler may want all requests to fail immediately.\r\n * @param {WebChannelBase} channel The channel.\r\n * @return {WebChannelBase.Error} An error code. The code should\r\n * return WebChannelBase.Error.OK to indicate it's okay. Any other\r\n * error code will cause a failure.\r\n */\r\nWebChannelBase.Handler.prototype.okToMakeRequest = function(channel) {\r\n return WebChannelBase.Error.OK;\r\n};\r\n\r\n\r\n/**\r\n * Indicates the WebChannel has successfully negotiated with the server\r\n * and can now send and receive data.\r\n * @param {WebChannelBase} channel The channel.\r\n */\r\nWebChannelBase.Handler.prototype.channelOpened = function(channel) {};\r\n\r\n\r\n/**\r\n * New input is available for the application to process.\r\n *\r\n * @param {WebChannelBase} channel The channel.\r\n * @param {Array<?>} array The data array.\r\n */\r\nWebChannelBase.Handler.prototype.channelHandleArray = function(\r\n channel, array) {};\r\n\r\n\r\n/**\r\n * Indicates messages that have been successfully sent on the channel.\r\n *\r\n * @param {WebChannelBase} channel The channel.\r\n * @param {!ChannelRequest} request The request object that contains\r\n * the pending messages that have been successfully delivered to the server.\r\n */\r\nWebChannelBase.Handler.prototype.channelSuccess = function(channel, request) {};\r\n\r\n\r\n/**\r\n * Indicates an error occurred on the WebChannel.\r\n *\r\n * @param {WebChannelBase} channel The channel.\r\n * @param {WebChannelBase.Error} error The error code.\r\n */\r\nWebChannelBase.Handler.prototype.channelError = function(channel, error) {};\r\n\r\n\r\n/**\r\n * Indicates the WebChannel is closed. Also notifies about which maps,\r\n * if any, that may not have been delivered to the server.\r\n * @param {WebChannelBase} channel The channel.\r\n * @param {Array<Wire.QueuedMap>=} opt_pendingMaps The\r\n * array of pending maps, which may or may not have been delivered to the\r\n * server.\r\n * @param {Array<Wire.QueuedMap>=} opt_undeliveredMaps\r\n * The array of undelivered maps, which have definitely not been delivered\r\n * to the server.\r\n */\r\nWebChannelBase.Handler.prototype.channelClosed = function(\r\n channel, opt_pendingMaps, opt_undeliveredMaps) {};\r\n\r\n\r\n/**\r\n * Gets any parameters that should be added at the time another connection is\r\n * made to the server.\r\n * @param {WebChannelBase} channel The channel.\r\n * @return {!Object} Extra parameter keys and values to add to the requests.\r\n */\r\nWebChannelBase.Handler.prototype.getAdditionalParams = function(channel) {\r\n return {};\r\n};\r\n\r\n\r\n/**\r\n * Gets the URI of an image that can be used to test network connectivity.\r\n * @param {WebChannelBase} channel The channel.\r\n * @return {goog.Uri?} A custom URI to load for the network test.\r\n */\r\nWebChannelBase.Handler.prototype.getNetworkTestImageUri = function(channel) {\r\n return null;\r\n};\r\n\r\n\r\n/**\r\n * Gets whether this channel is currently active. This is used to determine the\r\n * length of time to wait before retrying.\r\n * @param {WebChannelBase} channel The channel.\r\n * @return {boolean} Whether the channel is currently active.\r\n */\r\nWebChannelBase.Handler.prototype.isActive = function(channel) {\r\n return true;\r\n};\r\n\r\n\r\n/**\r\n * Called by the channel if enumeration of the map throws an exception.\r\n * @param {WebChannelBase} channel The channel.\r\n * @param {Object} map The map that can't be enumerated.\r\n */\r\nWebChannelBase.Handler.prototype.badMapError = function(channel, map) {};\r\n\r\n\r\n/**\r\n * Allows the handler to override a host prefix provided by the server. Will\r\n * be called whenever the channel has received such a prefix and is considering\r\n * its use.\r\n * @param {?string} serverHostPrefix The host prefix provided by the server.\r\n * @return {?string} The host prefix the client should use.\r\n */\r\nWebChannelBase.Handler.prototype.correctHostPrefix = function(\r\n serverHostPrefix) {\r\n return serverHostPrefix;\r\n};\r\n}); // goog.scope\r\n","// Copyright 2006 The Closure Library Authors. All Rights Reserved.\r\n//\r\n// Licensed under the Apache License, Version 2.0 (the \"License\");\r\n// you may not use this file except in compliance with the License.\r\n// You may obtain a copy of the License at\r\n//\r\n// http://www.apache.org/licenses/LICENSE-2.0\r\n//\r\n// Unless required by applicable law or agreed to in writing, software\r\n// distributed under the License is distributed on an \"AS-IS\" BASIS,\r\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n// See the License for the specific language governing permissions and\r\n// limitations under the License.\r\n\r\n/**\r\n * @fileoverview Utilities for string manipulation.\r\n * @author arv@google.com (Erik Arvidsson)\r\n */\r\n\r\n\r\n/**\r\n * Namespace for string utilities\r\n */\r\ngoog.provide('goog.string');\r\ngoog.provide('goog.string.Unicode');\r\n\r\ngoog.require('goog.string.internal');\r\n\r\n\r\n/**\r\n * @define {boolean} Enables HTML escaping of lowercase letter \"e\" which helps\r\n * with detection of double-escaping as this letter is frequently used.\r\n */\r\ngoog.string.DETECT_DOUBLE_ESCAPING =\r\n goog.define('goog.string.DETECT_DOUBLE_ESCAPING', false);\r\n\r\n\r\n/**\r\n * @define {boolean} Whether to force non-dom html unescaping.\r\n */\r\ngoog.string.FORCE_NON_DOM_HTML_UNESCAPING =\r\n goog.define('goog.string.FORCE_NON_DOM_HTML_UNESCAPING', false);\r\n\r\n\r\n/**\r\n * Common Unicode string characters.\r\n * @enum {string}\r\n */\r\ngoog.string.Unicode = {\r\n NBSP: '\\xa0'\r\n};\r\n\r\n\r\n/**\r\n * Fast prefix-checker.\r\n * @param {string} str The string to check.\r\n * @param {string} prefix A string to look for at the start of `str`.\r\n * @return {boolean} True if `str` begins with `prefix`.\r\n */\r\ngoog.string.startsWith = goog.string.internal.startsWith;\r\n\r\n\r\n/**\r\n * Fast suffix-checker.\r\n * @param {string} str The string to check.\r\n * @param {string} suffix A string to look for at the end of `str`.\r\n * @return {boolean} True if `str` ends with `suffix`.\r\n */\r\ngoog.string.endsWith = goog.string.internal.endsWith;\r\n\r\n\r\n/**\r\n * Case-insensitive prefix-checker.\r\n * @param {string} str The string to check.\r\n * @param {string} prefix A string to look for at the end of `str`.\r\n * @return {boolean} True if `str` begins with `prefix` (ignoring\r\n * case).\r\n */\r\ngoog.string.caseInsensitiveStartsWith =\r\n goog.string.internal.caseInsensitiveStartsWith;\r\n\r\n\r\n/**\r\n * Case-insensitive suffix-checker.\r\n * @param {string} str The string to check.\r\n * @param {string} suffix A string to look for at the end of `str`.\r\n * @return {boolean} True if `str` ends with `suffix` (ignoring\r\n * case).\r\n */\r\ngoog.string.caseInsensitiveEndsWith =\r\n goog.string.internal.caseInsensitiveEndsWith;\r\n\r\n\r\n/**\r\n * Case-insensitive equality checker.\r\n * @param {string} str1 First string to check.\r\n * @param {string} str2 Second string to check.\r\n * @return {boolean} True if `str1` and `str2` are the same string,\r\n * ignoring case.\r\n */\r\ngoog.string.caseInsensitiveEquals = goog.string.internal.caseInsensitiveEquals;\r\n\r\n\r\n/**\r\n * Does simple python-style string substitution.\r\n * subs(\"foo%s hot%s\", \"bar\", \"dog\") becomes \"foobar hotdog\".\r\n * @param {string} str The string containing the pattern.\r\n * @param {...*} var_args The items to substitute into the pattern.\r\n * @return {string} A copy of `str` in which each occurrence of\r\n * {@code %s} has been replaced an argument from `var_args`.\r\n */\r\ngoog.string.subs = function(str, var_args) {\r\n var splitParts = str.split('%s');\r\n var returnString = '';\r\n\r\n var subsArguments = Array.prototype.slice.call(arguments, 1);\r\n while (subsArguments.length &&\r\n // Replace up to the last split part. We are inserting in the\r\n // positions between split parts.\r\n splitParts.length > 1) {\r\n returnString += splitParts.shift() + subsArguments.shift();\r\n }\r\n\r\n return returnString + splitParts.join('%s'); // Join unused '%s'\r\n};\r\n\r\n\r\n/**\r\n * Converts multiple whitespace chars (spaces, non-breaking-spaces, new lines\r\n * and tabs) to a single space, and strips leading and trailing whitespace.\r\n * @param {string} str Input string.\r\n * @return {string} A copy of `str` with collapsed whitespace.\r\n */\r\ngoog.string.collapseWhitespace = function(str) {\r\n // Since IE doesn't include non-breaking-space (0xa0) in their \\s character\r\n // class (as required by section 7.2 of the ECMAScript spec), we explicitly\r\n // include it in the regexp to enforce consistent cross-browser behavior.\r\n return str.replace(/[\\s\\xa0]+/g, ' ').replace(/^\\s+|\\s+$/g, '');\r\n};\r\n\r\n\r\n/**\r\n * Checks if a string is empty or contains only whitespaces.\r\n * @param {string} str The string to check.\r\n * @return {boolean} Whether `str` is empty or whitespace only.\r\n */\r\ngoog.string.isEmptyOrWhitespace = goog.string.internal.isEmptyOrWhitespace;\r\n\r\n\r\n/**\r\n * Checks if a string is empty.\r\n * @param {string} str The string to check.\r\n * @return {boolean} Whether `str` is empty.\r\n */\r\ngoog.string.isEmptyString = function(str) {\r\n return str.length == 0;\r\n};\r\n\r\n\r\n/**\r\n * Checks if a string is empty or contains only whitespaces.\r\n *\r\n * @param {string} str The string to check.\r\n * @return {boolean} Whether `str` is empty or whitespace only.\r\n * @deprecated Use goog.string.isEmptyOrWhitespace instead.\r\n */\r\ngoog.string.isEmpty = goog.string.isEmptyOrWhitespace;\r\n\r\n\r\n/**\r\n * Checks if a string is null, undefined, empty or contains only whitespaces.\r\n * @param {*} str The string to check.\r\n * @return {boolean} Whether `str` is null, undefined, empty, or\r\n * whitespace only.\r\n * @deprecated Use goog.string.isEmptyOrWhitespace(goog.string.makeSafe(str))\r\n * instead.\r\n */\r\ngoog.string.isEmptyOrWhitespaceSafe = function(str) {\r\n return goog.string.isEmptyOrWhitespace(goog.string.makeSafe(str));\r\n};\r\n\r\n\r\n/**\r\n * Checks if a string is null, undefined, empty or contains only whitespaces.\r\n *\r\n * @param {*} str The string to check.\r\n * @return {boolean} Whether `str` is null, undefined, empty, or\r\n * whitespace only.\r\n * @deprecated Use goog.string.isEmptyOrWhitespace instead.\r\n */\r\ngoog.string.isEmptySafe = goog.string.isEmptyOrWhitespaceSafe;\r\n\r\n\r\n/**\r\n * Checks if a string is all breaking whitespace.\r\n * @param {string} str The string to check.\r\n * @return {boolean} Whether the string is all breaking whitespace.\r\n */\r\ngoog.string.isBreakingWhitespace = function(str) {\r\n return !/[^\\t\\n\\r ]/.test(str);\r\n};\r\n\r\n\r\n/**\r\n * Checks if a string contains all letters.\r\n * @param {string} str string to check.\r\n * @return {boolean} True if `str` consists entirely of letters.\r\n */\r\ngoog.string.isAlpha = function(str) {\r\n return !/[^a-zA-Z]/.test(str);\r\n};\r\n\r\n\r\n/**\r\n * Checks if a string contains only numbers.\r\n * @param {*} str string to check. If not a string, it will be\r\n * casted to one.\r\n * @return {boolean} True if `str` is numeric.\r\n */\r\ngoog.string.isNumeric = function(str) {\r\n return !/[^0-9]/.test(str);\r\n};\r\n\r\n\r\n/**\r\n * Checks if a string contains only numbers or letters.\r\n * @param {string} str string to check.\r\n * @return {boolean} True if `str` is alphanumeric.\r\n */\r\ngoog.string.isAlphaNumeric = function(str) {\r\n return !/[^a-zA-Z0-9]/.test(str);\r\n};\r\n\r\n\r\n/**\r\n * Checks if a character is a space character.\r\n * @param {string} ch Character to check.\r\n * @return {boolean} True if `ch` is a space.\r\n */\r\ngoog.string.isSpace = function(ch) {\r\n return ch == ' ';\r\n};\r\n\r\n\r\n/**\r\n * Checks if a character is a valid unicode character.\r\n * @param {string} ch Character to check.\r\n * @return {boolean} True if `ch` is a valid unicode character.\r\n */\r\ngoog.string.isUnicodeChar = function(ch) {\r\n return ch.length == 1 && ch >= ' ' && ch <= '~' ||\r\n ch >= '\\u0080' && ch <= '\\uFFFD';\r\n};\r\n\r\n\r\n/**\r\n * Takes a string and replaces newlines with a space. Multiple lines are\r\n * replaced with a single space.\r\n * @param {string} str The string from which to strip newlines.\r\n * @return {string} A copy of `str` stripped of newlines.\r\n */\r\ngoog.string.stripNewlines = function(str) {\r\n return str.replace(/(\\r\\n|\\r|\\n)+/g, ' ');\r\n};\r\n\r\n\r\n/**\r\n * Replaces Windows and Mac new lines with unix style: \\r or \\r\\n with \\n.\r\n * @param {string} str The string to in which to canonicalize newlines.\r\n * @return {string} `str` A copy of {@code} with canonicalized newlines.\r\n */\r\ngoog.string.canonicalizeNewlines = function(str) {\r\n return str.replace(/(\\r\\n|\\r|\\n)/g, '\\n');\r\n};\r\n\r\n\r\n/**\r\n * Normalizes whitespace in a string, replacing all whitespace chars with\r\n * a space.\r\n * @param {string} str The string in which to normalize whitespace.\r\n * @return {string} A copy of `str` with all whitespace normalized.\r\n */\r\ngoog.string.normalizeWhitespace = function(str) {\r\n return str.replace(/\\xa0|\\s/g, ' ');\r\n};\r\n\r\n\r\n/**\r\n * Normalizes spaces in a string, replacing all consecutive spaces and tabs\r\n * with a single space. Replaces non-breaking space with a space.\r\n * @param {string} str The string in which to normalize spaces.\r\n * @return {string} A copy of `str` with all consecutive spaces and tabs\r\n * replaced with a single space.\r\n */\r\ngoog.string.normalizeSpaces = function(str) {\r\n return str.replace(/\\xa0|[ \\t]+/g, ' ');\r\n};\r\n\r\n\r\n/**\r\n * Removes the breaking spaces from the left and right of the string and\r\n * collapses the sequences of breaking spaces in the middle into single spaces.\r\n * The original and the result strings render the same way in HTML.\r\n * @param {string} str A string in which to collapse spaces.\r\n * @return {string} Copy of the string with normalized breaking spaces.\r\n */\r\ngoog.string.collapseBreakingSpaces = function(str) {\r\n return str.replace(/[\\t\\r\\n ]+/g, ' ')\r\n .replace(/^[\\t\\r\\n ]+|[\\t\\r\\n ]+$/g, '');\r\n};\r\n\r\n\r\n/**\r\n * Trims white spaces to the left and right of a string.\r\n * @param {string} str The string to trim.\r\n * @return {string} A trimmed copy of `str`.\r\n */\r\ngoog.string.trim = goog.string.internal.trim;\r\n\r\n\r\n/**\r\n * Trims whitespaces at the left end of a string.\r\n * @param {string} str The string to left trim.\r\n * @return {string} A trimmed copy of `str`.\r\n */\r\ngoog.string.trimLeft = function(str) {\r\n // Since IE doesn't include non-breaking-space (0xa0) in their \\s character\r\n // class (as required by section 7.2 of the ECMAScript spec), we explicitly\r\n // include it in the regexp to enforce consistent cross-browser behavior.\r\n return str.replace(/^[\\s\\xa0]+/, '');\r\n};\r\n\r\n\r\n/**\r\n * Trims whitespaces at the right end of a string.\r\n * @param {string} str The string to right trim.\r\n * @return {string} A trimmed copy of `str`.\r\n */\r\ngoog.string.trimRight = function(str) {\r\n // Since IE doesn't include non-breaking-space (0xa0) in their \\s character\r\n // class (as required by section 7.2 of the ECMAScript spec), we explicitly\r\n // include it in the regexp to enforce consistent cross-browser behavior.\r\n return str.replace(/[\\s\\xa0]+$/, '');\r\n};\r\n\r\n\r\n/**\r\n * A string comparator that ignores case.\r\n * -1 = str1 less than str2\r\n * 0 = str1 equals str2\r\n * 1 = str1 greater than str2\r\n *\r\n * @param {string} str1 The string to compare.\r\n * @param {string} str2 The string to compare `str1` to.\r\n * @return {number} The comparator result, as described above.\r\n */\r\ngoog.string.caseInsensitiveCompare =\r\n goog.string.internal.caseInsensitiveCompare;\r\n\r\n\r\n/**\r\n * Compares two strings interpreting their numeric substrings as numbers.\r\n *\r\n * @param {string} str1 First string.\r\n * @param {string} str2 Second string.\r\n * @param {!RegExp} tokenizerRegExp Splits a string into substrings of\r\n * non-negative integers, non-numeric characters and optionally fractional\r\n * numbers starting with a decimal point.\r\n * @return {number} Negative if str1 < str2, 0 is str1 == str2, positive if\r\n * str1 > str2.\r\n * @private\r\n */\r\ngoog.string.numberAwareCompare_ = function(str1, str2, tokenizerRegExp) {\r\n if (str1 == str2) {\r\n return 0;\r\n }\r\n if (!str1) {\r\n return -1;\r\n }\r\n if (!str2) {\r\n return 1;\r\n }\r\n\r\n // Using match to split the entire string ahead of time turns out to be faster\r\n // for most inputs than using RegExp.exec or iterating over each character.\r\n var tokens1 = str1.toLowerCase().match(tokenizerRegExp);\r\n var tokens2 = str2.toLowerCase().match(tokenizerRegExp);\r\n\r\n var count = Math.min(tokens1.length, tokens2.length);\r\n\r\n for (var i = 0; i < count; i++) {\r\n var a = tokens1[i];\r\n var b = tokens2[i];\r\n\r\n // Compare pairs of tokens, returning if one token sorts before the other.\r\n if (a != b) {\r\n // Only if both tokens are integers is a special comparison required.\r\n // Decimal numbers are sorted as strings (e.g., '.09' < '.1').\r\n var num1 = parseInt(a, 10);\r\n if (!isNaN(num1)) {\r\n var num2 = parseInt(b, 10);\r\n if (!isNaN(num2) && num1 - num2) {\r\n return num1 - num2;\r\n }\r\n }\r\n return a < b ? -1 : 1;\r\n }\r\n }\r\n\r\n // If one string is a substring of the other, the shorter string sorts first.\r\n if (tokens1.length != tokens2.length) {\r\n return tokens1.length - tokens2.length;\r\n }\r\n\r\n // The two strings must be equivalent except for case (perfect equality is\r\n // tested at the head of the function.) Revert to default ASCII string\r\n // comparison to stabilize the sort.\r\n return str1 < str2 ? -1 : 1;\r\n};\r\n\r\n\r\n/**\r\n * String comparison function that handles non-negative integer numbers in a\r\n * way humans might expect. Using this function, the string 'File 2.jpg' sorts\r\n * before 'File 10.jpg', and 'Version 1.9' before 'Version 1.10'. The comparison\r\n * is mostly case-insensitive, though strings that are identical except for case\r\n * are sorted with the upper-case strings before lower-case.\r\n *\r\n * This comparison function is up to 50x slower than either the default or the\r\n * case-insensitive compare. It should not be used in time-critical code, but\r\n * should be fast enough to sort several hundred short strings (like filenames)\r\n * with a reasonable delay.\r\n *\r\n * @param {string} str1 The string to compare in a numerically sensitive way.\r\n * @param {string} str2 The string to compare `str1` to.\r\n * @return {number} less than 0 if str1 < str2, 0 if str1 == str2, greater than\r\n * 0 if str1 > str2.\r\n */\r\ngoog.string.intAwareCompare = function(str1, str2) {\r\n return goog.string.numberAwareCompare_(str1, str2, /\\d+|\\D+/g);\r\n};\r\n\r\n\r\n/**\r\n * String comparison function that handles non-negative integer and fractional\r\n * numbers in a way humans might expect. Using this function, the string\r\n * 'File 2.jpg' sorts before 'File 10.jpg', and '3.14' before '3.2'. Equivalent\r\n * to {@link goog.string.intAwareCompare} apart from the way how it interprets\r\n * dots.\r\n *\r\n * @param {string} str1 The string to compare in a numerically sensitive way.\r\n * @param {string} str2 The string to compare `str1` to.\r\n * @return {number} less than 0 if str1 < str2, 0 if str1 == str2, greater than\r\n * 0 if str1 > str2.\r\n */\r\ngoog.string.floatAwareCompare = function(str1, str2) {\r\n return goog.string.numberAwareCompare_(str1, str2, /\\d+|\\.\\d+|\\D+/g);\r\n};\r\n\r\n\r\n/**\r\n * Alias for {@link goog.string.floatAwareCompare}.\r\n *\r\n * @param {string} str1\r\n * @param {string} str2\r\n * @return {number}\r\n */\r\ngoog.string.numerateCompare = goog.string.floatAwareCompare;\r\n\r\n\r\n/**\r\n * URL-encodes a string\r\n * @param {*} str The string to url-encode.\r\n * @return {string} An encoded copy of `str` that is safe for urls.\r\n * Note that '#', ':', and other characters used to delimit portions\r\n * of URLs *will* be encoded.\r\n */\r\ngoog.string.urlEncode = function(str) {\r\n return encodeURIComponent(String(str));\r\n};\r\n\r\n\r\n/**\r\n * URL-decodes the string. We need to specially handle '+'s because\r\n * the javascript library doesn't convert them to spaces.\r\n * @param {string} str The string to url decode.\r\n * @return {string} The decoded `str`.\r\n */\r\ngoog.string.urlDecode = function(str) {\r\n return decodeURIComponent(str.replace(/\\+/g, ' '));\r\n};\r\n\r\n\r\n/**\r\n * Converts \\n to <br>s or <br />s.\r\n * @param {string} str The string in which to convert newlines.\r\n * @param {boolean=} opt_xml Whether to use XML compatible tags.\r\n * @return {string} A copy of `str` with converted newlines.\r\n */\r\ngoog.string.newLineToBr = goog.string.internal.newLineToBr;\r\n\r\n\r\n/**\r\n * Escapes double quote '\"' and single quote '\\'' characters in addition to\r\n * '&', '<', and '>' so that a string can be included in an HTML tag attribute\r\n * value within double or single quotes.\r\n *\r\n * It should be noted that > doesn't need to be escaped for the HTML or XML to\r\n * be valid, but it has been decided to escape it for consistency with other\r\n * implementations.\r\n *\r\n * With goog.string.DETECT_DOUBLE_ESCAPING, this function escapes also the\r\n * lowercase letter \"e\".\r\n *\r\n * NOTE(user):\r\n * HtmlEscape is often called during the generation of large blocks of HTML.\r\n * Using statics for the regular expressions and strings is an optimization\r\n * that can more than half the amount of time IE spends in this function for\r\n * large apps, since strings and regexes both contribute to GC allocations.\r\n *\r\n * Testing for the presence of a character before escaping increases the number\r\n * of function calls, but actually provides a speed increase for the average\r\n * case -- since the average case often doesn't require the escaping of all 4\r\n * characters and indexOf() is much cheaper than replace().\r\n * The worst case does suffer slightly from the additional calls, therefore the\r\n * opt_isLikelyToContainHtmlChars option has been included for situations\r\n * where all 4 HTML entities are very likely to be present and need escaping.\r\n *\r\n * Some benchmarks (times tended to fluctuate +-0.05ms):\r\n * FireFox IE6\r\n * (no chars / average (mix of cases) / all 4 chars)\r\n * no checks 0.13 / 0.22 / 0.22 0.23 / 0.53 / 0.80\r\n * indexOf 0.08 / 0.17 / 0.26 0.22 / 0.54 / 0.84\r\n * indexOf + re test 0.07 / 0.17 / 0.28 0.19 / 0.50 / 0.85\r\n *\r\n * An additional advantage of checking if replace actually needs to be called\r\n * is a reduction in the number of object allocations, so as the size of the\r\n * application grows the difference between the various methods would increase.\r\n *\r\n * @param {string} str string to be escaped.\r\n * @param {boolean=} opt_isLikelyToContainHtmlChars Don't perform a check to see\r\n * if the character needs replacing - use this option if you expect each of\r\n * the characters to appear often. Leave false if you expect few html\r\n * characters to occur in your strings, such as if you are escaping HTML.\r\n * @return {string} An escaped copy of `str`.\r\n */\r\ngoog.string.htmlEscape = function(str, opt_isLikelyToContainHtmlChars) {\r\n str = goog.string.internal.htmlEscape(str, opt_isLikelyToContainHtmlChars);\r\n if (goog.string.DETECT_DOUBLE_ESCAPING) {\r\n str = str.replace(goog.string.E_RE_, 'e');\r\n }\r\n return str;\r\n};\r\n\r\n\r\n/**\r\n * Regular expression that matches a lowercase letter \"e\", for use in escaping.\r\n * @const {!RegExp}\r\n * @private\r\n */\r\ngoog.string.E_RE_ = /e/g;\r\n\r\n\r\n/**\r\n * Unescapes an HTML string.\r\n *\r\n * @param {string} str The string to unescape.\r\n * @return {string} An unescaped copy of `str`.\r\n */\r\ngoog.string.unescapeEntities = function(str) {\r\n if (goog.string.contains(str, '&')) {\r\n // We are careful not to use a DOM if we do not have one or we explicitly\r\n // requested non-DOM html unescaping.\r\n if (!goog.string.FORCE_NON_DOM_HTML_UNESCAPING &&\r\n 'document' in goog.global) {\r\n return goog.string.unescapeEntitiesUsingDom_(str);\r\n } else {\r\n // Fall back on pure XML entities\r\n return goog.string.unescapePureXmlEntities_(str);\r\n }\r\n }\r\n return str;\r\n};\r\n\r\n\r\n/**\r\n * Unescapes a HTML string using the provided document.\r\n *\r\n * @param {string} str The string to unescape.\r\n * @param {!Document} document A document to use in escaping the string.\r\n * @return {string} An unescaped copy of `str`.\r\n */\r\ngoog.string.unescapeEntitiesWithDocument = function(str, document) {\r\n if (goog.string.contains(str, '&')) {\r\n return goog.string.unescapeEntitiesUsingDom_(str, document);\r\n }\r\n return str;\r\n};\r\n\r\n\r\n/**\r\n * Unescapes an HTML string using a DOM to resolve non-XML, non-numeric\r\n * entities. This function is XSS-safe and whitespace-preserving.\r\n * @private\r\n * @param {string} str The string to unescape.\r\n * @param {Document=} opt_document An optional document to use for creating\r\n * elements. If this is not specified then the default window.document\r\n * will be used.\r\n * @return {string} The unescaped `str` string.\r\n */\r\ngoog.string.unescapeEntitiesUsingDom_ = function(str, opt_document) {\r\n /** @type {!Object<string, string>} */\r\n var seen = {'&': '&', '<': '<', '>': '>', '"': '\"'};\r\n /** @type {!Element} */\r\n var div;\r\n if (opt_document) {\r\n div = opt_document.createElement('div');\r\n } else {\r\n div = goog.global.document.createElement('div');\r\n }\r\n // Match as many valid entity characters as possible. If the actual entity\r\n // happens to be shorter, it will still work as innerHTML will return the\r\n // trailing characters unchanged. Since the entity characters do not include\r\n // open angle bracket, there is no chance of XSS from the innerHTML use.\r\n // Since no whitespace is passed to innerHTML, whitespace is preserved.\r\n return str.replace(goog.string.HTML_ENTITY_PATTERN_, function(s, entity) {\r\n // Check for cached entity.\r\n var value = seen[s];\r\n if (value) {\r\n return value;\r\n }\r\n // Check for numeric entity.\r\n if (entity.charAt(0) == '#') {\r\n // Prefix with 0 so that hex entities (e.g. ) parse as hex numbers.\r\n var n = Number('0' + entity.substr(1));\r\n if (!isNaN(n)) {\r\n value = String.fromCharCode(n);\r\n }\r\n }\r\n // Fall back to innerHTML otherwise.\r\n if (!value) {\r\n // Append a non-entity character to avoid a bug in Webkit that parses\r\n // an invalid entity at the end of innerHTML text as the empty string.\r\n div.innerHTML = s + ' ';\r\n // Then remove the trailing character from the result.\r\n value = div.firstChild.nodeValue.slice(0, -1);\r\n }\r\n // Cache and return.\r\n return seen[s] = value;\r\n });\r\n};\r\n\r\n\r\n/**\r\n * Unescapes XML entities.\r\n * @private\r\n * @param {string} str The string to unescape.\r\n * @return {string} An unescaped copy of `str`.\r\n */\r\ngoog.string.unescapePureXmlEntities_ = function(str) {\r\n return str.replace(/&([^;]+);/g, function(s, entity) {\r\n switch (entity) {\r\n case 'amp':\r\n return '&';\r\n case 'lt':\r\n return '<';\r\n case 'gt':\r\n return '>';\r\n case 'quot':\r\n return '\"';\r\n default:\r\n if (entity.charAt(0) == '#') {\r\n // Prefix with 0 so that hex entities (e.g. ) parse as hex.\r\n var n = Number('0' + entity.substr(1));\r\n if (!isNaN(n)) {\r\n return String.fromCharCode(n);\r\n }\r\n }\r\n // For invalid entities we just return the entity\r\n return s;\r\n }\r\n });\r\n};\r\n\r\n\r\n/**\r\n * Regular expression that matches an HTML entity.\r\n * See also HTML5: Tokenization / Tokenizing character references.\r\n * @private\r\n * @type {!RegExp}\r\n */\r\ngoog.string.HTML_ENTITY_PATTERN_ = /&([^;\\s<&]+);?/g;\r\n\r\n\r\n/**\r\n * Do escaping of whitespace to preserve spatial formatting. We use character\r\n * entity #160 to make it safer for xml.\r\n * @param {string} str The string in which to escape whitespace.\r\n * @param {boolean=} opt_xml Whether to use XML compatible tags.\r\n * @return {string} An escaped copy of `str`.\r\n */\r\ngoog.string.whitespaceEscape = function(str, opt_xml) {\r\n // This doesn't use goog.string.preserveSpaces for backwards compatibility.\r\n return goog.string.newLineToBr(str.replace(/ /g, '  '), opt_xml);\r\n};\r\n\r\n\r\n/**\r\n * Preserve spaces that would be otherwise collapsed in HTML by replacing them\r\n * with non-breaking space Unicode characters.\r\n * @param {string} str The string in which to preserve whitespace.\r\n * @return {string} A copy of `str` with preserved whitespace.\r\n */\r\ngoog.string.preserveSpaces = function(str) {\r\n return str.replace(/(^|[\\n ]) /g, '$1' + goog.string.Unicode.NBSP);\r\n};\r\n\r\n\r\n/**\r\n * Strip quote characters around a string. The second argument is a string of\r\n * characters to treat as quotes. This can be a single character or a string of\r\n * multiple character and in that case each of those are treated as possible\r\n * quote characters. For example:\r\n *\r\n * <pre>\r\n * goog.string.stripQuotes('\"abc\"', '\"`') --> 'abc'\r\n * goog.string.stripQuotes('`abc`', '\"`') --> 'abc'\r\n * </pre>\r\n *\r\n * @param {string} str The string to strip.\r\n * @param {string} quoteChars The quote characters to strip.\r\n * @return {string} A copy of `str` without the quotes.\r\n */\r\ngoog.string.stripQuotes = function(str, quoteChars) {\r\n var length = quoteChars.length;\r\n for (var i = 0; i < length; i++) {\r\n var quoteChar = length == 1 ? quoteChars : quoteChars.charAt(i);\r\n if (str.charAt(0) == quoteChar && str.charAt(str.length - 1) == quoteChar) {\r\n return str.substring(1, str.length - 1);\r\n }\r\n }\r\n return str;\r\n};\r\n\r\n\r\n/**\r\n * Truncates a string to a certain length and adds '...' if necessary. The\r\n * length also accounts for the ellipsis, so a maximum length of 10 and a string\r\n * 'Hello World!' produces 'Hello W...'.\r\n * @param {string} str The string to truncate.\r\n * @param {number} chars Max number of characters.\r\n * @param {boolean=} opt_protectEscapedCharacters Whether to protect escaped\r\n * characters from being cut off in the middle.\r\n * @return {string} The truncated `str` string.\r\n */\r\ngoog.string.truncate = function(str, chars, opt_protectEscapedCharacters) {\r\n if (opt_protectEscapedCharacters) {\r\n str = goog.string.unescapeEntities(str);\r\n }\r\n\r\n if (str.length > chars) {\r\n str = str.substring(0, chars - 3) + '...';\r\n }\r\n\r\n if (opt_protectEscapedCharacters) {\r\n str = goog.string.htmlEscape(str);\r\n }\r\n\r\n return str;\r\n};\r\n\r\n\r\n/**\r\n * Truncate a string in the middle, adding \"...\" if necessary,\r\n * and favoring the beginning of the string.\r\n * @param {string} str The string to truncate the middle of.\r\n * @param {number} chars Max number of characters.\r\n * @param {boolean=} opt_protectEscapedCharacters Whether to protect escaped\r\n * characters from being cutoff in the middle.\r\n * @param {number=} opt_trailingChars Optional number of trailing characters to\r\n * leave at the end of the string, instead of truncating as close to the\r\n * middle as possible.\r\n * @return {string} A truncated copy of `str`.\r\n */\r\ngoog.string.truncateMiddle = function(\r\n str, chars, opt_protectEscapedCharacters, opt_trailingChars) {\r\n if (opt_protectEscapedCharacters) {\r\n str = goog.string.unescapeEntities(str);\r\n }\r\n\r\n if (opt_trailingChars && str.length > chars) {\r\n if (opt_trailingChars > chars) {\r\n opt_trailingChars = chars;\r\n }\r\n var endPoint = str.length - opt_trailingChars;\r\n var startPoint = chars - opt_trailingChars;\r\n str = str.substring(0, startPoint) + '...' + str.substring(endPoint);\r\n } else if (str.length > chars) {\r\n // Favor the beginning of the string:\r\n var half = Math.floor(chars / 2);\r\n var endPos = str.length - half;\r\n half += chars % 2;\r\n str = str.substring(0, half) + '...' + str.substring(endPos);\r\n }\r\n\r\n if (opt_protectEscapedCharacters) {\r\n str = goog.string.htmlEscape(str);\r\n }\r\n\r\n return str;\r\n};\r\n\r\n\r\n/**\r\n * Special chars that need to be escaped for goog.string.quote.\r\n * @private {!Object<string, string>}\r\n */\r\ngoog.string.specialEscapeChars_ = {\r\n '\\0': '\\\\0',\r\n '\\b': '\\\\b',\r\n '\\f': '\\\\f',\r\n '\\n': '\\\\n',\r\n '\\r': '\\\\r',\r\n '\\t': '\\\\t',\r\n '\\x0B': '\\\\x0B', // '\\v' is not supported in JScript\r\n '\"': '\\\\\"',\r\n '\\\\': '\\\\\\\\',\r\n // To support the use case of embedding quoted strings inside of script\r\n // tags, we have to make sure HTML comments and opening/closing script tags do\r\n // not appear in the resulting string. The specific strings that must be\r\n // escaped are documented at:\r\n // http://www.w3.org/TR/html51/semantics.html#restrictions-for-contents-of-script-elements\r\n '<': '\\x3c'\r\n};\r\n\r\n\r\n/**\r\n * Character mappings used internally for goog.string.escapeChar.\r\n * @private {!Object<string, string>}\r\n */\r\ngoog.string.jsEscapeCache_ = {\r\n '\\'': '\\\\\\''\r\n};\r\n\r\n\r\n/**\r\n * Encloses a string in double quotes and escapes characters so that the\r\n * string is a valid JS string. The resulting string is safe to embed in\r\n * `<script>` tags as \"<\" is escaped.\r\n * @param {string} s The string to quote.\r\n * @return {string} A copy of `s` surrounded by double quotes.\r\n */\r\ngoog.string.quote = function(s) {\r\n s = String(s);\r\n var sb = ['\"'];\r\n for (var i = 0; i < s.length; i++) {\r\n var ch = s.charAt(i);\r\n var cc = ch.charCodeAt(0);\r\n sb[i + 1] = goog.string.specialEscapeChars_[ch] ||\r\n ((cc > 31 && cc < 127) ? ch : goog.string.escapeChar(ch));\r\n }\r\n sb.push('\"');\r\n return sb.join('');\r\n};\r\n\r\n\r\n/**\r\n * Takes a string and returns the escaped string for that input string.\r\n * @param {string} str The string to escape.\r\n * @return {string} An escaped string representing `str`.\r\n */\r\ngoog.string.escapeString = function(str) {\r\n var sb = [];\r\n for (var i = 0; i < str.length; i++) {\r\n sb[i] = goog.string.escapeChar(str.charAt(i));\r\n }\r\n return sb.join('');\r\n};\r\n\r\n\r\n/**\r\n * Takes a character and returns the escaped string for that character. For\r\n * example escapeChar(String.fromCharCode(15)) -> \"\\\\x0E\".\r\n * @param {string} c The character to escape.\r\n * @return {string} An escaped string representing `c`.\r\n */\r\ngoog.string.escapeChar = function(c) {\r\n if (c in goog.string.jsEscapeCache_) {\r\n return goog.string.jsEscapeCache_[c];\r\n }\r\n\r\n if (c in goog.string.specialEscapeChars_) {\r\n return goog.string.jsEscapeCache_[c] = goog.string.specialEscapeChars_[c];\r\n }\r\n\r\n var rv = c;\r\n var cc = c.charCodeAt(0);\r\n if (cc > 31 && cc < 127) {\r\n rv = c;\r\n } else {\r\n // tab is 9 but handled above\r\n if (cc < 256) {\r\n rv = '\\\\x';\r\n if (cc < 16 || cc > 256) {\r\n rv += '0';\r\n }\r\n } else {\r\n rv = '\\\\u';\r\n if (cc < 4096) { // \\u1000\r\n rv += '0';\r\n }\r\n }\r\n rv += cc.toString(16).toUpperCase();\r\n }\r\n\r\n return goog.string.jsEscapeCache_[c] = rv;\r\n};\r\n\r\n\r\n/**\r\n * Determines whether a string contains a substring.\r\n * @param {string} str The string to search.\r\n * @param {string} subString The substring to search for.\r\n * @return {boolean} Whether `str` contains `subString`.\r\n */\r\ngoog.string.contains = goog.string.internal.contains;\r\n\r\n\r\n/**\r\n * Determines whether a string contains a substring, ignoring case.\r\n * @param {string} str The string to search.\r\n * @param {string} subString The substring to search for.\r\n * @return {boolean} Whether `str` contains `subString`.\r\n */\r\ngoog.string.caseInsensitiveContains =\r\n goog.string.internal.caseInsensitiveContains;\r\n\r\n\r\n/**\r\n * Returns the non-overlapping occurrences of ss in s.\r\n * If either s or ss evalutes to false, then returns zero.\r\n * @param {string} s The string to look in.\r\n * @param {string} ss The string to look for.\r\n * @return {number} Number of occurrences of ss in s.\r\n */\r\ngoog.string.countOf = function(s, ss) {\r\n return s && ss ? s.split(ss).length - 1 : 0;\r\n};\r\n\r\n\r\n/**\r\n * Removes a substring of a specified length at a specific\r\n * index in a string.\r\n * @param {string} s The base string from which to remove.\r\n * @param {number} index The index at which to remove the substring.\r\n * @param {number} stringLength The length of the substring to remove.\r\n * @return {string} A copy of `s` with the substring removed or the full\r\n * string if nothing is removed or the input is invalid.\r\n */\r\ngoog.string.removeAt = function(s, index, stringLength) {\r\n var resultStr = s;\r\n // If the index is greater or equal to 0 then remove substring\r\n if (index >= 0 && index < s.length && stringLength > 0) {\r\n resultStr = s.substr(0, index) +\r\n s.substr(index + stringLength, s.length - index - stringLength);\r\n }\r\n return resultStr;\r\n};\r\n\r\n\r\n/**\r\n * Removes the first occurrence of a substring from a string.\r\n * @param {string} str The base string from which to remove.\r\n * @param {string} substr The string to remove.\r\n * @return {string} A copy of `str` with `substr` removed or the\r\n * full string if nothing is removed.\r\n */\r\ngoog.string.remove = function(str, substr) {\r\n return str.replace(substr, '');\r\n};\r\n\r\n\r\n/**\r\n * Removes all occurrences of a substring from a string.\r\n * @param {string} s The base string from which to remove.\r\n * @param {string} ss The string to remove.\r\n * @return {string} A copy of `s` with `ss` removed or the full\r\n * string if nothing is removed.\r\n */\r\ngoog.string.removeAll = function(s, ss) {\r\n var re = new RegExp(goog.string.regExpEscape(ss), 'g');\r\n return s.replace(re, '');\r\n};\r\n\r\n\r\n/**\r\n * Replaces all occurrences of a substring of a string with a new substring.\r\n * @param {string} s The base string from which to remove.\r\n * @param {string} ss The string to replace.\r\n * @param {string} replacement The replacement string.\r\n * @return {string} A copy of `s` with `ss` replaced by\r\n * `replacement` or the original string if nothing is replaced.\r\n */\r\ngoog.string.replaceAll = function(s, ss, replacement) {\r\n var re = new RegExp(goog.string.regExpEscape(ss), 'g');\r\n return s.replace(re, replacement.replace(/\\$/g, '$$$$'));\r\n};\r\n\r\n\r\n/**\r\n * Escapes characters in the string that are not safe to use in a RegExp.\r\n * @param {*} s The string to escape. If not a string, it will be casted\r\n * to one.\r\n * @return {string} A RegExp safe, escaped copy of `s`.\r\n */\r\ngoog.string.regExpEscape = function(s) {\r\n return String(s)\r\n .replace(/([-()\\[\\]{}+?*.$\\^|,:#<!\\\\])/g, '\\\\$1')\r\n .replace(/\\x08/g, '\\\\x08');\r\n};\r\n\r\n\r\n/**\r\n * Repeats a string n times.\r\n * @param {string} string The string to repeat.\r\n * @param {number} length The number of times to repeat.\r\n * @return {string} A string containing `length` repetitions of\r\n * `string`.\r\n */\r\ngoog.string.repeat = (String.prototype.repeat) ? function(string, length) {\r\n // The native method is over 100 times faster than the alternative.\r\n return string.repeat(length);\r\n} : function(string, length) {\r\n return new Array(length + 1).join(string);\r\n};\r\n\r\n\r\n/**\r\n * Pads number to given length and optionally rounds it to a given precision.\r\n * For example:\r\n * <pre>padNumber(1.25, 2, 3) -> '01.250'\r\n * padNumber(1.25, 2) -> '01.25'\r\n * padNumber(1.25, 2, 1) -> '01.3'\r\n * padNumber(1.25, 0) -> '1.25'</pre>\r\n *\r\n * @param {number} num The number to pad.\r\n * @param {number} length The desired length.\r\n * @param {number=} opt_precision The desired precision.\r\n * @return {string} `num` as a string with the given options.\r\n */\r\ngoog.string.padNumber = function(num, length, opt_precision) {\r\n var s = goog.isDef(opt_precision) ? num.toFixed(opt_precision) : String(num);\r\n var index = s.indexOf('.');\r\n if (index == -1) {\r\n index = s.length;\r\n }\r\n return goog.string.repeat('0', Math.max(0, length - index)) + s;\r\n};\r\n\r\n\r\n/**\r\n * Returns a string representation of the given object, with\r\n * null and undefined being returned as the empty string.\r\n *\r\n * @param {*} obj The object to convert.\r\n * @return {string} A string representation of the `obj`.\r\n */\r\ngoog.string.makeSafe = function(obj) {\r\n return obj == null ? '' : String(obj);\r\n};\r\n\r\n\r\n/**\r\n * Concatenates string expressions. This is useful\r\n * since some browsers are very inefficient when it comes to using plus to\r\n * concat strings. Be careful when using null and undefined here since\r\n * these will not be included in the result. If you need to represent these\r\n * be sure to cast the argument to a String first.\r\n * For example:\r\n * <pre>buildString('a', 'b', 'c', 'd') -> 'abcd'\r\n * buildString(null, undefined) -> ''\r\n * </pre>\r\n * @param {...*} var_args A list of strings to concatenate. If not a string,\r\n * it will be casted to one.\r\n * @return {string} The concatenation of `var_args`.\r\n */\r\ngoog.string.buildString = function(var_args) {\r\n return Array.prototype.join.call(arguments, '');\r\n};\r\n\r\n\r\n/**\r\n * Returns a string with at least 64-bits of randomness.\r\n *\r\n * Doesn't trust JavaScript's random function entirely. Uses a combination of\r\n * random and current timestamp, and then encodes the string in base-36 to\r\n * make it shorter.\r\n *\r\n * @return {string} A random string, e.g. sn1s7vb4gcic.\r\n */\r\ngoog.string.getRandomString = function() {\r\n var x = 2147483648;\r\n return Math.floor(Math.random() * x).toString(36) +\r\n Math.abs(Math.floor(Math.random() * x) ^ goog.now()).toString(36);\r\n};\r\n\r\n\r\n/**\r\n * Compares two version numbers.\r\n *\r\n * @param {string|number} version1 Version of first item.\r\n * @param {string|number} version2 Version of second item.\r\n *\r\n * @return {number} 1 if `version1` is higher.\r\n * 0 if arguments are equal.\r\n * -1 if `version2` is higher.\r\n */\r\ngoog.string.compareVersions = goog.string.internal.compareVersions;\r\n\r\n\r\n/**\r\n * String hash function similar to java.lang.String.hashCode().\r\n * The hash code for a string is computed as\r\n * s[0] * 31 ^ (n - 1) + s[1] * 31 ^ (n - 2) + ... + s[n - 1],\r\n * where s[i] is the ith character of the string and n is the length of\r\n * the string. We mod the result to make it between 0 (inclusive) and 2^32\r\n * (exclusive).\r\n * @param {string} str A string.\r\n * @return {number} Hash value for `str`, between 0 (inclusive) and 2^32\r\n * (exclusive). The empty string returns 0.\r\n */\r\ngoog.string.hashCode = function(str) {\r\n var result = 0;\r\n for (var i = 0; i < str.length; ++i) {\r\n // Normalize to 4 byte range, 0 ... 2^32.\r\n result = (31 * result + str.charCodeAt(i)) >>> 0;\r\n }\r\n return result;\r\n};\r\n\r\n\r\n/**\r\n * The most recent unique ID. |0 is equivalent to Math.floor in this case.\r\n * @type {number}\r\n * @private\r\n */\r\ngoog.string.uniqueStringCounter_ = Math.random() * 0x80000000 | 0;\r\n\r\n\r\n/**\r\n * Generates and returns a string which is unique in the current document.\r\n * This is useful, for example, to create unique IDs for DOM elements.\r\n * @return {string} A unique id.\r\n */\r\ngoog.string.createUniqueString = function() {\r\n return 'goog_' + goog.string.uniqueStringCounter_++;\r\n};\r\n\r\n\r\n/**\r\n * Converts the supplied string to a number, which may be Infinity or NaN.\r\n * This function strips whitespace: (toNumber(' 123') === 123)\r\n * This function accepts scientific notation: (toNumber('1e1') === 10)\r\n *\r\n * This is better than JavaScript's built-in conversions because, sadly:\r\n * (Number(' ') === 0) and (parseFloat('123a') === 123)\r\n *\r\n * @param {string} str The string to convert.\r\n * @return {number} The number the supplied string represents, or NaN.\r\n */\r\ngoog.string.toNumber = function(str) {\r\n var num = Number(str);\r\n if (num == 0 && goog.string.isEmptyOrWhitespace(str)) {\r\n return NaN;\r\n }\r\n return num;\r\n};\r\n\r\n\r\n/**\r\n * Returns whether the given string is lower camel case (e.g. \"isFooBar\").\r\n *\r\n * Note that this assumes the string is entirely letters.\r\n * @see http://en.wikipedia.org/wiki/CamelCase#Variations_and_synonyms\r\n *\r\n * @param {string} str String to test.\r\n * @return {boolean} Whether the string is lower camel case.\r\n */\r\ngoog.string.isLowerCamelCase = function(str) {\r\n return /^[a-z]+([A-Z][a-z]*)*$/.test(str);\r\n};\r\n\r\n\r\n/**\r\n * Returns whether the given string is upper camel case (e.g. \"FooBarBaz\").\r\n *\r\n * Note that this assumes the string is entirely letters.\r\n * @see http://en.wikipedia.org/wiki/CamelCase#Variations_and_synonyms\r\n *\r\n * @param {string} str String to test.\r\n * @return {boolean} Whether the string is upper camel case.\r\n */\r\ngoog.string.isUpperCamelCase = function(str) {\r\n return /^([A-Z][a-z]*)+$/.test(str);\r\n};\r\n\r\n\r\n/**\r\n * Converts a string from selector-case to camelCase (e.g. from\r\n * \"multi-part-string\" to \"multiPartString\"), useful for converting\r\n * CSS selectors and HTML dataset keys to their equivalent JS properties.\r\n * @param {string} str The string in selector-case form.\r\n * @return {string} The string in camelCase form.\r\n */\r\ngoog.string.toCamelCase = function(str) {\r\n return String(str).replace(/\\-([a-z])/g, function(all, match) {\r\n return match.toUpperCase();\r\n });\r\n};\r\n\r\n\r\n/**\r\n * Converts a string from camelCase to selector-case (e.g. from\r\n * \"multiPartString\" to \"multi-part-string\"), useful for converting JS\r\n * style and dataset properties to equivalent CSS selectors and HTML keys.\r\n * @param {string} str The string in camelCase form.\r\n * @return {string} The string in selector-case form.\r\n */\r\ngoog.string.toSelectorCase = function(str) {\r\n return String(str).replace(/([A-Z])/g, '-$1').toLowerCase();\r\n};\r\n\r\n\r\n/**\r\n * Converts a string into TitleCase. First character of the string is always\r\n * capitalized in addition to the first letter of every subsequent word.\r\n * Words are delimited by one or more whitespaces by default. Custom delimiters\r\n * can optionally be specified to replace the default, which doesn't preserve\r\n * whitespace delimiters and instead must be explicitly included if needed.\r\n *\r\n * Default delimiter => \" \":\r\n * goog.string.toTitleCase('oneTwoThree') => 'OneTwoThree'\r\n * goog.string.toTitleCase('one two three') => 'One Two Three'\r\n * goog.string.toTitleCase(' one two ') => ' One Two '\r\n * goog.string.toTitleCase('one_two_three') => 'One_two_three'\r\n * goog.string.toTitleCase('one-two-three') => 'One-two-three'\r\n *\r\n * Custom delimiter => \"_-.\":\r\n * goog.string.toTitleCase('oneTwoThree', '_-.') => 'OneTwoThree'\r\n * goog.string.toTitleCase('one two three', '_-.') => 'One two three'\r\n * goog.string.toTitleCase(' one two ', '_-.') => ' one two '\r\n * goog.string.toTitleCase('one_two_three', '_-.') => 'One_Two_Three'\r\n * goog.string.toTitleCase('one-two-three', '_-.') => 'One-Two-Three'\r\n * goog.string.toTitleCase('one...two...three', '_-.') => 'One...Two...Three'\r\n * goog.string.toTitleCase('one. two. three', '_-.') => 'One. two. three'\r\n * goog.string.toTitleCase('one-two.three', '_-.') => 'One-Two.Three'\r\n *\r\n * @param {string} str String value in camelCase form.\r\n * @param {string=} opt_delimiters Custom delimiter character set used to\r\n * distinguish words in the string value. Each character represents a\r\n * single delimiter. When provided, default whitespace delimiter is\r\n * overridden and must be explicitly included if needed.\r\n * @return {string} String value in TitleCase form.\r\n */\r\ngoog.string.toTitleCase = function(str, opt_delimiters) {\r\n var delimiters = goog.isString(opt_delimiters) ?\r\n goog.string.regExpEscape(opt_delimiters) :\r\n '\\\\s';\r\n\r\n // For IE8, we need to prevent using an empty character set. Otherwise,\r\n // incorrect matching will occur.\r\n delimiters = delimiters ? '|[' + delimiters + ']+' : '';\r\n\r\n var regexp = new RegExp('(^' + delimiters + ')([a-z])', 'g');\r\n return str.replace(regexp, function(all, p1, p2) {\r\n return p1 + p2.toUpperCase();\r\n });\r\n};\r\n\r\n\r\n/**\r\n * Capitalizes a string, i.e. converts the first letter to uppercase\r\n * and all other letters to lowercase, e.g.:\r\n *\r\n * goog.string.capitalize('one') => 'One'\r\n * goog.string.capitalize('ONE') => 'One'\r\n * goog.string.capitalize('one two') => 'One two'\r\n *\r\n * Note that this function does not trim initial whitespace.\r\n *\r\n * @param {string} str String value to capitalize.\r\n * @return {string} String value with first letter in uppercase.\r\n */\r\ngoog.string.capitalize = function(str) {\r\n return String(str.charAt(0)).toUpperCase() +\r\n String(str.substr(1)).toLowerCase();\r\n};\r\n\r\n\r\n/**\r\n * Parse a string in decimal or hexidecimal ('0xFFFF') form.\r\n *\r\n * To parse a particular radix, please use parseInt(string, radix) directly. See\r\n * https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/parseInt\r\n *\r\n * This is a wrapper for the built-in parseInt function that will only parse\r\n * numbers as base 10 or base 16. Some JS implementations assume strings\r\n * starting with \"0\" are intended to be octal. ES3 allowed but discouraged\r\n * this behavior. ES5 forbids it. This function emulates the ES5 behavior.\r\n *\r\n * For more information, see Mozilla JS Reference: http://goo.gl/8RiFj\r\n *\r\n * @param {string|number|null|undefined} value The value to be parsed.\r\n * @return {number} The number, parsed. If the string failed to parse, this\r\n * will be NaN.\r\n */\r\ngoog.string.parseInt = function(value) {\r\n // Force finite numbers to strings.\r\n if (isFinite(value)) {\r\n value = String(value);\r\n }\r\n\r\n if (goog.isString(value)) {\r\n // If the string starts with '0x' or '-0x', parse as hex.\r\n return /^\\s*-?0x/i.test(value) ? parseInt(value, 16) : parseInt(value, 10);\r\n }\r\n\r\n return NaN;\r\n};\r\n\r\n\r\n/**\r\n * Splits a string on a separator a limited number of times.\r\n *\r\n * This implementation is more similar to Python or Java, where the limit\r\n * parameter specifies the maximum number of splits rather than truncating\r\n * the number of results.\r\n *\r\n * See http://docs.python.org/2/library/stdtypes.html#str.split\r\n * See JavaDoc: http://goo.gl/F2AsY\r\n * See Mozilla reference: http://goo.gl/dZdZs\r\n *\r\n * @param {string} str String to split.\r\n * @param {string} separator The separator.\r\n * @param {number} limit The limit to the number of splits. The resulting array\r\n * will have a maximum length of limit+1. Negative numbers are the same\r\n * as zero.\r\n * @return {!Array<string>} The string, split.\r\n */\r\ngoog.string.splitLimit = function(str, separator, limit) {\r\n var parts = str.split(separator);\r\n var returnVal = [];\r\n\r\n // Only continue doing this while we haven't hit the limit and we have\r\n // parts left.\r\n while (limit > 0 && parts.length) {\r\n returnVal.push(parts.shift());\r\n limit--;\r\n }\r\n\r\n // If there are remaining parts, append them to the end.\r\n if (parts.length) {\r\n returnVal.push(parts.join(separator));\r\n }\r\n\r\n return returnVal;\r\n};\r\n\r\n\r\n/**\r\n * Finds the characters to the right of the last instance of any separator\r\n *\r\n * This function is similar to goog.string.path.baseName, except it can take a\r\n * list of characters to split the string on. It will return the rightmost\r\n * grouping of characters to the right of any separator as a left-to-right\r\n * oriented string.\r\n *\r\n * @see goog.string.path.baseName\r\n * @param {string} str The string\r\n * @param {string|!Array<string>} separators A list of separator characters\r\n * @return {string} The last part of the string with respect to the separators\r\n */\r\ngoog.string.lastComponent = function(str, separators) {\r\n if (!separators) {\r\n return str;\r\n } else if (typeof separators == 'string') {\r\n separators = [separators];\r\n }\r\n\r\n var lastSeparatorIndex = -1;\r\n for (var i = 0; i < separators.length; i++) {\r\n if (separators[i] == '') {\r\n continue;\r\n }\r\n var currentSeparatorIndex = str.lastIndexOf(separators[i]);\r\n if (currentSeparatorIndex > lastSeparatorIndex) {\r\n lastSeparatorIndex = currentSeparatorIndex;\r\n }\r\n }\r\n if (lastSeparatorIndex == -1) {\r\n return str;\r\n }\r\n return str.slice(lastSeparatorIndex + 1);\r\n};\r\n\r\n\r\n/**\r\n * Computes the Levenshtein edit distance between two strings.\r\n * @param {string} a\r\n * @param {string} b\r\n * @return {number} The edit distance between the two strings.\r\n */\r\ngoog.string.editDistance = function(a, b) {\r\n var v0 = [];\r\n var v1 = [];\r\n\r\n if (a == b) {\r\n return 0;\r\n }\r\n\r\n if (!a.length || !b.length) {\r\n return Math.max(a.length, b.length);\r\n }\r\n\r\n for (var i = 0; i < b.length + 1; i++) {\r\n v0[i] = i;\r\n }\r\n\r\n for (var i = 0; i < a.length; i++) {\r\n v1[0] = i + 1;\r\n\r\n for (var j = 0; j < b.length; j++) {\r\n var cost = Number(a[i] != b[j]);\r\n // Cost for the substring is the minimum of adding one character, removing\r\n // one character, or a swap.\r\n v1[j + 1] = Math.min(v1[j] + 1, v0[j + 1] + 1, v0[j] + cost);\r\n }\r\n\r\n for (var j = 0; j < v0.length; j++) {\r\n v0[j] = v1[j];\r\n }\r\n }\r\n\r\n return v1[b.length];\r\n};\r\n","// Copyright 2006 The Closure Library Authors. All Rights Reserved.\r\n//\r\n// Licensed under the Apache License, Version 2.0 (the \"License\");\r\n// you may not use this file except in compliance with the License.\r\n// You may obtain a copy of the License at\r\n//\r\n// http://www.apache.org/licenses/LICENSE-2.0\r\n//\r\n// Unless required by applicable law or agreed to in writing, software\r\n// distributed under the License is distributed on an \"AS-IS\" BASIS,\r\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n// See the License for the specific language governing permissions and\r\n// limitations under the License.\r\n\r\n/**\r\n * @fileoverview Generics method for collection-like classes and objects.\r\n *\r\n * @author arv@google.com (Erik Arvidsson)\r\n *\r\n * This file contains functions to work with collections. It supports using\r\n * Map, Set, Array and Object and other classes that implement collection-like\r\n * methods.\r\n * @suppress {strictMissingProperties}\r\n */\r\n\r\n\r\ngoog.provide('goog.structs');\r\n\r\ngoog.require('goog.array');\r\ngoog.require('goog.object');\r\n\r\n\r\n// We treat an object as a dictionary if it has getKeys or it is an object that\r\n// isn't arrayLike.\r\n\r\n\r\n/**\r\n * Returns the number of values in the collection-like object.\r\n * @param {Object} col The collection-like object.\r\n * @return {number} The number of values in the collection-like object.\r\n */\r\ngoog.structs.getCount = function(col) {\r\n if (col.getCount && typeof col.getCount == 'function') {\r\n return col.getCount();\r\n }\r\n if (goog.isArrayLike(col) || goog.isString(col)) {\r\n return col.length;\r\n }\r\n return goog.object.getCount(col);\r\n};\r\n\r\n\r\n/**\r\n * Returns the values of the collection-like object.\r\n * @param {Object} col The collection-like object.\r\n * @return {!Array<?>} The values in the collection-like object.\r\n */\r\ngoog.structs.getValues = function(col) {\r\n if (col.getValues && typeof col.getValues == 'function') {\r\n return col.getValues();\r\n }\r\n if (goog.isString(col)) {\r\n return col.split('');\r\n }\r\n if (goog.isArrayLike(col)) {\r\n var rv = [];\r\n var l = col.length;\r\n for (var i = 0; i < l; i++) {\r\n rv.push(col[i]);\r\n }\r\n return rv;\r\n }\r\n return goog.object.getValues(col);\r\n};\r\n\r\n\r\n/**\r\n * Returns the keys of the collection. Some collections have no notion of\r\n * keys/indexes and this function will return undefined in those cases.\r\n * @param {Object} col The collection-like object.\r\n * @return {!Array|undefined} The keys in the collection.\r\n */\r\ngoog.structs.getKeys = function(col) {\r\n if (col.getKeys && typeof col.getKeys == 'function') {\r\n return col.getKeys();\r\n }\r\n // if we have getValues but no getKeys we know this is a key-less collection\r\n if (col.getValues && typeof col.getValues == 'function') {\r\n return undefined;\r\n }\r\n if (goog.isArrayLike(col) || goog.isString(col)) {\r\n var rv = [];\r\n var l = col.length;\r\n for (var i = 0; i < l; i++) {\r\n rv.push(i);\r\n }\r\n return rv;\r\n }\r\n\r\n return goog.object.getKeys(col);\r\n};\r\n\r\n\r\n/**\r\n * Whether the collection contains the given value. This is O(n) and uses\r\n * equals (==) to test the existence.\r\n * @param {Object} col The collection-like object.\r\n * @param {*} val The value to check for.\r\n * @return {boolean} True if the map contains the value.\r\n */\r\ngoog.structs.contains = function(col, val) {\r\n if (col.contains && typeof col.contains == 'function') {\r\n return col.contains(val);\r\n }\r\n if (col.containsValue && typeof col.containsValue == 'function') {\r\n return col.containsValue(val);\r\n }\r\n if (goog.isArrayLike(col) || goog.isString(col)) {\r\n return goog.array.contains(/** @type {!Array<?>} */ (col), val);\r\n }\r\n return goog.object.containsValue(col, val);\r\n};\r\n\r\n\r\n/**\r\n * Whether the collection is empty.\r\n * @param {Object} col The collection-like object.\r\n * @return {boolean} True if empty.\r\n */\r\ngoog.structs.isEmpty = function(col) {\r\n if (col.isEmpty && typeof col.isEmpty == 'function') {\r\n return col.isEmpty();\r\n }\r\n\r\n // We do not use goog.string.isEmptyOrWhitespace because here we treat the\r\n // string as\r\n // collection and as such even whitespace matters\r\n\r\n if (goog.isArrayLike(col) || goog.isString(col)) {\r\n return goog.array.isEmpty(/** @type {!Array<?>} */ (col));\r\n }\r\n return goog.object.isEmpty(col);\r\n};\r\n\r\n\r\n/**\r\n * Removes all the elements from the collection.\r\n * @param {Object} col The collection-like object.\r\n */\r\ngoog.structs.clear = function(col) {\r\n // NOTE(arv): This should not contain strings because strings are immutable\r\n if (col.clear && typeof col.clear == 'function') {\r\n col.clear();\r\n } else if (goog.isArrayLike(col)) {\r\n goog.array.clear(/** @type {IArrayLike<?>} */ (col));\r\n } else {\r\n goog.object.clear(col);\r\n }\r\n};\r\n\r\n\r\n/**\r\n * Calls a function for each value in a collection. The function takes\r\n * three arguments; the value, the key and the collection.\r\n *\r\n * @param {S} col The collection-like object.\r\n * @param {function(this:T,?,?,S):?} f The function to call for every value.\r\n * This function takes\r\n * 3 arguments (the value, the key or undefined if the collection has no\r\n * notion of keys, and the collection) and the return value is irrelevant.\r\n * @param {T=} opt_obj The object to be used as the value of 'this'\r\n * within `f`.\r\n * @template T,S\r\n * @deprecated Use a more specific method, e.g. goog.array.forEach,\r\n * goog.object.forEach, or for-of.\r\n */\r\ngoog.structs.forEach = function(col, f, opt_obj) {\r\n if (col.forEach && typeof col.forEach == 'function') {\r\n col.forEach(f, opt_obj);\r\n } else if (goog.isArrayLike(col) || goog.isString(col)) {\r\n goog.array.forEach(/** @type {!Array<?>} */ (col), f, opt_obj);\r\n } else {\r\n var keys = goog.structs.getKeys(col);\r\n var values = goog.structs.getValues(col);\r\n var l = values.length;\r\n for (var i = 0; i < l; i++) {\r\n f.call(/** @type {?} */ (opt_obj), values[i], keys && keys[i], col);\r\n }\r\n }\r\n};\r\n\r\n\r\n/**\r\n * Calls a function for every value in the collection. When a call returns true,\r\n * adds the value to a new collection (Array is returned by default).\r\n *\r\n * @param {S} col The collection-like object.\r\n * @param {function(this:T,?,?,S):boolean} f The function to call for every\r\n * value. This function takes\r\n * 3 arguments (the value, the key or undefined if the collection has no\r\n * notion of keys, and the collection) and should return a Boolean. If the\r\n * return value is true the value is added to the result collection. If it\r\n * is false the value is not included.\r\n * @param {T=} opt_obj The object to be used as the value of 'this'\r\n * within `f`.\r\n * @return {!Object|!Array<?>} A new collection where the passed values are\r\n * present. If col is a key-less collection an array is returned. If col\r\n * has keys and values a plain old JS object is returned.\r\n * @template T,S\r\n */\r\ngoog.structs.filter = function(col, f, opt_obj) {\r\n if (typeof col.filter == 'function') {\r\n return col.filter(f, opt_obj);\r\n }\r\n if (goog.isArrayLike(col) || goog.isString(col)) {\r\n return goog.array.filter(/** @type {!Array<?>} */ (col), f, opt_obj);\r\n }\r\n\r\n var rv;\r\n var keys = goog.structs.getKeys(col);\r\n var values = goog.structs.getValues(col);\r\n var l = values.length;\r\n if (keys) {\r\n rv = {};\r\n for (var i = 0; i < l; i++) {\r\n if (f.call(/** @type {?} */ (opt_obj), values[i], keys[i], col)) {\r\n rv[keys[i]] = values[i];\r\n }\r\n }\r\n } else {\r\n // We should not use goog.array.filter here since we want to make sure that\r\n // the index is undefined as well as make sure that col is passed to the\r\n // function.\r\n rv = [];\r\n for (var i = 0; i < l; i++) {\r\n if (f.call(opt_obj, values[i], undefined, col)) {\r\n rv.push(values[i]);\r\n }\r\n }\r\n }\r\n return rv;\r\n};\r\n\r\n\r\n/**\r\n * Calls a function for every value in the collection and adds the result into a\r\n * new collection (defaults to creating a new Array).\r\n *\r\n * @param {S} col The collection-like object.\r\n * @param {function(this:T,?,?,S):V} f The function to call for every value.\r\n * This function takes 3 arguments (the value, the key or undefined if the\r\n * collection has no notion of keys, and the collection) and should return\r\n * something. The result will be used as the value in the new collection.\r\n * @param {T=} opt_obj The object to be used as the value of 'this'\r\n * within `f`.\r\n * @return {!Object<V>|!Array<V>} A new collection with the new values. If\r\n * col is a key-less collection an array is returned. If col has keys and\r\n * values a plain old JS object is returned.\r\n * @template T,S,V\r\n */\r\ngoog.structs.map = function(col, f, opt_obj) {\r\n if (typeof col.map == 'function') {\r\n return col.map(f, opt_obj);\r\n }\r\n if (goog.isArrayLike(col) || goog.isString(col)) {\r\n return goog.array.map(/** @type {!Array<?>} */ (col), f, opt_obj);\r\n }\r\n\r\n var rv;\r\n var keys = goog.structs.getKeys(col);\r\n var values = goog.structs.getValues(col);\r\n var l = values.length;\r\n if (keys) {\r\n rv = {};\r\n for (var i = 0; i < l; i++) {\r\n rv[keys[i]] = f.call(/** @type {?} */ (opt_obj), values[i], keys[i], col);\r\n }\r\n } else {\r\n // We should not use goog.array.map here since we want to make sure that\r\n // the index is undefined as well as make sure that col is passed to the\r\n // function.\r\n rv = [];\r\n for (var i = 0; i < l; i++) {\r\n rv[i] = f.call(/** @type {?} */ (opt_obj), values[i], undefined, col);\r\n }\r\n }\r\n return rv;\r\n};\r\n\r\n\r\n/**\r\n * Calls f for each value in a collection. If any call returns true this returns\r\n * true (without checking the rest). If all returns false this returns false.\r\n *\r\n * @param {S} col The collection-like object.\r\n * @param {function(this:T,?,?,S):boolean} f The function to call for every\r\n * value. This function takes 3 arguments (the value, the key or undefined\r\n * if the collection has no notion of keys, and the collection) and should\r\n * return a boolean.\r\n * @param {T=} opt_obj The object to be used as the value of 'this'\r\n * within `f`.\r\n * @return {boolean} True if any value passes the test.\r\n * @template T,S\r\n */\r\ngoog.structs.some = function(col, f, opt_obj) {\r\n if (typeof col.some == 'function') {\r\n return col.some(f, opt_obj);\r\n }\r\n if (goog.isArrayLike(col) || goog.isString(col)) {\r\n return goog.array.some(/** @type {!Array<?>} */ (col), f, opt_obj);\r\n }\r\n var keys = goog.structs.getKeys(col);\r\n var values = goog.structs.getValues(col);\r\n var l = values.length;\r\n for (var i = 0; i < l; i++) {\r\n if (f.call(/** @type {?} */ (opt_obj), values[i], keys && keys[i], col)) {\r\n return true;\r\n }\r\n }\r\n return false;\r\n};\r\n\r\n\r\n/**\r\n * Calls f for each value in a collection. If all calls return true this return\r\n * true this returns true. If any returns false this returns false at this point\r\n * and does not continue to check the remaining values.\r\n *\r\n * @param {S} col The collection-like object.\r\n * @param {function(this:T,?,?,S):boolean} f The function to call for every\r\n * value. This function takes 3 arguments (the value, the key or\r\n * undefined if the collection has no notion of keys, and the collection)\r\n * and should return a boolean.\r\n * @param {T=} opt_obj The object to be used as the value of 'this'\r\n * within `f`.\r\n * @return {boolean} True if all key-value pairs pass the test.\r\n * @template T,S\r\n */\r\ngoog.structs.every = function(col, f, opt_obj) {\r\n if (typeof col.every == 'function') {\r\n return col.every(f, opt_obj);\r\n }\r\n if (goog.isArrayLike(col) || goog.isString(col)) {\r\n return goog.array.every(/** @type {!Array<?>} */ (col), f, opt_obj);\r\n }\r\n var keys = goog.structs.getKeys(col);\r\n var values = goog.structs.getValues(col);\r\n var l = values.length;\r\n for (var i = 0; i < l; i++) {\r\n if (!f.call(/** @type {?} */ (opt_obj), values[i], keys && keys[i], col)) {\r\n return false;\r\n }\r\n }\r\n return true;\r\n};\r\n","// Copyright 2006 The Closure Library Authors. All Rights Reserved.\r\n//\r\n// Licensed under the Apache License, Version 2.0 (the \"License\");\r\n// you may not use this file except in compliance with the License.\r\n// You may obtain a copy of the License at\r\n//\r\n// http://www.apache.org/licenses/LICENSE-2.0\r\n//\r\n// Unless required by applicable law or agreed to in writing, software\r\n// distributed under the License is distributed on an \"AS-IS\" BASIS,\r\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n// See the License for the specific language governing permissions and\r\n// limitations under the License.\r\n\r\n/**\r\n * @fileoverview Datastructure: Hash Map.\r\n *\r\n * @author arv@google.com (Erik Arvidsson)\r\n *\r\n * This file contains an implementation of a Map structure. It implements a lot\r\n * of the methods used in goog.structs so those functions work on hashes. This\r\n * is best suited for complex key types. For simple keys such as numbers and\r\n * strings consider using the lighter-weight utilities in goog.object.\r\n */\r\n\r\n\r\ngoog.provide('goog.structs.Map');\r\n\r\ngoog.require('goog.iter.Iterator');\r\ngoog.require('goog.iter.StopIteration');\r\n\r\n\r\n\r\n/**\r\n * Class for Hash Map datastructure.\r\n * @param {*=} opt_map Map or Object to initialize the map with.\r\n * @param {...*} var_args If 2 or more arguments are present then they\r\n * will be used as key-value pairs.\r\n * @constructor\r\n * @template K, V\r\n * @deprecated This type is misleading: use ES6 Map instead.\r\n */\r\ngoog.structs.Map = function(opt_map, var_args) {\r\n\r\n /**\r\n * Underlying JS object used to implement the map.\r\n * @private {!Object}\r\n */\r\n this.map_ = {};\r\n\r\n /**\r\n * An array of keys. This is necessary for two reasons:\r\n * 1. Iterating the keys using for (var key in this.map_) allocates an\r\n * object for every key in IE which is really bad for IE6 GC perf.\r\n * 2. Without a side data structure, we would need to escape all the keys\r\n * as that would be the only way we could tell during iteration if the\r\n * key was an internal key or a property of the object.\r\n *\r\n * This array can contain deleted keys so it's necessary to check the map\r\n * as well to see if the key is still in the map (this doesn't require a\r\n * memory allocation in IE).\r\n * @private {!Array<string>}\r\n */\r\n this.keys_ = [];\r\n\r\n /**\r\n * The number of key value pairs in the map.\r\n * @private {number}\r\n */\r\n this.count_ = 0;\r\n\r\n /**\r\n * Version used to detect changes while iterating.\r\n * @private {number}\r\n */\r\n this.version_ = 0;\r\n\r\n var argLength = arguments.length;\r\n\r\n if (argLength > 1) {\r\n if (argLength % 2) {\r\n throw new Error('Uneven number of arguments');\r\n }\r\n for (var i = 0; i < argLength; i += 2) {\r\n this.set(arguments[i], arguments[i + 1]);\r\n }\r\n } else if (opt_map) {\r\n this.addAll(/** @type {!Object} */ (opt_map));\r\n }\r\n};\r\n\r\n\r\n/**\r\n * @return {number} The number of key-value pairs in the map.\r\n */\r\ngoog.structs.Map.prototype.getCount = function() {\r\n return this.count_;\r\n};\r\n\r\n\r\n/**\r\n * Returns the values of the map.\r\n * @return {!Array<V>} The values in the map.\r\n */\r\ngoog.structs.Map.prototype.getValues = function() {\r\n this.cleanupKeysArray_();\r\n\r\n var rv = [];\r\n for (var i = 0; i < this.keys_.length; i++) {\r\n var key = this.keys_[i];\r\n rv.push(this.map_[key]);\r\n }\r\n return rv;\r\n};\r\n\r\n\r\n/**\r\n * Returns the keys of the map.\r\n * @return {!Array<string>} Array of string values.\r\n */\r\ngoog.structs.Map.prototype.getKeys = function() {\r\n this.cleanupKeysArray_();\r\n return /** @type {!Array<string>} */ (this.keys_.concat());\r\n};\r\n\r\n\r\n/**\r\n * Whether the map contains the given key.\r\n * @param {*} key The key to check for.\r\n * @return {boolean} Whether the map contains the key.\r\n */\r\ngoog.structs.Map.prototype.containsKey = function(key) {\r\n return goog.structs.Map.hasKey_(this.map_, key);\r\n};\r\n\r\n\r\n/**\r\n * Whether the map contains the given value. This is O(n).\r\n * @param {V} val The value to check for.\r\n * @return {boolean} Whether the map contains the value.\r\n */\r\ngoog.structs.Map.prototype.containsValue = function(val) {\r\n for (var i = 0; i < this.keys_.length; i++) {\r\n var key = this.keys_[i];\r\n if (goog.structs.Map.hasKey_(this.map_, key) && this.map_[key] == val) {\r\n return true;\r\n }\r\n }\r\n return false;\r\n};\r\n\r\n\r\n/**\r\n * Whether this map is equal to the argument map.\r\n * @param {goog.structs.Map} otherMap The map against which to test equality.\r\n * @param {function(V, V): boolean=} opt_equalityFn Optional equality function\r\n * to test equality of values. If not specified, this will test whether\r\n * the values contained in each map are identical objects.\r\n * @return {boolean} Whether the maps are equal.\r\n */\r\ngoog.structs.Map.prototype.equals = function(otherMap, opt_equalityFn) {\r\n if (this === otherMap) {\r\n return true;\r\n }\r\n\r\n if (this.count_ != otherMap.getCount()) {\r\n return false;\r\n }\r\n\r\n var equalityFn = opt_equalityFn || goog.structs.Map.defaultEquals;\r\n\r\n this.cleanupKeysArray_();\r\n for (var key, i = 0; key = this.keys_[i]; i++) {\r\n if (!equalityFn(this.get(key), otherMap.get(key))) {\r\n return false;\r\n }\r\n }\r\n\r\n return true;\r\n};\r\n\r\n\r\n/**\r\n * Default equality test for values.\r\n * @param {*} a The first value.\r\n * @param {*} b The second value.\r\n * @return {boolean} Whether a and b reference the same object.\r\n */\r\ngoog.structs.Map.defaultEquals = function(a, b) {\r\n return a === b;\r\n};\r\n\r\n\r\n/**\r\n * @return {boolean} Whether the map is empty.\r\n */\r\ngoog.structs.Map.prototype.isEmpty = function() {\r\n return this.count_ == 0;\r\n};\r\n\r\n\r\n/**\r\n * Removes all key-value pairs from the map.\r\n */\r\ngoog.structs.Map.prototype.clear = function() {\r\n this.map_ = {};\r\n this.keys_.length = 0;\r\n this.count_ = 0;\r\n this.version_ = 0;\r\n};\r\n\r\n\r\n/**\r\n * Removes a key-value pair based on the key. This is O(logN) amortized due to\r\n * updating the keys array whenever the count becomes half the size of the keys\r\n * in the keys array.\r\n * @param {*} key The key to remove.\r\n * @return {boolean} Whether object was removed.\r\n */\r\ngoog.structs.Map.prototype.remove = function(key) {\r\n if (goog.structs.Map.hasKey_(this.map_, key)) {\r\n delete this.map_[key];\r\n this.count_--;\r\n this.version_++;\r\n\r\n // clean up the keys array if the threshold is hit\r\n if (this.keys_.length > 2 * this.count_) {\r\n this.cleanupKeysArray_();\r\n }\r\n\r\n return true;\r\n }\r\n return false;\r\n};\r\n\r\n\r\n/**\r\n * Cleans up the temp keys array by removing entries that are no longer in the\r\n * map.\r\n * @private\r\n */\r\ngoog.structs.Map.prototype.cleanupKeysArray_ = function() {\r\n if (this.count_ != this.keys_.length) {\r\n // First remove keys that are no longer in the map.\r\n var srcIndex = 0;\r\n var destIndex = 0;\r\n while (srcIndex < this.keys_.length) {\r\n var key = this.keys_[srcIndex];\r\n if (goog.structs.Map.hasKey_(this.map_, key)) {\r\n this.keys_[destIndex++] = key;\r\n }\r\n srcIndex++;\r\n }\r\n this.keys_.length = destIndex;\r\n }\r\n\r\n if (this.count_ != this.keys_.length) {\r\n // If the count still isn't correct, that means we have duplicates. This can\r\n // happen when the same key is added and removed multiple times. Now we have\r\n // to allocate one extra Object to remove the duplicates. This could have\r\n // been done in the first pass, but in the common case, we can avoid\r\n // allocating an extra object by only doing this when necessary.\r\n var seen = {};\r\n var srcIndex = 0;\r\n var destIndex = 0;\r\n while (srcIndex < this.keys_.length) {\r\n var key = this.keys_[srcIndex];\r\n if (!(goog.structs.Map.hasKey_(seen, key))) {\r\n this.keys_[destIndex++] = key;\r\n seen[key] = 1;\r\n }\r\n srcIndex++;\r\n }\r\n this.keys_.length = destIndex;\r\n }\r\n};\r\n\r\n\r\n/**\r\n * Returns the value for the given key. If the key is not found and the default\r\n * value is not given this will return `undefined`.\r\n * @param {*} key The key to get the value for.\r\n * @param {DEFAULT=} opt_val The value to return if no item is found for the\r\n * given key, defaults to undefined.\r\n * @return {V|DEFAULT} The value for the given key.\r\n * @template DEFAULT\r\n */\r\ngoog.structs.Map.prototype.get = function(key, opt_val) {\r\n if (goog.structs.Map.hasKey_(this.map_, key)) {\r\n return this.map_[key];\r\n }\r\n return opt_val;\r\n};\r\n\r\n\r\n/**\r\n * Adds a key-value pair to the map.\r\n * @param {*} key The key.\r\n * @param {V} value The value to add.\r\n * @return {*} Some subclasses return a value.\r\n */\r\ngoog.structs.Map.prototype.set = function(key, value) {\r\n if (!(goog.structs.Map.hasKey_(this.map_, key))) {\r\n this.count_++;\r\n // TODO(johnlenz): This class lies, it claims to return an array of string\r\n // keys, but instead returns the original object used.\r\n this.keys_.push(/** @type {?} */ (key));\r\n // Only change the version if we add a new key.\r\n this.version_++;\r\n }\r\n this.map_[key] = value;\r\n};\r\n\r\n\r\n/**\r\n * Adds multiple key-value pairs from another goog.structs.Map or Object.\r\n * @param {?Object} map Object containing the data to add.\r\n */\r\ngoog.structs.Map.prototype.addAll = function(map) {\r\n if (map instanceof goog.structs.Map) {\r\n var keys = map.getKeys();\r\n for (var i = 0; i < keys.length; i++) {\r\n this.set(keys[i], map.get(keys[i]));\r\n }\r\n } else {\r\n for (var key in map) {\r\n this.set(key, map[key]);\r\n }\r\n }\r\n};\r\n\r\n\r\n/**\r\n * Calls the given function on each entry in the map.\r\n * @param {function(this:T, V, K, goog.structs.Map<K,V>)} f\r\n * @param {T=} opt_obj The value of \"this\" inside f.\r\n * @template T\r\n */\r\ngoog.structs.Map.prototype.forEach = function(f, opt_obj) {\r\n var keys = this.getKeys();\r\n for (var i = 0; i < keys.length; i++) {\r\n var key = keys[i];\r\n var value = this.get(key);\r\n f.call(opt_obj, value, key, this);\r\n }\r\n};\r\n\r\n\r\n/**\r\n * Clones a map and returns a new map.\r\n * @return {!goog.structs.Map} A new map with the same key-value pairs.\r\n */\r\ngoog.structs.Map.prototype.clone = function() {\r\n return new goog.structs.Map(this);\r\n};\r\n\r\n\r\n/**\r\n * Returns a new map in which all the keys and values are interchanged\r\n * (keys become values and values become keys). If multiple keys map to the\r\n * same value, the chosen transposed value is implementation-dependent.\r\n *\r\n * It acts very similarly to {goog.object.transpose(Object)}.\r\n *\r\n * @return {!goog.structs.Map} The transposed map.\r\n */\r\ngoog.structs.Map.prototype.transpose = function() {\r\n var transposed = new goog.structs.Map();\r\n for (var i = 0; i < this.keys_.length; i++) {\r\n var key = this.keys_[i];\r\n var value = this.map_[key];\r\n transposed.set(value, key);\r\n }\r\n\r\n return transposed;\r\n};\r\n\r\n\r\n/**\r\n * @return {!Object} Object representation of the map.\r\n */\r\ngoog.structs.Map.prototype.toObject = function() {\r\n this.cleanupKeysArray_();\r\n var obj = {};\r\n for (var i = 0; i < this.keys_.length; i++) {\r\n var key = this.keys_[i];\r\n obj[key] = this.map_[key];\r\n }\r\n return obj;\r\n};\r\n\r\n\r\n/**\r\n * Returns an iterator that iterates over the keys in the map. Removal of keys\r\n * while iterating might have undesired side effects.\r\n * @return {!goog.iter.Iterator} An iterator over the keys in the map.\r\n */\r\ngoog.structs.Map.prototype.getKeyIterator = function() {\r\n return this.__iterator__(true);\r\n};\r\n\r\n\r\n/**\r\n * Returns an iterator that iterates over the values in the map. Removal of\r\n * keys while iterating might have undesired side effects.\r\n * @return {!goog.iter.Iterator} An iterator over the values in the map.\r\n */\r\ngoog.structs.Map.prototype.getValueIterator = function() {\r\n return this.__iterator__(false);\r\n};\r\n\r\n\r\n/**\r\n * Returns an iterator that iterates over the values or the keys in the map.\r\n * This throws an exception if the map was mutated since the iterator was\r\n * created.\r\n * @param {boolean=} opt_keys True to iterate over the keys. False to iterate\r\n * over the values. The default value is false.\r\n * @return {!goog.iter.Iterator} An iterator over the values or keys in the map.\r\n */\r\ngoog.structs.Map.prototype.__iterator__ = function(opt_keys) {\r\n // Clean up keys to minimize the risk of iterating over dead keys.\r\n this.cleanupKeysArray_();\r\n\r\n var i = 0;\r\n var version = this.version_;\r\n var selfObj = this;\r\n\r\n var newIter = new goog.iter.Iterator;\r\n newIter.next = function() {\r\n if (version != selfObj.version_) {\r\n throw new Error('The map has changed since the iterator was created');\r\n }\r\n if (i >= selfObj.keys_.length) {\r\n throw goog.iter.StopIteration;\r\n }\r\n var key = selfObj.keys_[i++];\r\n return opt_keys ? key : selfObj.map_[key];\r\n };\r\n return newIter;\r\n};\r\n\r\n\r\n/**\r\n * Safe way to test for hasOwnProperty. It even allows testing for\r\n * 'hasOwnProperty'.\r\n * @param {!Object} obj The object to test for presence of the given key.\r\n * @param {*} key The key to check for.\r\n * @return {boolean} Whether the object has the key.\r\n * @private\r\n */\r\ngoog.structs.Map.hasKey_ = function(obj, key) {\r\n return Object.prototype.hasOwnProperty.call(obj, key);\r\n};\r\n","// Copyright 2008 The Closure Library Authors. All Rights Reserved.\r\n//\r\n// Licensed under the Apache License, Version 2.0 (the \"License\");\r\n// you may not use this file except in compliance with the License.\r\n// You may obtain a copy of the License at\r\n//\r\n// http://www.apache.org/licenses/LICENSE-2.0\r\n//\r\n// Unless required by applicable law or agreed to in writing, software\r\n// distributed under the License is distributed on an \"AS-IS\" BASIS,\r\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n// See the License for the specific language governing permissions and\r\n// limitations under the License.\r\n\r\n/**\r\n * @fileoverview Simple utilities for dealing with URI strings.\r\n *\r\n * This is intended to be a lightweight alternative to constructing goog.Uri\r\n * objects. Whereas goog.Uri adds several kilobytes to the binary regardless\r\n * of how much of its functionality you use, this is designed to be a set of\r\n * mostly-independent utilities so that the compiler includes only what is\r\n * necessary for the task. Estimated savings of porting is 5k pre-gzip and\r\n * 1.5k post-gzip. To ensure the savings remain, future developers should\r\n * avoid adding new functionality to existing functions, but instead create\r\n * new ones and factor out shared code.\r\n *\r\n * Many of these utilities have limited functionality, tailored to common\r\n * cases. The query parameter utilities assume that the parameter keys are\r\n * already encoded, since most keys are compile-time alphanumeric strings. The\r\n * query parameter mutation utilities also do not tolerate fragment identifiers.\r\n *\r\n * By design, these functions can be slower than goog.Uri equivalents.\r\n * Repeated calls to some of functions may be quadratic in behavior for IE,\r\n * although the effect is somewhat limited given the 2kb limit.\r\n *\r\n * One advantage of the limited functionality here is that this approach is\r\n * less sensitive to differences in URI encodings than goog.Uri, since these\r\n * functions operate on strings directly, rather than decoding them and\r\n * then re-encoding.\r\n *\r\n * Uses features of RFC 3986 for parsing/formatting URIs:\r\n * http://www.ietf.org/rfc/rfc3986.txt\r\n *\r\n * @author gboyer@google.com (Garrett Boyer) - The \"lightened\" design.\r\n * @author msamuel@google.com (Mike Samuel) - Domain knowledge and regexes.\r\n */\r\n\r\ngoog.provide('goog.uri.utils');\r\ngoog.provide('goog.uri.utils.ComponentIndex');\r\ngoog.provide('goog.uri.utils.QueryArray');\r\ngoog.provide('goog.uri.utils.QueryValue');\r\ngoog.provide('goog.uri.utils.StandardQueryParam');\r\n\r\ngoog.require('goog.array');\r\ngoog.require('goog.asserts');\r\ngoog.require('goog.string');\r\n\r\n\r\n/**\r\n * Character codes inlined to avoid object allocations due to charCode.\r\n * @enum {number}\r\n * @private\r\n */\r\ngoog.uri.utils.CharCode_ = {\r\n AMPERSAND: 38,\r\n EQUAL: 61,\r\n HASH: 35,\r\n QUESTION: 63\r\n};\r\n\r\n\r\n/**\r\n * Builds a URI string from already-encoded parts.\r\n *\r\n * No encoding is performed. Any component may be omitted as either null or\r\n * undefined.\r\n *\r\n * @param {?string=} opt_scheme The scheme such as 'http'.\r\n * @param {?string=} opt_userInfo The user name before the '@'.\r\n * @param {?string=} opt_domain The domain such as 'www.google.com', already\r\n * URI-encoded.\r\n * @param {(string|number|null)=} opt_port The port number.\r\n * @param {?string=} opt_path The path, already URI-encoded. If it is not\r\n * empty, it must begin with a slash.\r\n * @param {?string=} opt_queryData The URI-encoded query data.\r\n * @param {?string=} opt_fragment The URI-encoded fragment identifier.\r\n * @return {string} The fully combined URI.\r\n */\r\ngoog.uri.utils.buildFromEncodedParts = function(\r\n opt_scheme, opt_userInfo, opt_domain, opt_port, opt_path, opt_queryData,\r\n opt_fragment) {\r\n var out = '';\r\n\r\n if (opt_scheme) {\r\n out += opt_scheme + ':';\r\n }\r\n\r\n if (opt_domain) {\r\n out += '//';\r\n\r\n if (opt_userInfo) {\r\n out += opt_userInfo + '@';\r\n }\r\n\r\n out += opt_domain;\r\n\r\n if (opt_port) {\r\n out += ':' + opt_port;\r\n }\r\n }\r\n\r\n if (opt_path) {\r\n out += opt_path;\r\n }\r\n\r\n if (opt_queryData) {\r\n out += '?' + opt_queryData;\r\n }\r\n\r\n if (opt_fragment) {\r\n out += '#' + opt_fragment;\r\n }\r\n\r\n return out;\r\n};\r\n\r\n\r\n/**\r\n * A regular expression for breaking a URI into its component parts.\r\n *\r\n * {@link http://www.ietf.org/rfc/rfc3986.txt} says in Appendix B\r\n * As the \"first-match-wins\" algorithm is identical to the \"greedy\"\r\n * disambiguation method used by POSIX regular expressions, it is natural and\r\n * commonplace to use a regular expression for parsing the potential five\r\n * components of a URI reference.\r\n *\r\n * The following line is the regular expression for breaking-down a\r\n * well-formed URI reference into its components.\r\n *\r\n * <pre>\r\n * ^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\\?([^#]*))?(#(.*))?\r\n * 12 3 4 5 6 7 8 9\r\n * </pre>\r\n *\r\n * The numbers in the second line above are only to assist readability; they\r\n * indicate the reference points for each subexpression (i.e., each paired\r\n * parenthesis). We refer to the value matched for subexpression <n> as $<n>.\r\n * For example, matching the above expression to\r\n * <pre>\r\n * http://www.ics.uci.edu/pub/ietf/uri/#Related\r\n * </pre>\r\n * results in the following subexpression matches:\r\n * <pre>\r\n * $1 = http:\r\n * $2 = http\r\n * $3 = //www.ics.uci.edu\r\n * $4 = www.ics.uci.edu\r\n * $5 = /pub/ietf/uri/\r\n * $6 = <undefined>\r\n * $7 = <undefined>\r\n * $8 = #Related\r\n * $9 = Related\r\n * </pre>\r\n * where <undefined> indicates that the component is not present, as is the\r\n * case for the query component in the above example. Therefore, we can\r\n * determine the value of the five components as\r\n * <pre>\r\n * scheme = $2\r\n * authority = $4\r\n * path = $5\r\n * query = $7\r\n * fragment = $9\r\n * </pre>\r\n *\r\n * The regular expression has been modified slightly to expose the\r\n * userInfo, domain, and port separately from the authority.\r\n * The modified version yields\r\n * <pre>\r\n * $1 = http scheme\r\n * $2 = <undefined> userInfo -\\\r\n * $3 = www.ics.uci.edu domain | authority\r\n * $4 = <undefined> port -/\r\n * $5 = /pub/ietf/uri/ path\r\n * $6 = <undefined> query without ?\r\n * $7 = Related fragment without #\r\n * </pre>\r\n * @type {!RegExp}\r\n * @private\r\n */\r\ngoog.uri.utils.splitRe_ = new RegExp(\r\n '^' +\r\n '(?:' +\r\n '([^:/?#.]+)' + // scheme - ignore special characters\r\n // used by other URL parts such as :,\r\n // ?, /, #, and .\r\n ':)?' +\r\n '(?://' +\r\n '(?:([^/?#]*)@)?' + // userInfo\r\n '([^/#?]*?)' + // domain\r\n '(?::([0-9]+))?' + // port\r\n '(?=[/#?]|$)' + // authority-terminating character\r\n ')?' +\r\n '([^?#]+)?' + // path\r\n '(?:\\\\?([^#]*))?' + // query\r\n '(?:#([\\\\s\\\\S]*))?' + // fragment\r\n '$');\r\n\r\n\r\n/**\r\n * The index of each URI component in the return value of goog.uri.utils.split.\r\n * @enum {number}\r\n */\r\ngoog.uri.utils.ComponentIndex = {\r\n SCHEME: 1,\r\n USER_INFO: 2,\r\n DOMAIN: 3,\r\n PORT: 4,\r\n PATH: 5,\r\n QUERY_DATA: 6,\r\n FRAGMENT: 7\r\n};\r\n\r\n\r\n/**\r\n * Splits a URI into its component parts.\r\n *\r\n * Each component can be accessed via the component indices; for example:\r\n * <pre>\r\n * goog.uri.utils.split(someStr)[goog.uri.utils.ComponentIndex.QUERY_DATA];\r\n * </pre>\r\n *\r\n * @param {string} uri The URI string to examine.\r\n * @return {!Array<string|undefined>} Each component still URI-encoded.\r\n * Each component that is present will contain the encoded value, whereas\r\n * components that are not present will be undefined or empty, depending\r\n * on the browser's regular expression implementation. Never null, since\r\n * arbitrary strings may still look like path names.\r\n */\r\ngoog.uri.utils.split = function(uri) {\r\n // See @return comment -- never null.\r\n return /** @type {!Array<string|undefined>} */ (\r\n uri.match(goog.uri.utils.splitRe_));\r\n};\r\n\r\n\r\n/**\r\n * @param {?string} uri A possibly null string.\r\n * @param {boolean=} opt_preserveReserved If true, percent-encoding of RFC-3986\r\n * reserved characters will not be removed.\r\n * @return {?string} The string URI-decoded, or null if uri is null.\r\n * @private\r\n */\r\ngoog.uri.utils.decodeIfPossible_ = function(uri, opt_preserveReserved) {\r\n if (!uri) {\r\n return uri;\r\n }\r\n\r\n return opt_preserveReserved ? decodeURI(uri) : decodeURIComponent(uri);\r\n};\r\n\r\n\r\n/**\r\n * Gets a URI component by index.\r\n *\r\n * It is preferred to use the getPathEncoded() variety of functions ahead,\r\n * since they are more readable.\r\n *\r\n * @param {goog.uri.utils.ComponentIndex} componentIndex The component index.\r\n * @param {string} uri The URI to examine.\r\n * @return {?string} The still-encoded component, or null if the component\r\n * is not present.\r\n * @private\r\n */\r\ngoog.uri.utils.getComponentByIndex_ = function(componentIndex, uri) {\r\n // Convert undefined, null, and empty string into null.\r\n return goog.uri.utils.split(uri)[componentIndex] || null;\r\n};\r\n\r\n\r\n/**\r\n * @param {string} uri The URI to examine.\r\n * @return {?string} The protocol or scheme, or null if none. Does not\r\n * include trailing colons or slashes.\r\n */\r\ngoog.uri.utils.getScheme = function(uri) {\r\n return goog.uri.utils.getComponentByIndex_(\r\n goog.uri.utils.ComponentIndex.SCHEME, uri);\r\n};\r\n\r\n\r\n/**\r\n * Gets the effective scheme for the URL. If the URL is relative then the\r\n * scheme is derived from the page's location.\r\n * @param {string} uri The URI to examine.\r\n * @return {string} The protocol or scheme, always lower case.\r\n */\r\ngoog.uri.utils.getEffectiveScheme = function(uri) {\r\n var scheme = goog.uri.utils.getScheme(uri);\r\n if (!scheme && goog.global.self && goog.global.self.location) {\r\n var protocol = goog.global.self.location.protocol;\r\n scheme = protocol.substr(0, protocol.length - 1);\r\n }\r\n // NOTE: When called from a web worker in Firefox 3.5, location may be null.\r\n // All other browsers with web workers support self.location from the worker.\r\n return scheme ? scheme.toLowerCase() : '';\r\n};\r\n\r\n\r\n/**\r\n * @param {string} uri The URI to examine.\r\n * @return {?string} The user name still encoded, or null if none.\r\n */\r\ngoog.uri.utils.getUserInfoEncoded = function(uri) {\r\n return goog.uri.utils.getComponentByIndex_(\r\n goog.uri.utils.ComponentIndex.USER_INFO, uri);\r\n};\r\n\r\n\r\n/**\r\n * @param {string} uri The URI to examine.\r\n * @return {?string} The decoded user info, or null if none.\r\n */\r\ngoog.uri.utils.getUserInfo = function(uri) {\r\n return goog.uri.utils.decodeIfPossible_(\r\n goog.uri.utils.getUserInfoEncoded(uri));\r\n};\r\n\r\n\r\n/**\r\n * @param {string} uri The URI to examine.\r\n * @return {?string} The domain name still encoded, or null if none.\r\n */\r\ngoog.uri.utils.getDomainEncoded = function(uri) {\r\n return goog.uri.utils.getComponentByIndex_(\r\n goog.uri.utils.ComponentIndex.DOMAIN, uri);\r\n};\r\n\r\n\r\n/**\r\n * @param {string} uri The URI to examine.\r\n * @return {?string} The decoded domain, or null if none.\r\n */\r\ngoog.uri.utils.getDomain = function(uri) {\r\n return goog.uri.utils.decodeIfPossible_(\r\n goog.uri.utils.getDomainEncoded(uri), true /* opt_preserveReserved */);\r\n};\r\n\r\n\r\n/**\r\n * @param {string} uri The URI to examine.\r\n * @return {?number} The port number, or null if none.\r\n */\r\ngoog.uri.utils.getPort = function(uri) {\r\n // Coerce to a number. If the result of getComponentByIndex_ is null or\r\n // non-numeric, the number coersion yields NaN. This will then return\r\n // null for all non-numeric cases (though also zero, which isn't a relevant\r\n // port number).\r\n return Number(\r\n goog.uri.utils.getComponentByIndex_(\r\n goog.uri.utils.ComponentIndex.PORT, uri)) ||\r\n null;\r\n};\r\n\r\n\r\n/**\r\n * @param {string} uri The URI to examine.\r\n * @return {?string} The path still encoded, or null if none. Includes the\r\n * leading slash, if any.\r\n */\r\ngoog.uri.utils.getPathEncoded = function(uri) {\r\n return goog.uri.utils.getComponentByIndex_(\r\n goog.uri.utils.ComponentIndex.PATH, uri);\r\n};\r\n\r\n\r\n/**\r\n * @param {string} uri The URI to examine.\r\n * @return {?string} The decoded path, or null if none. Includes the leading\r\n * slash, if any.\r\n */\r\ngoog.uri.utils.getPath = function(uri) {\r\n return goog.uri.utils.decodeIfPossible_(\r\n goog.uri.utils.getPathEncoded(uri), true /* opt_preserveReserved */);\r\n};\r\n\r\n\r\n/**\r\n * @param {string} uri The URI to examine.\r\n * @return {?string} The query data still encoded, or null if none. Does not\r\n * include the question mark itself.\r\n */\r\ngoog.uri.utils.getQueryData = function(uri) {\r\n return goog.uri.utils.getComponentByIndex_(\r\n goog.uri.utils.ComponentIndex.QUERY_DATA, uri);\r\n};\r\n\r\n\r\n/**\r\n * @param {string} uri The URI to examine.\r\n * @return {?string} The fragment identifier, or null if none. Does not\r\n * include the hash mark itself.\r\n */\r\ngoog.uri.utils.getFragmentEncoded = function(uri) {\r\n // The hash mark may not appear in any other part of the URL.\r\n var hashIndex = uri.indexOf('#');\r\n return hashIndex < 0 ? null : uri.substr(hashIndex + 1);\r\n};\r\n\r\n\r\n/**\r\n * @param {string} uri The URI to examine.\r\n * @param {?string} fragment The encoded fragment identifier, or null if none.\r\n * Does not include the hash mark itself.\r\n * @return {string} The URI with the fragment set.\r\n */\r\ngoog.uri.utils.setFragmentEncoded = function(uri, fragment) {\r\n return goog.uri.utils.removeFragment(uri) + (fragment ? '#' + fragment : '');\r\n};\r\n\r\n\r\n/**\r\n * @param {string} uri The URI to examine.\r\n * @return {?string} The decoded fragment identifier, or null if none. Does\r\n * not include the hash mark.\r\n */\r\ngoog.uri.utils.getFragment = function(uri) {\r\n return goog.uri.utils.decodeIfPossible_(\r\n goog.uri.utils.getFragmentEncoded(uri));\r\n};\r\n\r\n\r\n/**\r\n * Extracts everything up to the port of the URI.\r\n * @param {string} uri The URI string.\r\n * @return {string} Everything up to and including the port.\r\n */\r\ngoog.uri.utils.getHost = function(uri) {\r\n var pieces = goog.uri.utils.split(uri);\r\n return goog.uri.utils.buildFromEncodedParts(\r\n pieces[goog.uri.utils.ComponentIndex.SCHEME],\r\n pieces[goog.uri.utils.ComponentIndex.USER_INFO],\r\n pieces[goog.uri.utils.ComponentIndex.DOMAIN],\r\n pieces[goog.uri.utils.ComponentIndex.PORT]);\r\n};\r\n\r\n\r\n/**\r\n * Returns the origin for a given URL.\r\n * @param {string} uri The URI string.\r\n * @return {string} Everything up to and including the port.\r\n */\r\ngoog.uri.utils.getOrigin = function(uri) {\r\n var pieces = goog.uri.utils.split(uri);\r\n return goog.uri.utils.buildFromEncodedParts(\r\n pieces[goog.uri.utils.ComponentIndex.SCHEME], null /* opt_userInfo */,\r\n pieces[goog.uri.utils.ComponentIndex.DOMAIN],\r\n pieces[goog.uri.utils.ComponentIndex.PORT]);\r\n};\r\n\r\n\r\n/**\r\n * Extracts the path of the URL and everything after.\r\n * @param {string} uri The URI string.\r\n * @return {string} The URI, starting at the path and including the query\r\n * parameters and fragment identifier.\r\n */\r\ngoog.uri.utils.getPathAndAfter = function(uri) {\r\n var pieces = goog.uri.utils.split(uri);\r\n return goog.uri.utils.buildFromEncodedParts(\r\n null, null, null, null, pieces[goog.uri.utils.ComponentIndex.PATH],\r\n pieces[goog.uri.utils.ComponentIndex.QUERY_DATA],\r\n pieces[goog.uri.utils.ComponentIndex.FRAGMENT]);\r\n};\r\n\r\n\r\n/**\r\n * Gets the URI with the fragment identifier removed.\r\n * @param {string} uri The URI to examine.\r\n * @return {string} Everything preceding the hash mark.\r\n */\r\ngoog.uri.utils.removeFragment = function(uri) {\r\n // The hash mark may not appear in any other part of the URL.\r\n var hashIndex = uri.indexOf('#');\r\n return hashIndex < 0 ? uri : uri.substr(0, hashIndex);\r\n};\r\n\r\n\r\n/**\r\n * Ensures that two URI's have the exact same domain, scheme, and port.\r\n *\r\n * Unlike the version in goog.Uri, this checks protocol, and therefore is\r\n * suitable for checking against the browser's same-origin policy.\r\n *\r\n * @param {string} uri1 The first URI.\r\n * @param {string} uri2 The second URI.\r\n * @return {boolean} Whether they have the same scheme, domain and port.\r\n */\r\ngoog.uri.utils.haveSameDomain = function(uri1, uri2) {\r\n var pieces1 = goog.uri.utils.split(uri1);\r\n var pieces2 = goog.uri.utils.split(uri2);\r\n return pieces1[goog.uri.utils.ComponentIndex.DOMAIN] ==\r\n pieces2[goog.uri.utils.ComponentIndex.DOMAIN] &&\r\n pieces1[goog.uri.utils.ComponentIndex.SCHEME] ==\r\n pieces2[goog.uri.utils.ComponentIndex.SCHEME] &&\r\n pieces1[goog.uri.utils.ComponentIndex.PORT] ==\r\n pieces2[goog.uri.utils.ComponentIndex.PORT];\r\n};\r\n\r\n\r\n/**\r\n * Asserts that there are no fragment or query identifiers, only in uncompiled\r\n * mode.\r\n * @param {string} uri The URI to examine.\r\n * @private\r\n */\r\ngoog.uri.utils.assertNoFragmentsOrQueries_ = function(uri) {\r\n goog.asserts.assert(\r\n uri.indexOf('#') < 0 && uri.indexOf('?') < 0,\r\n 'goog.uri.utils: Fragment or query identifiers are not supported: [%s]',\r\n uri);\r\n};\r\n\r\n\r\n/**\r\n * Supported query parameter values by the parameter serializing utilities.\r\n *\r\n * If a value is null or undefined, the key-value pair is skipped, as an easy\r\n * way to omit parameters conditionally. Non-array parameters are converted\r\n * to a string and URI encoded. Array values are expanded into multiple\r\n * &key=value pairs, with each element stringized and URI-encoded.\r\n *\r\n * @typedef {*}\r\n */\r\ngoog.uri.utils.QueryValue;\r\n\r\n\r\n/**\r\n * An array representing a set of query parameters with alternating keys\r\n * and values.\r\n *\r\n * Keys are assumed to be URI encoded already and live at even indices. See\r\n * goog.uri.utils.QueryValue for details on how parameter values are encoded.\r\n *\r\n * Example:\r\n * <pre>\r\n * var data = [\r\n * // Simple param: ?name=BobBarker\r\n * 'name', 'BobBarker',\r\n * // Conditional param -- may be omitted entirely.\r\n * 'specialDietaryNeeds', hasDietaryNeeds() ? getDietaryNeeds() : null,\r\n * // Multi-valued param: &house=LosAngeles&house=NewYork&house=null\r\n * 'house', ['LosAngeles', 'NewYork', null]\r\n * ];\r\n * </pre>\r\n *\r\n * @typedef {!Array<string|goog.uri.utils.QueryValue>}\r\n */\r\ngoog.uri.utils.QueryArray;\r\n\r\n\r\n/**\r\n * Parses encoded query parameters and calls callback function for every\r\n * parameter found in the string.\r\n *\r\n * Missing value of parameter (e.g. “…&key&…”) is treated as if the value was an\r\n * empty string. Keys may be empty strings (e.g. “…&=value&…”) which also means\r\n * that “…&=&…” and “…&&…” will result in an empty key and value.\r\n *\r\n * @param {string} encodedQuery Encoded query string excluding question mark at\r\n * the beginning.\r\n * @param {function(string, string)} callback Function called for every\r\n * parameter found in query string. The first argument (name) will not be\r\n * urldecoded (so the function is consistent with buildQueryData), but the\r\n * second will. If the parameter has no value (i.e. “=” was not present)\r\n * the second argument (value) will be an empty string.\r\n */\r\ngoog.uri.utils.parseQueryData = function(encodedQuery, callback) {\r\n if (!encodedQuery) {\r\n return;\r\n }\r\n var pairs = encodedQuery.split('&');\r\n for (var i = 0; i < pairs.length; i++) {\r\n var indexOfEquals = pairs[i].indexOf('=');\r\n var name = null;\r\n var value = null;\r\n if (indexOfEquals >= 0) {\r\n name = pairs[i].substring(0, indexOfEquals);\r\n value = pairs[i].substring(indexOfEquals + 1);\r\n } else {\r\n name = pairs[i];\r\n }\r\n callback(name, value ? goog.string.urlDecode(value) : '');\r\n }\r\n};\r\n\r\n\r\n/**\r\n * Split the URI into 3 parts where the [1] is the queryData without a leading\r\n * '?'. For example, the URI http://foo.com/bar?a=b#abc returns\r\n * ['http://foo.com/bar','a=b','#abc'].\r\n * @param {string} uri The URI to parse.\r\n * @return {!Array<string>} An array representation of uri of length 3 where the\r\n * middle value is the queryData without a leading '?'.\r\n * @private\r\n */\r\ngoog.uri.utils.splitQueryData_ = function(uri) {\r\n // Find the query data and hash.\r\n var hashIndex = uri.indexOf('#');\r\n if (hashIndex < 0) {\r\n hashIndex = uri.length;\r\n }\r\n var questionIndex = uri.indexOf('?');\r\n var queryData;\r\n if (questionIndex < 0 || questionIndex > hashIndex) {\r\n questionIndex = hashIndex;\r\n queryData = '';\r\n } else {\r\n queryData = uri.substring(questionIndex + 1, hashIndex);\r\n }\r\n return [uri.substr(0, questionIndex), queryData, uri.substr(hashIndex)];\r\n};\r\n\r\n\r\n/**\r\n * Join an array created by splitQueryData_ back into a URI.\r\n * @param {!Array<string>} parts A URI in the form generated by splitQueryData_.\r\n * @return {string} The joined URI.\r\n * @private\r\n */\r\ngoog.uri.utils.joinQueryData_ = function(parts) {\r\n return parts[0] + (parts[1] ? '?' + parts[1] : '') + parts[2];\r\n};\r\n\r\n\r\n/**\r\n * @param {string} queryData\r\n * @param {string} newData\r\n * @return {string}\r\n * @private\r\n */\r\ngoog.uri.utils.appendQueryData_ = function(queryData, newData) {\r\n if (!newData) {\r\n return queryData;\r\n }\r\n return queryData ? queryData + '&' + newData : newData;\r\n};\r\n\r\n\r\n/**\r\n * @param {string} uri\r\n * @param {string} queryData\r\n * @return {string}\r\n * @private\r\n */\r\ngoog.uri.utils.appendQueryDataToUri_ = function(uri, queryData) {\r\n if (!queryData) {\r\n return uri;\r\n }\r\n var parts = goog.uri.utils.splitQueryData_(uri);\r\n parts[1] = goog.uri.utils.appendQueryData_(parts[1], queryData);\r\n return goog.uri.utils.joinQueryData_(parts);\r\n};\r\n\r\n\r\n/**\r\n * Appends key=value pairs to an array, supporting multi-valued objects.\r\n * @param {*} key The key prefix.\r\n * @param {goog.uri.utils.QueryValue} value The value to serialize.\r\n * @param {!Array<string>} pairs The array to which the 'key=value' strings\r\n * should be appended.\r\n * @private\r\n */\r\ngoog.uri.utils.appendKeyValuePairs_ = function(key, value, pairs) {\r\n goog.asserts.assertString(key);\r\n if (goog.isArray(value)) {\r\n // Convince the compiler it's an array.\r\n goog.asserts.assertArray(value);\r\n for (var j = 0; j < value.length; j++) {\r\n // Convert to string explicitly, to short circuit the null and array\r\n // logic in this function -- this ensures that null and undefined get\r\n // written as literal 'null' and 'undefined', and arrays don't get\r\n // expanded out but instead encoded in the default way.\r\n goog.uri.utils.appendKeyValuePairs_(key, String(value[j]), pairs);\r\n }\r\n } else if (value != null) {\r\n // Skip a top-level null or undefined entirely.\r\n pairs.push(\r\n key +\r\n // Check for empty string. Zero gets encoded into the url as literal\r\n // strings. For empty string, skip the equal sign, to be consistent\r\n // with UriBuilder.java.\r\n (value === '' ? '' : '=' + goog.string.urlEncode(value)));\r\n }\r\n};\r\n\r\n\r\n/**\r\n * Builds a query data string from a sequence of alternating keys and values.\r\n * Currently generates \"&key&\" for empty args.\r\n *\r\n * @param {!IArrayLike<string|goog.uri.utils.QueryValue>} keysAndValues\r\n * Alternating keys and values. See the QueryArray typedef.\r\n * @param {number=} opt_startIndex A start offset into the arary, defaults to 0.\r\n * @return {string} The encoded query string, in the form 'a=1&b=2'.\r\n */\r\ngoog.uri.utils.buildQueryData = function(keysAndValues, opt_startIndex) {\r\n goog.asserts.assert(\r\n Math.max(keysAndValues.length - (opt_startIndex || 0), 0) % 2 == 0,\r\n 'goog.uri.utils: Key/value lists must be even in length.');\r\n\r\n var params = [];\r\n for (var i = opt_startIndex || 0; i < keysAndValues.length; i += 2) {\r\n var key = /** @type {string} */ (keysAndValues[i]);\r\n goog.uri.utils.appendKeyValuePairs_(key, keysAndValues[i + 1], params);\r\n }\r\n return params.join('&');\r\n};\r\n\r\n\r\n/**\r\n * Builds a query data string from a map.\r\n * Currently generates \"&key&\" for empty args.\r\n *\r\n * @param {!Object<string, goog.uri.utils.QueryValue>} map An object where keys\r\n * are URI-encoded parameter keys, and the values are arbitrary types\r\n * or arrays. Keys with a null value are dropped.\r\n * @return {string} The encoded query string, in the form 'a=1&b=2'.\r\n */\r\ngoog.uri.utils.buildQueryDataFromMap = function(map) {\r\n var params = [];\r\n for (var key in map) {\r\n goog.uri.utils.appendKeyValuePairs_(key, map[key], params);\r\n }\r\n return params.join('&');\r\n};\r\n\r\n\r\n/**\r\n * Appends URI parameters to an existing URI.\r\n *\r\n * The variable arguments may contain alternating keys and values. Keys are\r\n * assumed to be already URI encoded. The values should not be URI-encoded,\r\n * and will instead be encoded by this function.\r\n * <pre>\r\n * appendParams('http://www.foo.com?existing=true',\r\n * 'key1', 'value1',\r\n * 'key2', 'value?willBeEncoded',\r\n * 'key3', ['valueA', 'valueB', 'valueC'],\r\n * 'key4', null);\r\n * result: 'http://www.foo.com?existing=true&' +\r\n * 'key1=value1&' +\r\n * 'key2=value%3FwillBeEncoded&' +\r\n * 'key3=valueA&key3=valueB&key3=valueC'\r\n * </pre>\r\n *\r\n * A single call to this function will not exhibit quadratic behavior in IE,\r\n * whereas multiple repeated calls may, although the effect is limited by\r\n * fact that URL's generally can't exceed 2kb.\r\n *\r\n * @param {string} uri The original URI, which may already have query data.\r\n * @param {...(goog.uri.utils.QueryArray|goog.uri.utils.QueryValue)}\r\n * var_args\r\n * An array or argument list conforming to goog.uri.utils.QueryArray.\r\n * @return {string} The URI with all query parameters added.\r\n */\r\ngoog.uri.utils.appendParams = function(uri, var_args) {\r\n var queryData = arguments.length == 2 ?\r\n goog.uri.utils.buildQueryData(arguments[1], 0) :\r\n goog.uri.utils.buildQueryData(arguments, 1);\r\n return goog.uri.utils.appendQueryDataToUri_(uri, queryData);\r\n};\r\n\r\n\r\n/**\r\n * Appends query parameters from a map.\r\n *\r\n * @param {string} uri The original URI, which may already have query data.\r\n * @param {!Object<goog.uri.utils.QueryValue>} map An object where keys are\r\n * URI-encoded parameter keys, and the values are arbitrary types or arrays.\r\n * Keys with a null value are dropped.\r\n * @return {string} The new parameters.\r\n */\r\ngoog.uri.utils.appendParamsFromMap = function(uri, map) {\r\n var queryData = goog.uri.utils.buildQueryDataFromMap(map);\r\n return goog.uri.utils.appendQueryDataToUri_(uri, queryData);\r\n};\r\n\r\n\r\n/**\r\n * Appends a single URI parameter.\r\n *\r\n * Repeated calls to this can exhibit quadratic behavior in IE6 due to the\r\n * way string append works, though it should be limited given the 2kb limit.\r\n *\r\n * @param {string} uri The original URI, which may already have query data.\r\n * @param {string} key The key, which must already be URI encoded.\r\n * @param {*=} opt_value The value, which will be stringized and encoded\r\n * (assumed not already to be encoded). If omitted, undefined, or null, the\r\n * key will be added as a valueless parameter.\r\n * @return {string} The URI with the query parameter added.\r\n */\r\ngoog.uri.utils.appendParam = function(uri, key, opt_value) {\r\n var value = goog.isDefAndNotNull(opt_value) ?\r\n '=' + goog.string.urlEncode(opt_value) :\r\n '';\r\n return goog.uri.utils.appendQueryDataToUri_(uri, key + value);\r\n};\r\n\r\n\r\n/**\r\n * Finds the next instance of a query parameter with the specified name.\r\n *\r\n * Does not instantiate any objects.\r\n *\r\n * @param {string} uri The URI to search. May contain a fragment identifier\r\n * if opt_hashIndex is specified.\r\n * @param {number} startIndex The index to begin searching for the key at. A\r\n * match may be found even if this is one character after the ampersand.\r\n * @param {string} keyEncoded The URI-encoded key.\r\n * @param {number} hashOrEndIndex Index to stop looking at. If a hash\r\n * mark is present, it should be its index, otherwise it should be the\r\n * length of the string.\r\n * @return {number} The position of the first character in the key's name,\r\n * immediately after either a question mark or a dot.\r\n * @private\r\n */\r\ngoog.uri.utils.findParam_ = function(\r\n uri, startIndex, keyEncoded, hashOrEndIndex) {\r\n var index = startIndex;\r\n var keyLength = keyEncoded.length;\r\n\r\n // Search for the key itself and post-filter for surronuding punctuation,\r\n // rather than expensively building a regexp.\r\n while ((index = uri.indexOf(keyEncoded, index)) >= 0 &&\r\n index < hashOrEndIndex) {\r\n var precedingChar = uri.charCodeAt(index - 1);\r\n // Ensure that the preceding character is '&' or '?'.\r\n if (precedingChar == goog.uri.utils.CharCode_.AMPERSAND ||\r\n precedingChar == goog.uri.utils.CharCode_.QUESTION) {\r\n // Ensure the following character is '&', '=', '#', or NaN\r\n // (end of string).\r\n var followingChar = uri.charCodeAt(index + keyLength);\r\n if (!followingChar || followingChar == goog.uri.utils.CharCode_.EQUAL ||\r\n followingChar == goog.uri.utils.CharCode_.AMPERSAND ||\r\n followingChar == goog.uri.utils.CharCode_.HASH) {\r\n return index;\r\n }\r\n }\r\n index += keyLength + 1;\r\n }\r\n\r\n return -1;\r\n};\r\n\r\n\r\n/**\r\n * Regular expression for finding a hash mark or end of string.\r\n * @type {RegExp}\r\n * @private\r\n */\r\ngoog.uri.utils.hashOrEndRe_ = /#|$/;\r\n\r\n\r\n/**\r\n * Determines if the URI contains a specific key.\r\n *\r\n * Performs no object instantiations.\r\n *\r\n * @param {string} uri The URI to process. May contain a fragment\r\n * identifier.\r\n * @param {string} keyEncoded The URI-encoded key. Case-sensitive.\r\n * @return {boolean} Whether the key is present.\r\n */\r\ngoog.uri.utils.hasParam = function(uri, keyEncoded) {\r\n return goog.uri.utils.findParam_(\r\n uri, 0, keyEncoded, uri.search(goog.uri.utils.hashOrEndRe_)) >= 0;\r\n};\r\n\r\n\r\n/**\r\n * Gets the first value of a query parameter.\r\n * @param {string} uri The URI to process. May contain a fragment.\r\n * @param {string} keyEncoded The URI-encoded key. Case-sensitive.\r\n * @return {?string} The first value of the parameter (URI-decoded), or null\r\n * if the parameter is not found.\r\n */\r\ngoog.uri.utils.getParamValue = function(uri, keyEncoded) {\r\n var hashOrEndIndex = uri.search(goog.uri.utils.hashOrEndRe_);\r\n var foundIndex =\r\n goog.uri.utils.findParam_(uri, 0, keyEncoded, hashOrEndIndex);\r\n\r\n if (foundIndex < 0) {\r\n return null;\r\n } else {\r\n var endPosition = uri.indexOf('&', foundIndex);\r\n if (endPosition < 0 || endPosition > hashOrEndIndex) {\r\n endPosition = hashOrEndIndex;\r\n }\r\n // Progress forth to the end of the \"key=\" or \"key&\" substring.\r\n foundIndex += keyEncoded.length + 1;\r\n // Use substr, because it (unlike substring) will return empty string\r\n // if foundIndex > endPosition.\r\n return goog.string.urlDecode(\r\n uri.substr(foundIndex, endPosition - foundIndex));\r\n }\r\n};\r\n\r\n\r\n/**\r\n * Gets all values of a query parameter.\r\n * @param {string} uri The URI to process. May contain a fragment.\r\n * @param {string} keyEncoded The URI-encoded key. Case-sensitive.\r\n * @return {!Array<string>} All URI-decoded values with the given key.\r\n * If the key is not found, this will have length 0, but never be null.\r\n */\r\ngoog.uri.utils.getParamValues = function(uri, keyEncoded) {\r\n var hashOrEndIndex = uri.search(goog.uri.utils.hashOrEndRe_);\r\n var position = 0;\r\n var foundIndex;\r\n var result = [];\r\n\r\n while ((foundIndex = goog.uri.utils.findParam_(\r\n uri, position, keyEncoded, hashOrEndIndex)) >= 0) {\r\n // Find where this parameter ends, either the '&' or the end of the\r\n // query parameters.\r\n position = uri.indexOf('&', foundIndex);\r\n if (position < 0 || position > hashOrEndIndex) {\r\n position = hashOrEndIndex;\r\n }\r\n\r\n // Progress forth to the end of the \"key=\" or \"key&\" substring.\r\n foundIndex += keyEncoded.length + 1;\r\n // Use substr, because it (unlike substring) will return empty string\r\n // if foundIndex > position.\r\n result.push(\r\n goog.string.urlDecode(uri.substr(foundIndex, position - foundIndex)));\r\n }\r\n\r\n return result;\r\n};\r\n\r\n\r\n/**\r\n * Regexp to find trailing question marks and ampersands.\r\n * @type {RegExp}\r\n * @private\r\n */\r\ngoog.uri.utils.trailingQueryPunctuationRe_ = /[?&]($|#)/;\r\n\r\n\r\n/**\r\n * Removes all instances of a query parameter.\r\n * @param {string} uri The URI to process. Must not contain a fragment.\r\n * @param {string} keyEncoded The URI-encoded key.\r\n * @return {string} The URI with all instances of the parameter removed.\r\n */\r\ngoog.uri.utils.removeParam = function(uri, keyEncoded) {\r\n var hashOrEndIndex = uri.search(goog.uri.utils.hashOrEndRe_);\r\n var position = 0;\r\n var foundIndex;\r\n var buffer = [];\r\n\r\n // Look for a query parameter.\r\n while ((foundIndex = goog.uri.utils.findParam_(\r\n uri, position, keyEncoded, hashOrEndIndex)) >= 0) {\r\n // Get the portion of the query string up to, but not including, the ?\r\n // or & starting the parameter.\r\n buffer.push(uri.substring(position, foundIndex));\r\n // Progress to immediately after the '&'. If not found, go to the end.\r\n // Avoid including the hash mark.\r\n position = Math.min(\r\n (uri.indexOf('&', foundIndex) + 1) || hashOrEndIndex, hashOrEndIndex);\r\n }\r\n\r\n // Append everything that is remaining.\r\n buffer.push(uri.substr(position));\r\n\r\n // Join the buffer, and remove trailing punctuation that remains.\r\n return buffer.join('').replace(\r\n goog.uri.utils.trailingQueryPunctuationRe_, '$1');\r\n};\r\n\r\n\r\n/**\r\n * Replaces all existing definitions of a parameter with a single definition.\r\n *\r\n * Repeated calls to this can exhibit quadratic behavior due to the need to\r\n * find existing instances and reconstruct the string, though it should be\r\n * limited given the 2kb limit. Consider using appendParams or setParamsFromMap\r\n * to update multiple parameters in bulk.\r\n *\r\n * @param {string} uri The original URI, which may already have query data.\r\n * @param {string} keyEncoded The key, which must already be URI encoded.\r\n * @param {*} value The value, which will be stringized and encoded (assumed\r\n * not already to be encoded).\r\n * @return {string} The URI with the query parameter added.\r\n */\r\ngoog.uri.utils.setParam = function(uri, keyEncoded, value) {\r\n return goog.uri.utils.appendParam(\r\n goog.uri.utils.removeParam(uri, keyEncoded), keyEncoded, value);\r\n};\r\n\r\n\r\n/**\r\n * Effeciently set or remove multiple query parameters in a URI. Order of\r\n * unchanged parameters will not be modified, all updated parameters will be\r\n * appended to the end of the query. Params with values of null or undefined are\r\n * removed.\r\n *\r\n * @param {string} uri The URI to process.\r\n * @param {!Object<string, goog.uri.utils.QueryValue>} params A list of\r\n * parameters to update. If null or undefined, the param will be removed.\r\n * @return {string} An updated URI where the query data has been updated with\r\n * the params.\r\n */\r\ngoog.uri.utils.setParamsFromMap = function(uri, params) {\r\n var parts = goog.uri.utils.splitQueryData_(uri);\r\n var queryData = parts[1];\r\n var buffer = [];\r\n if (queryData) {\r\n goog.array.forEach(queryData.split('&'), function(pair) {\r\n var indexOfEquals = pair.indexOf('=');\r\n var name = indexOfEquals >= 0 ? pair.substr(0, indexOfEquals) : pair;\r\n if (!params.hasOwnProperty(name)) {\r\n buffer.push(pair);\r\n }\r\n });\r\n }\r\n parts[1] = goog.uri.utils.appendQueryData_(\r\n buffer.join('&'), goog.uri.utils.buildQueryDataFromMap(params));\r\n return goog.uri.utils.joinQueryData_(parts);\r\n};\r\n\r\n\r\n/**\r\n * Generates a URI path using a given URI and a path with checks to\r\n * prevent consecutive \"//\". The baseUri passed in must not contain\r\n * query or fragment identifiers. The path to append may not contain query or\r\n * fragment identifiers.\r\n *\r\n * @param {string} baseUri URI to use as the base.\r\n * @param {string} path Path to append.\r\n * @return {string} Updated URI.\r\n */\r\ngoog.uri.utils.appendPath = function(baseUri, path) {\r\n goog.uri.utils.assertNoFragmentsOrQueries_(baseUri);\r\n\r\n // Remove any trailing '/'\r\n if (goog.string.endsWith(baseUri, '/')) {\r\n baseUri = baseUri.substr(0, baseUri.length - 1);\r\n }\r\n // Remove any leading '/'\r\n if (goog.string.startsWith(path, '/')) {\r\n path = path.substr(1);\r\n }\r\n return goog.string.buildString(baseUri, '/', path);\r\n};\r\n\r\n\r\n/**\r\n * Replaces the path.\r\n * @param {string} uri URI to use as the base.\r\n * @param {string} path New path.\r\n * @return {string} Updated URI.\r\n */\r\ngoog.uri.utils.setPath = function(uri, path) {\r\n // Add any missing '/'.\r\n if (!goog.string.startsWith(path, '/')) {\r\n path = '/' + path;\r\n }\r\n var parts = goog.uri.utils.split(uri);\r\n return goog.uri.utils.buildFromEncodedParts(\r\n parts[goog.uri.utils.ComponentIndex.SCHEME],\r\n parts[goog.uri.utils.ComponentIndex.USER_INFO],\r\n parts[goog.uri.utils.ComponentIndex.DOMAIN],\r\n parts[goog.uri.utils.ComponentIndex.PORT], path,\r\n parts[goog.uri.utils.ComponentIndex.QUERY_DATA],\r\n parts[goog.uri.utils.ComponentIndex.FRAGMENT]);\r\n};\r\n\r\n\r\n/**\r\n * Standard supported query parameters.\r\n * @enum {string}\r\n */\r\ngoog.uri.utils.StandardQueryParam = {\r\n\r\n /** Unused parameter for unique-ifying. */\r\n RANDOM: 'zx'\r\n};\r\n\r\n\r\n/**\r\n * Sets the zx parameter of a URI to a random value.\r\n * @param {string} uri Any URI.\r\n * @return {string} That URI with the \"zx\" parameter added or replaced to\r\n * contain a random string.\r\n */\r\ngoog.uri.utils.makeUnique = function(uri) {\r\n return goog.uri.utils.setParam(\r\n uri, goog.uri.utils.StandardQueryParam.RANDOM,\r\n goog.string.getRandomString());\r\n};\r\n","// Copyright 2006 The Closure Library Authors. All Rights Reserved.\r\n//\r\n// Licensed under the Apache License, Version 2.0 (the \"License\");\r\n// you may not use this file except in compliance with the License.\r\n// You may obtain a copy of the License at\r\n//\r\n// http://www.apache.org/licenses/LICENSE-2.0\r\n//\r\n// Unless required by applicable law or agreed to in writing, software\r\n// distributed under the License is distributed on an \"AS-IS\" BASIS,\r\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n// See the License for the specific language governing permissions and\r\n// limitations under the License.\r\n\r\n/**\r\n * @fileoverview Class for parsing and formatting URIs.\r\n *\r\n * Use goog.Uri(string) to parse a URI string. Use goog.Uri.create(...) to\r\n * create a new instance of the goog.Uri object from Uri parts.\r\n *\r\n * e.g: <code>var myUri = new goog.Uri(window.location);</code>\r\n *\r\n * Implements RFC 3986 for parsing/formatting URIs.\r\n * http://www.ietf.org/rfc/rfc3986.txt\r\n *\r\n * Some changes have been made to the interface (more like .NETs), though the\r\n * internal representation is now of un-encoded parts, this will change the\r\n * behavior slightly.\r\n *\r\n * @author msamuel@google.com (Mike Samuel)\r\n */\r\n\r\ngoog.provide('goog.Uri');\r\ngoog.provide('goog.Uri.QueryData');\r\n\r\ngoog.require('goog.array');\r\ngoog.require('goog.asserts');\r\ngoog.require('goog.string');\r\ngoog.require('goog.structs');\r\ngoog.require('goog.structs.Map');\r\ngoog.require('goog.uri.utils');\r\ngoog.require('goog.uri.utils.ComponentIndex');\r\ngoog.require('goog.uri.utils.StandardQueryParam');\r\n\r\n\r\n\r\n/**\r\n * This class contains setters and getters for the parts of the URI.\r\n * The <code>getXyz</code>/<code>setXyz</code> methods return the decoded part\r\n * -- so<code>goog.Uri.parse('/foo%20bar').getPath()</code> will return the\r\n * decoded path, <code>/foo bar</code>.\r\n *\r\n * Reserved characters (see RFC 3986 section 2.2) can be present in\r\n * their percent-encoded form in scheme, domain, and path URI components and\r\n * will not be auto-decoded. For example:\r\n * <code>goog.Uri.parse('rel%61tive/path%2fto/resource').getPath()</code> will\r\n * return <code>relative/path%2fto/resource</code>.\r\n *\r\n * The constructor accepts an optional unparsed, raw URI string. The parser\r\n * is relaxed, so special characters that aren't escaped but don't cause\r\n * ambiguities will not cause parse failures.\r\n *\r\n * All setters return <code>this</code> and so may be chained, a la\r\n * <code>goog.Uri.parse('/foo').setFragment('part').toString()</code>.\r\n *\r\n * @param {*=} opt_uri Optional string URI to parse\r\n * (use goog.Uri.create() to create a URI from parts), or if\r\n * a goog.Uri is passed, a clone is created.\r\n * @param {boolean=} opt_ignoreCase If true, #getParameterValue will ignore\r\n * the case of the parameter name.\r\n *\r\n * @throws URIError If opt_uri is provided and URI is malformed (that is,\r\n * if decodeURIComponent fails on any of the URI components).\r\n * @constructor\r\n * @struct\r\n */\r\ngoog.Uri = function(opt_uri, opt_ignoreCase) {\r\n /**\r\n * Scheme such as \"http\".\r\n * @private {string}\r\n */\r\n this.scheme_ = '';\r\n\r\n /**\r\n * User credentials in the form \"username:password\".\r\n * @private {string}\r\n */\r\n this.userInfo_ = '';\r\n\r\n /**\r\n * Domain part, e.g. \"www.google.com\".\r\n * @private {string}\r\n */\r\n this.domain_ = '';\r\n\r\n /**\r\n * Port, e.g. 8080.\r\n * @private {?number}\r\n */\r\n this.port_ = null;\r\n\r\n /**\r\n * Path, e.g. \"/tests/img.png\".\r\n * @private {string}\r\n */\r\n this.path_ = '';\r\n\r\n /**\r\n * The fragment without the #.\r\n * @private {string}\r\n */\r\n this.fragment_ = '';\r\n\r\n /**\r\n * Whether or not this Uri should be treated as Read Only.\r\n * @private {boolean}\r\n */\r\n this.isReadOnly_ = false;\r\n\r\n /**\r\n * Whether or not to ignore case when comparing query params.\r\n * @private {boolean}\r\n */\r\n this.ignoreCase_ = false;\r\n\r\n /**\r\n * Object representing query data.\r\n * @private {!goog.Uri.QueryData}\r\n */\r\n this.queryData_;\r\n\r\n // Parse in the uri string\r\n var m;\r\n if (opt_uri instanceof goog.Uri) {\r\n this.ignoreCase_ =\r\n goog.isDef(opt_ignoreCase) ? opt_ignoreCase : opt_uri.getIgnoreCase();\r\n this.setScheme(opt_uri.getScheme());\r\n this.setUserInfo(opt_uri.getUserInfo());\r\n this.setDomain(opt_uri.getDomain());\r\n this.setPort(opt_uri.getPort());\r\n this.setPath(opt_uri.getPath());\r\n this.setQueryData(opt_uri.getQueryData().clone());\r\n this.setFragment(opt_uri.getFragment());\r\n } else if (opt_uri && (m = goog.uri.utils.split(String(opt_uri)))) {\r\n this.ignoreCase_ = !!opt_ignoreCase;\r\n\r\n // Set the parts -- decoding as we do so.\r\n // COMPATIBILITY NOTE - In IE, unmatched fields may be empty strings,\r\n // whereas in other browsers they will be undefined.\r\n this.setScheme(m[goog.uri.utils.ComponentIndex.SCHEME] || '', true);\r\n this.setUserInfo(m[goog.uri.utils.ComponentIndex.USER_INFO] || '', true);\r\n this.setDomain(m[goog.uri.utils.ComponentIndex.DOMAIN] || '', true);\r\n this.setPort(m[goog.uri.utils.ComponentIndex.PORT]);\r\n this.setPath(m[goog.uri.utils.ComponentIndex.PATH] || '', true);\r\n this.setQueryData(m[goog.uri.utils.ComponentIndex.QUERY_DATA] || '', true);\r\n this.setFragment(m[goog.uri.utils.ComponentIndex.FRAGMENT] || '', true);\r\n\r\n } else {\r\n this.ignoreCase_ = !!opt_ignoreCase;\r\n this.queryData_ = new goog.Uri.QueryData(null, null, this.ignoreCase_);\r\n }\r\n};\r\n\r\n\r\n/**\r\n * Parameter name added to stop caching.\r\n * @type {string}\r\n */\r\ngoog.Uri.RANDOM_PARAM = goog.uri.utils.StandardQueryParam.RANDOM;\r\n\r\n\r\n/**\r\n * @return {string} The string form of the url.\r\n * @override\r\n */\r\ngoog.Uri.prototype.toString = function() {\r\n var out = [];\r\n\r\n var scheme = this.getScheme();\r\n if (scheme) {\r\n out.push(\r\n goog.Uri.encodeSpecialChars_(\r\n scheme, goog.Uri.reDisallowedInSchemeOrUserInfo_, true),\r\n ':');\r\n }\r\n\r\n var domain = this.getDomain();\r\n if (domain || scheme == 'file') {\r\n out.push('//');\r\n\r\n var userInfo = this.getUserInfo();\r\n if (userInfo) {\r\n out.push(\r\n goog.Uri.encodeSpecialChars_(\r\n userInfo, goog.Uri.reDisallowedInSchemeOrUserInfo_, true),\r\n '@');\r\n }\r\n\r\n out.push(goog.Uri.removeDoubleEncoding_(goog.string.urlEncode(domain)));\r\n\r\n var port = this.getPort();\r\n if (port != null) {\r\n out.push(':', String(port));\r\n }\r\n }\r\n\r\n var path = this.getPath();\r\n if (path) {\r\n if (this.hasDomain() && path.charAt(0) != '/') {\r\n out.push('/');\r\n }\r\n out.push(\r\n goog.Uri.encodeSpecialChars_(\r\n path, path.charAt(0) == '/' ? goog.Uri.reDisallowedInAbsolutePath_ :\r\n goog.Uri.reDisallowedInRelativePath_,\r\n true));\r\n }\r\n\r\n var query = this.getEncodedQuery();\r\n if (query) {\r\n out.push('?', query);\r\n }\r\n\r\n var fragment = this.getFragment();\r\n if (fragment) {\r\n out.push(\r\n '#', goog.Uri.encodeSpecialChars_(\r\n fragment, goog.Uri.reDisallowedInFragment_));\r\n }\r\n return out.join('');\r\n};\r\n\r\n\r\n/**\r\n * Resolves the given relative URI (a goog.Uri object), using the URI\r\n * represented by this instance as the base URI.\r\n *\r\n * There are several kinds of relative URIs:<br>\r\n * 1. foo - replaces the last part of the path, the whole query and fragment<br>\r\n * 2. /foo - replaces the path, the query and fragment<br>\r\n * 3. //foo - replaces everything from the domain on. foo is a domain name<br>\r\n * 4. ?foo - replace the query and fragment<br>\r\n * 5. #foo - replace the fragment only\r\n *\r\n * Additionally, if relative URI has a non-empty path, all \"..\" and \".\"\r\n * segments will be resolved, as described in RFC 3986.\r\n *\r\n * @param {!goog.Uri} relativeUri The relative URI to resolve.\r\n * @return {!goog.Uri} The resolved URI.\r\n */\r\ngoog.Uri.prototype.resolve = function(relativeUri) {\r\n\r\n var absoluteUri = this.clone();\r\n\r\n // we satisfy these conditions by looking for the first part of relativeUri\r\n // that is not blank and applying defaults to the rest\r\n\r\n var overridden = relativeUri.hasScheme();\r\n\r\n if (overridden) {\r\n absoluteUri.setScheme(relativeUri.getScheme());\r\n } else {\r\n overridden = relativeUri.hasUserInfo();\r\n }\r\n\r\n if (overridden) {\r\n absoluteUri.setUserInfo(relativeUri.getUserInfo());\r\n } else {\r\n overridden = relativeUri.hasDomain();\r\n }\r\n\r\n if (overridden) {\r\n absoluteUri.setDomain(relativeUri.getDomain());\r\n } else {\r\n overridden = relativeUri.hasPort();\r\n }\r\n\r\n var path = relativeUri.getPath();\r\n if (overridden) {\r\n absoluteUri.setPort(relativeUri.getPort());\r\n } else {\r\n overridden = relativeUri.hasPath();\r\n if (overridden) {\r\n // resolve path properly\r\n if (path.charAt(0) != '/') {\r\n // path is relative\r\n if (this.hasDomain() && !this.hasPath()) {\r\n // RFC 3986, section 5.2.3, case 1\r\n path = '/' + path;\r\n } else {\r\n // RFC 3986, section 5.2.3, case 2\r\n var lastSlashIndex = absoluteUri.getPath().lastIndexOf('/');\r\n if (lastSlashIndex != -1) {\r\n path = absoluteUri.getPath().substr(0, lastSlashIndex + 1) + path;\r\n }\r\n }\r\n }\r\n path = goog.Uri.removeDotSegments(path);\r\n }\r\n }\r\n\r\n if (overridden) {\r\n absoluteUri.setPath(path);\r\n } else {\r\n overridden = relativeUri.hasQuery();\r\n }\r\n\r\n if (overridden) {\r\n absoluteUri.setQueryData(relativeUri.getQueryData().clone());\r\n } else {\r\n overridden = relativeUri.hasFragment();\r\n }\r\n\r\n if (overridden) {\r\n absoluteUri.setFragment(relativeUri.getFragment());\r\n }\r\n\r\n return absoluteUri;\r\n};\r\n\r\n\r\n/**\r\n * Clones the URI instance.\r\n * @return {!goog.Uri} New instance of the URI object.\r\n */\r\ngoog.Uri.prototype.clone = function() {\r\n return new goog.Uri(this);\r\n};\r\n\r\n\r\n/**\r\n * @return {string} The encoded scheme/protocol for the URI.\r\n */\r\ngoog.Uri.prototype.getScheme = function() {\r\n return this.scheme_;\r\n};\r\n\r\n\r\n/**\r\n * Sets the scheme/protocol.\r\n * @throws URIError If opt_decode is true and newScheme is malformed (that is,\r\n * if decodeURIComponent fails).\r\n * @param {string} newScheme New scheme value.\r\n * @param {boolean=} opt_decode Optional param for whether to decode new value.\r\n * @return {!goog.Uri} Reference to this URI object.\r\n */\r\ngoog.Uri.prototype.setScheme = function(newScheme, opt_decode) {\r\n this.enforceReadOnly();\r\n this.scheme_ =\r\n opt_decode ? goog.Uri.decodeOrEmpty_(newScheme, true) : newScheme;\r\n\r\n // remove an : at the end of the scheme so somebody can pass in\r\n // window.location.protocol\r\n if (this.scheme_) {\r\n this.scheme_ = this.scheme_.replace(/:$/, '');\r\n }\r\n return this;\r\n};\r\n\r\n\r\n/**\r\n * @return {boolean} Whether the scheme has been set.\r\n */\r\ngoog.Uri.prototype.hasScheme = function() {\r\n return !!this.scheme_;\r\n};\r\n\r\n\r\n/**\r\n * @return {string} The decoded user info.\r\n */\r\ngoog.Uri.prototype.getUserInfo = function() {\r\n return this.userInfo_;\r\n};\r\n\r\n\r\n/**\r\n * Sets the userInfo.\r\n * @throws URIError If opt_decode is true and newUserInfo is malformed (that is,\r\n * if decodeURIComponent fails).\r\n * @param {string} newUserInfo New userInfo value.\r\n * @param {boolean=} opt_decode Optional param for whether to decode new value.\r\n * @return {!goog.Uri} Reference to this URI object.\r\n */\r\ngoog.Uri.prototype.setUserInfo = function(newUserInfo, opt_decode) {\r\n this.enforceReadOnly();\r\n this.userInfo_ =\r\n opt_decode ? goog.Uri.decodeOrEmpty_(newUserInfo) : newUserInfo;\r\n return this;\r\n};\r\n\r\n\r\n/**\r\n * @return {boolean} Whether the user info has been set.\r\n */\r\ngoog.Uri.prototype.hasUserInfo = function() {\r\n return !!this.userInfo_;\r\n};\r\n\r\n\r\n/**\r\n * @return {string} The decoded domain.\r\n */\r\ngoog.Uri.prototype.getDomain = function() {\r\n return this.domain_;\r\n};\r\n\r\n\r\n/**\r\n * Sets the domain.\r\n * @throws URIError If opt_decode is true and newDomain is malformed (that is,\r\n * if decodeURIComponent fails).\r\n * @param {string} newDomain New domain value.\r\n * @param {boolean=} opt_decode Optional param for whether to decode new value.\r\n * @return {!goog.Uri} Reference to this URI object.\r\n */\r\ngoog.Uri.prototype.setDomain = function(newDomain, opt_decode) {\r\n this.enforceReadOnly();\r\n this.domain_ =\r\n opt_decode ? goog.Uri.decodeOrEmpty_(newDomain, true) : newDomain;\r\n return this;\r\n};\r\n\r\n\r\n/**\r\n * @return {boolean} Whether the domain has been set.\r\n */\r\ngoog.Uri.prototype.hasDomain = function() {\r\n return !!this.domain_;\r\n};\r\n\r\n\r\n/**\r\n * @return {?number} The port number.\r\n */\r\ngoog.Uri.prototype.getPort = function() {\r\n return this.port_;\r\n};\r\n\r\n\r\n/**\r\n * Sets the port number.\r\n * @param {*} newPort Port number. Will be explicitly casted to a number.\r\n * @return {!goog.Uri} Reference to this URI object.\r\n */\r\ngoog.Uri.prototype.setPort = function(newPort) {\r\n this.enforceReadOnly();\r\n\r\n if (newPort) {\r\n newPort = Number(newPort);\r\n if (isNaN(newPort) || newPort < 0) {\r\n throw new Error('Bad port number ' + newPort);\r\n }\r\n this.port_ = newPort;\r\n } else {\r\n this.port_ = null;\r\n }\r\n\r\n return this;\r\n};\r\n\r\n\r\n/**\r\n * @return {boolean} Whether the port has been set.\r\n */\r\ngoog.Uri.prototype.hasPort = function() {\r\n return this.port_ != null;\r\n};\r\n\r\n\r\n/**\r\n * @return {string} The decoded path.\r\n */\r\ngoog.Uri.prototype.getPath = function() {\r\n return this.path_;\r\n};\r\n\r\n\r\n/**\r\n * Sets the path.\r\n * @throws URIError If opt_decode is true and newPath is malformed (that is,\r\n * if decodeURIComponent fails).\r\n * @param {string} newPath New path value.\r\n * @param {boolean=} opt_decode Optional param for whether to decode new value.\r\n * @return {!goog.Uri} Reference to this URI object.\r\n */\r\ngoog.Uri.prototype.setPath = function(newPath, opt_decode) {\r\n this.enforceReadOnly();\r\n this.path_ = opt_decode ? goog.Uri.decodeOrEmpty_(newPath, true) : newPath;\r\n return this;\r\n};\r\n\r\n\r\n/**\r\n * @return {boolean} Whether the path has been set.\r\n */\r\ngoog.Uri.prototype.hasPath = function() {\r\n return !!this.path_;\r\n};\r\n\r\n\r\n/**\r\n * @return {boolean} Whether the query string has been set.\r\n */\r\ngoog.Uri.prototype.hasQuery = function() {\r\n return this.queryData_.toString() !== '';\r\n};\r\n\r\n\r\n/**\r\n * Sets the query data.\r\n * @param {goog.Uri.QueryData|string|undefined} queryData QueryData object.\r\n * @param {boolean=} opt_decode Optional param for whether to decode new value.\r\n * Applies only if queryData is a string.\r\n * @return {!goog.Uri} Reference to this URI object.\r\n */\r\ngoog.Uri.prototype.setQueryData = function(queryData, opt_decode) {\r\n this.enforceReadOnly();\r\n\r\n if (queryData instanceof goog.Uri.QueryData) {\r\n this.queryData_ = queryData;\r\n this.queryData_.setIgnoreCase(this.ignoreCase_);\r\n } else {\r\n if (!opt_decode) {\r\n // QueryData accepts encoded query string, so encode it if\r\n // opt_decode flag is not true.\r\n queryData = goog.Uri.encodeSpecialChars_(\r\n queryData, goog.Uri.reDisallowedInQuery_);\r\n }\r\n this.queryData_ = new goog.Uri.QueryData(queryData, null, this.ignoreCase_);\r\n }\r\n\r\n return this;\r\n};\r\n\r\n\r\n/**\r\n * Sets the URI query.\r\n * @param {string} newQuery New query value.\r\n * @param {boolean=} opt_decode Optional param for whether to decode new value.\r\n * @return {!goog.Uri} Reference to this URI object.\r\n */\r\ngoog.Uri.prototype.setQuery = function(newQuery, opt_decode) {\r\n return this.setQueryData(newQuery, opt_decode);\r\n};\r\n\r\n\r\n/**\r\n * @return {string} The encoded URI query, not including the ?.\r\n */\r\ngoog.Uri.prototype.getEncodedQuery = function() {\r\n return this.queryData_.toString();\r\n};\r\n\r\n\r\n/**\r\n * @return {string} The decoded URI query, not including the ?.\r\n */\r\ngoog.Uri.prototype.getDecodedQuery = function() {\r\n return this.queryData_.toDecodedString();\r\n};\r\n\r\n\r\n/**\r\n * Returns the query data.\r\n * @return {!goog.Uri.QueryData} QueryData object.\r\n */\r\ngoog.Uri.prototype.getQueryData = function() {\r\n return this.queryData_;\r\n};\r\n\r\n\r\n/**\r\n * @return {string} The encoded URI query, not including the ?.\r\n *\r\n * Warning: This method, unlike other getter methods, returns encoded\r\n * value, instead of decoded one.\r\n */\r\ngoog.Uri.prototype.getQuery = function() {\r\n return this.getEncodedQuery();\r\n};\r\n\r\n\r\n/**\r\n * Sets the value of the named query parameters, clearing previous values for\r\n * that key.\r\n *\r\n * @param {string} key The parameter to set.\r\n * @param {*} value The new value. Value does not need to be encoded.\r\n * @return {!goog.Uri} Reference to this URI object.\r\n */\r\ngoog.Uri.prototype.setParameterValue = function(key, value) {\r\n this.enforceReadOnly();\r\n this.queryData_.set(key, value);\r\n return this;\r\n};\r\n\r\n\r\n/**\r\n * Sets the values of the named query parameters, clearing previous values for\r\n * that key. Not new values will currently be moved to the end of the query\r\n * string.\r\n *\r\n * So, <code>goog.Uri.parse('foo?a=b&c=d&e=f').setParameterValues('c', ['new'])\r\n * </code> yields <tt>foo?a=b&e=f&c=new</tt>.</p>\r\n *\r\n * @param {string} key The parameter to set.\r\n * @param {*} values The new values. If values is a single\r\n * string then it will be treated as the sole value. Values do not need to\r\n * be encoded.\r\n * @return {!goog.Uri} Reference to this URI object.\r\n */\r\ngoog.Uri.prototype.setParameterValues = function(key, values) {\r\n this.enforceReadOnly();\r\n\r\n if (!goog.isArray(values)) {\r\n values = [String(values)];\r\n }\r\n\r\n this.queryData_.setValues(key, values);\r\n\r\n return this;\r\n};\r\n\r\n\r\n/**\r\n * Returns the value<b>s</b> for a given cgi parameter as a list of decoded\r\n * query parameter values.\r\n * @param {string} name The parameter to get values for.\r\n * @return {!Array<?>} The values for a given cgi parameter as a list of\r\n * decoded query parameter values.\r\n */\r\ngoog.Uri.prototype.getParameterValues = function(name) {\r\n return this.queryData_.getValues(name);\r\n};\r\n\r\n\r\n/**\r\n * Returns the first value for a given cgi parameter or undefined if the given\r\n * parameter name does not appear in the query string.\r\n * @param {string} paramName Unescaped parameter name.\r\n * @return {string|undefined} The first value for a given cgi parameter or\r\n * undefined if the given parameter name does not appear in the query\r\n * string.\r\n */\r\ngoog.Uri.prototype.getParameterValue = function(paramName) {\r\n return /** @type {string|undefined} */ (this.queryData_.get(paramName));\r\n};\r\n\r\n\r\n/**\r\n * @return {string} The URI fragment, not including the #.\r\n */\r\ngoog.Uri.prototype.getFragment = function() {\r\n return this.fragment_;\r\n};\r\n\r\n\r\n/**\r\n * Sets the URI fragment.\r\n * @throws URIError If opt_decode is true and newFragment is malformed (that is,\r\n * if decodeURIComponent fails).\r\n * @param {string} newFragment New fragment value.\r\n * @param {boolean=} opt_decode Optional param for whether to decode new value.\r\n * @return {!goog.Uri} Reference to this URI object.\r\n */\r\ngoog.Uri.prototype.setFragment = function(newFragment, opt_decode) {\r\n this.enforceReadOnly();\r\n this.fragment_ =\r\n opt_decode ? goog.Uri.decodeOrEmpty_(newFragment) : newFragment;\r\n return this;\r\n};\r\n\r\n\r\n/**\r\n * @return {boolean} Whether the URI has a fragment set.\r\n */\r\ngoog.Uri.prototype.hasFragment = function() {\r\n return !!this.fragment_;\r\n};\r\n\r\n\r\n/**\r\n * Returns true if this has the same domain as that of uri2.\r\n * @param {!goog.Uri} uri2 The URI object to compare to.\r\n * @return {boolean} true if same domain; false otherwise.\r\n */\r\ngoog.Uri.prototype.hasSameDomainAs = function(uri2) {\r\n return ((!this.hasDomain() && !uri2.hasDomain()) ||\r\n this.getDomain() == uri2.getDomain()) &&\r\n ((!this.hasPort() && !uri2.hasPort()) ||\r\n this.getPort() == uri2.getPort());\r\n};\r\n\r\n\r\n/**\r\n * Adds a random parameter to the Uri.\r\n * @return {!goog.Uri} Reference to this Uri object.\r\n */\r\ngoog.Uri.prototype.makeUnique = function() {\r\n this.enforceReadOnly();\r\n this.setParameterValue(goog.Uri.RANDOM_PARAM, goog.string.getRandomString());\r\n\r\n return this;\r\n};\r\n\r\n\r\n/**\r\n * Removes the named query parameter.\r\n *\r\n * @param {string} key The parameter to remove.\r\n * @return {!goog.Uri} Reference to this URI object.\r\n */\r\ngoog.Uri.prototype.removeParameter = function(key) {\r\n this.enforceReadOnly();\r\n this.queryData_.remove(key);\r\n return this;\r\n};\r\n\r\n\r\n/**\r\n * Sets whether Uri is read only. If this goog.Uri is read-only,\r\n * enforceReadOnly_ will be called at the start of any function that may modify\r\n * this Uri.\r\n * @param {boolean} isReadOnly whether this goog.Uri should be read only.\r\n * @return {!goog.Uri} Reference to this Uri object.\r\n */\r\ngoog.Uri.prototype.setReadOnly = function(isReadOnly) {\r\n this.isReadOnly_ = isReadOnly;\r\n return this;\r\n};\r\n\r\n\r\n/**\r\n * @return {boolean} Whether the URI is read only.\r\n */\r\ngoog.Uri.prototype.isReadOnly = function() {\r\n return this.isReadOnly_;\r\n};\r\n\r\n\r\n/**\r\n * Checks if this Uri has been marked as read only, and if so, throws an error.\r\n * This should be called whenever any modifying function is called.\r\n */\r\ngoog.Uri.prototype.enforceReadOnly = function() {\r\n if (this.isReadOnly_) {\r\n throw new Error('Tried to modify a read-only Uri');\r\n }\r\n};\r\n\r\n\r\n/**\r\n * Sets whether to ignore case.\r\n * NOTE: If there are already key/value pairs in the QueryData, and\r\n * ignoreCase_ is set to false, the keys will all be lower-cased.\r\n * @param {boolean} ignoreCase whether this goog.Uri should ignore case.\r\n * @return {!goog.Uri} Reference to this Uri object.\r\n */\r\ngoog.Uri.prototype.setIgnoreCase = function(ignoreCase) {\r\n this.ignoreCase_ = ignoreCase;\r\n if (this.queryData_) {\r\n this.queryData_.setIgnoreCase(ignoreCase);\r\n }\r\n return this;\r\n};\r\n\r\n\r\n/**\r\n * @return {boolean} Whether to ignore case.\r\n */\r\ngoog.Uri.prototype.getIgnoreCase = function() {\r\n return this.ignoreCase_;\r\n};\r\n\r\n\r\n//==============================================================================\r\n// Static members\r\n//==============================================================================\r\n\r\n\r\n/**\r\n * Creates a uri from the string form. Basically an alias of new goog.Uri().\r\n * If a Uri object is passed to parse then it will return a clone of the object.\r\n *\r\n * @throws URIError If parsing the URI is malformed. The passed URI components\r\n * should all be parseable by decodeURIComponent.\r\n * @param {*} uri Raw URI string or instance of Uri\r\n * object.\r\n * @param {boolean=} opt_ignoreCase Whether to ignore the case of parameter\r\n * names in #getParameterValue.\r\n * @return {!goog.Uri} The new URI object.\r\n */\r\ngoog.Uri.parse = function(uri, opt_ignoreCase) {\r\n return uri instanceof goog.Uri ? uri.clone() :\r\n new goog.Uri(uri, opt_ignoreCase);\r\n};\r\n\r\n\r\n/**\r\n * Creates a new goog.Uri object from unencoded parts.\r\n *\r\n * @param {?string=} opt_scheme Scheme/protocol or full URI to parse.\r\n * @param {?string=} opt_userInfo username:password.\r\n * @param {?string=} opt_domain www.google.com.\r\n * @param {?number=} opt_port 9830.\r\n * @param {?string=} opt_path /some/path/to/a/file.html.\r\n * @param {string|goog.Uri.QueryData=} opt_query a=1&b=2.\r\n * @param {?string=} opt_fragment The fragment without the #.\r\n * @param {boolean=} opt_ignoreCase Whether to ignore parameter name case in\r\n * #getParameterValue.\r\n *\r\n * @return {!goog.Uri} The new URI object.\r\n */\r\ngoog.Uri.create = function(\r\n opt_scheme, opt_userInfo, opt_domain, opt_port, opt_path, opt_query,\r\n opt_fragment, opt_ignoreCase) {\r\n\r\n var uri = new goog.Uri(null, opt_ignoreCase);\r\n\r\n // Only set the parts if they are defined and not empty strings.\r\n opt_scheme && uri.setScheme(opt_scheme);\r\n opt_userInfo && uri.setUserInfo(opt_userInfo);\r\n opt_domain && uri.setDomain(opt_domain);\r\n opt_port && uri.setPort(opt_port);\r\n opt_path && uri.setPath(opt_path);\r\n opt_query && uri.setQueryData(opt_query);\r\n opt_fragment && uri.setFragment(opt_fragment);\r\n\r\n return uri;\r\n};\r\n\r\n\r\n/**\r\n * Resolves a relative Uri against a base Uri, accepting both strings and\r\n * Uri objects.\r\n *\r\n * @param {*} base Base Uri.\r\n * @param {*} rel Relative Uri.\r\n * @return {!goog.Uri} Resolved uri.\r\n */\r\ngoog.Uri.resolve = function(base, rel) {\r\n if (!(base instanceof goog.Uri)) {\r\n base = goog.Uri.parse(base);\r\n }\r\n\r\n if (!(rel instanceof goog.Uri)) {\r\n rel = goog.Uri.parse(rel);\r\n }\r\n\r\n return base.resolve(rel);\r\n};\r\n\r\n\r\n/**\r\n * Removes dot segments in given path component, as described in\r\n * RFC 3986, section 5.2.4.\r\n *\r\n * @param {string} path A non-empty path component.\r\n * @return {string} Path component with removed dot segments.\r\n */\r\ngoog.Uri.removeDotSegments = function(path) {\r\n if (path == '..' || path == '.') {\r\n return '';\r\n\r\n } else if (\r\n !goog.string.contains(path, './') && !goog.string.contains(path, '/.')) {\r\n // This optimization detects uris which do not contain dot-segments,\r\n // and as a consequence do not require any processing.\r\n return path;\r\n\r\n } else {\r\n var leadingSlash = goog.string.startsWith(path, '/');\r\n var segments = path.split('/');\r\n var out = [];\r\n\r\n for (var pos = 0; pos < segments.length;) {\r\n var segment = segments[pos++];\r\n\r\n if (segment == '.') {\r\n if (leadingSlash && pos == segments.length) {\r\n out.push('');\r\n }\r\n } else if (segment == '..') {\r\n if (out.length > 1 || out.length == 1 && out[0] != '') {\r\n out.pop();\r\n }\r\n if (leadingSlash && pos == segments.length) {\r\n out.push('');\r\n }\r\n } else {\r\n out.push(segment);\r\n leadingSlash = true;\r\n }\r\n }\r\n\r\n return out.join('/');\r\n }\r\n};\r\n\r\n\r\n/**\r\n * Decodes a value or returns the empty string if it isn't defined or empty.\r\n * @throws URIError If decodeURIComponent fails to decode val.\r\n * @param {string|undefined} val Value to decode.\r\n * @param {boolean=} opt_preserveReserved If true, restricted characters will\r\n * not be decoded.\r\n * @return {string} Decoded value.\r\n * @private\r\n */\r\ngoog.Uri.decodeOrEmpty_ = function(val, opt_preserveReserved) {\r\n // Don't use UrlDecode() here because val is not a query parameter.\r\n if (!val) {\r\n return '';\r\n }\r\n\r\n // decodeURI has the same output for '%2f' and '%252f'. We double encode %25\r\n // so that we can distinguish between the 2 inputs. This is later undone by\r\n // removeDoubleEncoding_.\r\n return opt_preserveReserved ? decodeURI(val.replace(/%25/g, '%2525')) :\r\n decodeURIComponent(val);\r\n};\r\n\r\n\r\n/**\r\n * If unescapedPart is non null, then escapes any characters in it that aren't\r\n * valid characters in a url and also escapes any special characters that\r\n * appear in extra.\r\n *\r\n * @param {*} unescapedPart The string to encode.\r\n * @param {RegExp} extra A character set of characters in [\\01-\\177].\r\n * @param {boolean=} opt_removeDoubleEncoding If true, remove double percent\r\n * encoding.\r\n * @return {?string} null iff unescapedPart == null.\r\n * @private\r\n */\r\ngoog.Uri.encodeSpecialChars_ = function(\r\n unescapedPart, extra, opt_removeDoubleEncoding) {\r\n if (goog.isString(unescapedPart)) {\r\n var encoded = encodeURI(unescapedPart).replace(extra, goog.Uri.encodeChar_);\r\n if (opt_removeDoubleEncoding) {\r\n // encodeURI double-escapes %XX sequences used to represent restricted\r\n // characters in some URI components, remove the double escaping here.\r\n encoded = goog.Uri.removeDoubleEncoding_(encoded);\r\n }\r\n return encoded;\r\n }\r\n return null;\r\n};\r\n\r\n\r\n/**\r\n * Converts a character in [\\01-\\177] to its unicode character equivalent.\r\n * @param {string} ch One character string.\r\n * @return {string} Encoded string.\r\n * @private\r\n */\r\ngoog.Uri.encodeChar_ = function(ch) {\r\n var n = ch.charCodeAt(0);\r\n return '%' + ((n >> 4) & 0xf).toString(16) + (n & 0xf).toString(16);\r\n};\r\n\r\n\r\n/**\r\n * Removes double percent-encoding from a string.\r\n * @param {string} doubleEncodedString String\r\n * @return {string} String with double encoding removed.\r\n * @private\r\n */\r\ngoog.Uri.removeDoubleEncoding_ = function(doubleEncodedString) {\r\n return doubleEncodedString.replace(/%25([0-9a-fA-F]{2})/g, '%$1');\r\n};\r\n\r\n\r\n/**\r\n * Regular expression for characters that are disallowed in the scheme or\r\n * userInfo part of the URI.\r\n * @type {RegExp}\r\n * @private\r\n */\r\ngoog.Uri.reDisallowedInSchemeOrUserInfo_ = /[#\\/\\?@]/g;\r\n\r\n\r\n/**\r\n * Regular expression for characters that are disallowed in a relative path.\r\n * Colon is included due to RFC 3986 3.3.\r\n * @type {RegExp}\r\n * @private\r\n */\r\ngoog.Uri.reDisallowedInRelativePath_ = /[\\#\\?:]/g;\r\n\r\n\r\n/**\r\n * Regular expression for characters that are disallowed in an absolute path.\r\n * @type {RegExp}\r\n * @private\r\n */\r\ngoog.Uri.reDisallowedInAbsolutePath_ = /[\\#\\?]/g;\r\n\r\n\r\n/**\r\n * Regular expression for characters that are disallowed in the query.\r\n * @type {RegExp}\r\n * @private\r\n */\r\ngoog.Uri.reDisallowedInQuery_ = /[\\#\\?@]/g;\r\n\r\n\r\n/**\r\n * Regular expression for characters that are disallowed in the fragment.\r\n * @type {RegExp}\r\n * @private\r\n */\r\ngoog.Uri.reDisallowedInFragment_ = /#/g;\r\n\r\n\r\n/**\r\n * Checks whether two URIs have the same domain.\r\n * @param {string} uri1String First URI string.\r\n * @param {string} uri2String Second URI string.\r\n * @return {boolean} true if the two URIs have the same domain; false otherwise.\r\n */\r\ngoog.Uri.haveSameDomain = function(uri1String, uri2String) {\r\n // Differs from goog.uri.utils.haveSameDomain, since this ignores scheme.\r\n // TODO(gboyer): Have this just call goog.uri.util.haveSameDomain.\r\n var pieces1 = goog.uri.utils.split(uri1String);\r\n var pieces2 = goog.uri.utils.split(uri2String);\r\n return pieces1[goog.uri.utils.ComponentIndex.DOMAIN] ==\r\n pieces2[goog.uri.utils.ComponentIndex.DOMAIN] &&\r\n pieces1[goog.uri.utils.ComponentIndex.PORT] ==\r\n pieces2[goog.uri.utils.ComponentIndex.PORT];\r\n};\r\n\r\n\r\n\r\n/**\r\n * Class used to represent URI query parameters. It is essentially a hash of\r\n * name-value pairs, though a name can be present more than once.\r\n *\r\n * Has the same interface as the collections in goog.structs.\r\n *\r\n * @param {?string=} opt_query Optional encoded query string to parse into\r\n * the object.\r\n * @param {goog.Uri=} opt_uri Optional uri object that should have its\r\n * cache invalidated when this object updates. Deprecated -- this\r\n * is no longer required.\r\n * @param {boolean=} opt_ignoreCase If true, ignore the case of the parameter\r\n * name in #get.\r\n * @constructor\r\n * @struct\r\n * @final\r\n */\r\ngoog.Uri.QueryData = function(opt_query, opt_uri, opt_ignoreCase) {\r\n /**\r\n * The map containing name/value or name/array-of-values pairs.\r\n * May be null if it requires parsing from the query string.\r\n *\r\n * We need to use a Map because we cannot guarantee that the key names will\r\n * not be problematic for IE.\r\n *\r\n * @private {?goog.structs.Map<string, !Array<*>>}\r\n */\r\n this.keyMap_ = null;\r\n\r\n /**\r\n * The number of params, or null if it requires computing.\r\n * @private {?number}\r\n */\r\n this.count_ = null;\r\n\r\n /**\r\n * Encoded query string, or null if it requires computing from the key map.\r\n * @private {?string}\r\n */\r\n this.encodedQuery_ = opt_query || null;\r\n\r\n /**\r\n * If true, ignore the case of the parameter name in #get.\r\n * @private {boolean}\r\n */\r\n this.ignoreCase_ = !!opt_ignoreCase;\r\n};\r\n\r\n\r\n/**\r\n * If the underlying key map is not yet initialized, it parses the\r\n * query string and fills the map with parsed data.\r\n * @private\r\n */\r\ngoog.Uri.QueryData.prototype.ensureKeyMapInitialized_ = function() {\r\n if (!this.keyMap_) {\r\n this.keyMap_ = new goog.structs.Map();\r\n this.count_ = 0;\r\n if (this.encodedQuery_) {\r\n var self = this;\r\n goog.uri.utils.parseQueryData(this.encodedQuery_, function(name, value) {\r\n self.add(goog.string.urlDecode(name), value);\r\n });\r\n }\r\n }\r\n};\r\n\r\n\r\n/**\r\n * Creates a new query data instance from a map of names and values.\r\n *\r\n * @param {!goog.structs.Map<string, ?>|!Object} map Map of string parameter\r\n * names to parameter value. If parameter value is an array, it is\r\n * treated as if the key maps to each individual value in the\r\n * array.\r\n * @param {goog.Uri=} opt_uri URI object that should have its cache\r\n * invalidated when this object updates.\r\n * @param {boolean=} opt_ignoreCase If true, ignore the case of the parameter\r\n * name in #get.\r\n * @return {!goog.Uri.QueryData} The populated query data instance.\r\n */\r\ngoog.Uri.QueryData.createFromMap = function(map, opt_uri, opt_ignoreCase) {\r\n var keys = goog.structs.getKeys(map);\r\n if (typeof keys == 'undefined') {\r\n throw new Error('Keys are undefined');\r\n }\r\n\r\n var queryData = new goog.Uri.QueryData(null, null, opt_ignoreCase);\r\n var values = goog.structs.getValues(map);\r\n for (var i = 0; i < keys.length; i++) {\r\n var key = keys[i];\r\n var value = values[i];\r\n if (!goog.isArray(value)) {\r\n queryData.add(key, value);\r\n } else {\r\n queryData.setValues(key, value);\r\n }\r\n }\r\n return queryData;\r\n};\r\n\r\n\r\n/**\r\n * Creates a new query data instance from parallel arrays of parameter names\r\n * and values. Allows for duplicate parameter names. Throws an error if the\r\n * lengths of the arrays differ.\r\n *\r\n * @param {!Array<string>} keys Parameter names.\r\n * @param {!Array<?>} values Parameter values.\r\n * @param {goog.Uri=} opt_uri URI object that should have its cache\r\n * invalidated when this object updates.\r\n * @param {boolean=} opt_ignoreCase If true, ignore the case of the parameter\r\n * name in #get.\r\n * @return {!goog.Uri.QueryData} The populated query data instance.\r\n */\r\ngoog.Uri.QueryData.createFromKeysValues = function(\r\n keys, values, opt_uri, opt_ignoreCase) {\r\n if (keys.length != values.length) {\r\n throw new Error('Mismatched lengths for keys/values');\r\n }\r\n var queryData = new goog.Uri.QueryData(null, null, opt_ignoreCase);\r\n for (var i = 0; i < keys.length; i++) {\r\n queryData.add(keys[i], values[i]);\r\n }\r\n return queryData;\r\n};\r\n\r\n\r\n/**\r\n * @return {?number} The number of parameters.\r\n */\r\ngoog.Uri.QueryData.prototype.getCount = function() {\r\n this.ensureKeyMapInitialized_();\r\n return this.count_;\r\n};\r\n\r\n\r\n/**\r\n * Adds a key value pair.\r\n * @param {string} key Name.\r\n * @param {*} value Value.\r\n * @return {!goog.Uri.QueryData} Instance of this object.\r\n */\r\ngoog.Uri.QueryData.prototype.add = function(key, value) {\r\n this.ensureKeyMapInitialized_();\r\n this.invalidateCache_();\r\n\r\n key = this.getKeyName_(key);\r\n var values = this.keyMap_.get(key);\r\n if (!values) {\r\n this.keyMap_.set(key, (values = []));\r\n }\r\n values.push(value);\r\n this.count_ = goog.asserts.assertNumber(this.count_) + 1;\r\n return this;\r\n};\r\n\r\n\r\n/**\r\n * Removes all the params with the given key.\r\n * @param {string} key Name.\r\n * @return {boolean} Whether any parameter was removed.\r\n */\r\ngoog.Uri.QueryData.prototype.remove = function(key) {\r\n this.ensureKeyMapInitialized_();\r\n\r\n key = this.getKeyName_(key);\r\n if (this.keyMap_.containsKey(key)) {\r\n this.invalidateCache_();\r\n\r\n // Decrement parameter count.\r\n this.count_ =\r\n goog.asserts.assertNumber(this.count_) - this.keyMap_.get(key).length;\r\n return this.keyMap_.remove(key);\r\n }\r\n return false;\r\n};\r\n\r\n\r\n/**\r\n * Clears the parameters.\r\n */\r\ngoog.Uri.QueryData.prototype.clear = function() {\r\n this.invalidateCache_();\r\n this.keyMap_ = null;\r\n this.count_ = 0;\r\n};\r\n\r\n\r\n/**\r\n * @return {boolean} Whether we have any parameters.\r\n */\r\ngoog.Uri.QueryData.prototype.isEmpty = function() {\r\n this.ensureKeyMapInitialized_();\r\n return this.count_ == 0;\r\n};\r\n\r\n\r\n/**\r\n * Whether there is a parameter with the given name\r\n * @param {string} key The parameter name to check for.\r\n * @return {boolean} Whether there is a parameter with the given name.\r\n */\r\ngoog.Uri.QueryData.prototype.containsKey = function(key) {\r\n this.ensureKeyMapInitialized_();\r\n key = this.getKeyName_(key);\r\n return this.keyMap_.containsKey(key);\r\n};\r\n\r\n\r\n/**\r\n * Whether there is a parameter with the given value.\r\n * @param {*} value The value to check for.\r\n * @return {boolean} Whether there is a parameter with the given value.\r\n */\r\ngoog.Uri.QueryData.prototype.containsValue = function(value) {\r\n // NOTE(arv): This solution goes through all the params even if it was the\r\n // first param. We can get around this by not reusing code or by switching to\r\n // iterators.\r\n var vals = this.getValues();\r\n return goog.array.contains(vals, value);\r\n};\r\n\r\n\r\n/**\r\n * Runs a callback on every key-value pair in the map, including duplicate keys.\r\n * This won't maintain original order when duplicate keys are interspersed (like\r\n * getKeys() / getValues()).\r\n * @param {function(this:SCOPE, ?, string, !goog.Uri.QueryData)} f\r\n * @param {SCOPE=} opt_scope The value of \"this\" inside f.\r\n * @template SCOPE\r\n */\r\ngoog.Uri.QueryData.prototype.forEach = function(f, opt_scope) {\r\n this.ensureKeyMapInitialized_();\r\n this.keyMap_.forEach(function(values, key) {\r\n goog.array.forEach(values, function(value) {\r\n f.call(opt_scope, value, key, this);\r\n }, this);\r\n }, this);\r\n};\r\n\r\n\r\n/**\r\n * Returns all the keys of the parameters. If a key is used multiple times\r\n * it will be included multiple times in the returned array\r\n * @return {!Array<string>} All the keys of the parameters.\r\n */\r\ngoog.Uri.QueryData.prototype.getKeys = function() {\r\n this.ensureKeyMapInitialized_();\r\n // We need to get the values to know how many keys to add.\r\n var vals = this.keyMap_.getValues();\r\n var keys = this.keyMap_.getKeys();\r\n var rv = [];\r\n for (var i = 0; i < keys.length; i++) {\r\n var val = vals[i];\r\n for (var j = 0; j < val.length; j++) {\r\n rv.push(keys[i]);\r\n }\r\n }\r\n return rv;\r\n};\r\n\r\n\r\n/**\r\n * Returns all the values of the parameters with the given name. If the query\r\n * data has no such key this will return an empty array. If no key is given\r\n * all values wil be returned.\r\n * @param {string=} opt_key The name of the parameter to get the values for.\r\n * @return {!Array<?>} All the values of the parameters with the given name.\r\n */\r\ngoog.Uri.QueryData.prototype.getValues = function(opt_key) {\r\n this.ensureKeyMapInitialized_();\r\n var rv = [];\r\n if (goog.isString(opt_key)) {\r\n if (this.containsKey(opt_key)) {\r\n rv = goog.array.concat(rv, this.keyMap_.get(this.getKeyName_(opt_key)));\r\n }\r\n } else {\r\n // Return all values.\r\n var values = this.keyMap_.getValues();\r\n for (var i = 0; i < values.length; i++) {\r\n rv = goog.array.concat(rv, values[i]);\r\n }\r\n }\r\n return rv;\r\n};\r\n\r\n\r\n/**\r\n * Sets a key value pair and removes all other keys with the same value.\r\n *\r\n * @param {string} key Name.\r\n * @param {*} value Value.\r\n * @return {!goog.Uri.QueryData} Instance of this object.\r\n */\r\ngoog.Uri.QueryData.prototype.set = function(key, value) {\r\n this.ensureKeyMapInitialized_();\r\n this.invalidateCache_();\r\n\r\n // TODO(chrishenry): This could be better written as\r\n // this.remove(key), this.add(key, value), but that would reorder\r\n // the key (since the key is first removed and then added at the\r\n // end) and we would have to fix unit tests that depend on key\r\n // ordering.\r\n key = this.getKeyName_(key);\r\n if (this.containsKey(key)) {\r\n this.count_ =\r\n goog.asserts.assertNumber(this.count_) - this.keyMap_.get(key).length;\r\n }\r\n this.keyMap_.set(key, [value]);\r\n this.count_ = goog.asserts.assertNumber(this.count_) + 1;\r\n return this;\r\n};\r\n\r\n\r\n/**\r\n * Returns the first value associated with the key. If the query data has no\r\n * such key this will return undefined or the optional default.\r\n * @param {string} key The name of the parameter to get the value for.\r\n * @param {*=} opt_default The default value to return if the query data\r\n * has no such key.\r\n * @return {*} The first string value associated with the key, or opt_default\r\n * if there's no value.\r\n */\r\ngoog.Uri.QueryData.prototype.get = function(key, opt_default) {\r\n if (!key) {\r\n return opt_default;\r\n }\r\n var values = this.getValues(key);\r\n return values.length > 0 ? String(values[0]) : opt_default;\r\n};\r\n\r\n\r\n/**\r\n * Sets the values for a key. If the key already exists, this will\r\n * override all of the existing values that correspond to the key.\r\n * @param {string} key The key to set values for.\r\n * @param {!Array<?>} values The values to set.\r\n */\r\ngoog.Uri.QueryData.prototype.setValues = function(key, values) {\r\n this.remove(key);\r\n\r\n if (values.length > 0) {\r\n this.invalidateCache_();\r\n this.keyMap_.set(this.getKeyName_(key), goog.array.clone(values));\r\n this.count_ = goog.asserts.assertNumber(this.count_) + values.length;\r\n }\r\n};\r\n\r\n\r\n/**\r\n * @return {string} Encoded query string.\r\n * @override\r\n */\r\ngoog.Uri.QueryData.prototype.toString = function() {\r\n if (this.encodedQuery_) {\r\n return this.encodedQuery_;\r\n }\r\n\r\n if (!this.keyMap_) {\r\n return '';\r\n }\r\n\r\n var sb = [];\r\n\r\n // In the past, we use this.getKeys() and this.getVals(), but that\r\n // generates a lot of allocations as compared to simply iterating\r\n // over the keys.\r\n var keys = this.keyMap_.getKeys();\r\n for (var i = 0; i < keys.length; i++) {\r\n var key = keys[i];\r\n var encodedKey = goog.string.urlEncode(key);\r\n var val = this.getValues(key);\r\n for (var j = 0; j < val.length; j++) {\r\n var param = encodedKey;\r\n // Ensure that null and undefined are encoded into the url as\r\n // literal strings.\r\n if (val[j] !== '') {\r\n param += '=' + goog.string.urlEncode(val[j]);\r\n }\r\n sb.push(param);\r\n }\r\n }\r\n\r\n return this.encodedQuery_ = sb.join('&');\r\n};\r\n\r\n\r\n/**\r\n * @throws URIError If URI is malformed (that is, if decodeURIComponent fails on\r\n * any of the URI components).\r\n * @return {string} Decoded query string.\r\n */\r\ngoog.Uri.QueryData.prototype.toDecodedString = function() {\r\n return goog.Uri.decodeOrEmpty_(this.toString());\r\n};\r\n\r\n\r\n/**\r\n * Invalidate the cache.\r\n * @private\r\n */\r\ngoog.Uri.QueryData.prototype.invalidateCache_ = function() {\r\n this.encodedQuery_ = null;\r\n};\r\n\r\n\r\n/**\r\n * Removes all keys that are not in the provided list. (Modifies this object.)\r\n * @param {Array<string>} keys The desired keys.\r\n * @return {!goog.Uri.QueryData} a reference to this object.\r\n */\r\ngoog.Uri.QueryData.prototype.filterKeys = function(keys) {\r\n this.ensureKeyMapInitialized_();\r\n this.keyMap_.forEach(function(value, key) {\r\n if (!goog.array.contains(keys, key)) {\r\n this.remove(key);\r\n }\r\n }, this);\r\n return this;\r\n};\r\n\r\n\r\n/**\r\n * Clone the query data instance.\r\n * @return {!goog.Uri.QueryData} New instance of the QueryData object.\r\n */\r\ngoog.Uri.QueryData.prototype.clone = function() {\r\n var rv = new goog.Uri.QueryData();\r\n rv.encodedQuery_ = this.encodedQuery_;\r\n if (this.keyMap_) {\r\n rv.keyMap_ = this.keyMap_.clone();\r\n rv.count_ = this.count_;\r\n }\r\n return rv;\r\n};\r\n\r\n\r\n/**\r\n * Helper function to get the key name from a JavaScript object. Converts\r\n * the object to a string, and to lower case if necessary.\r\n * @private\r\n * @param {*} arg The object to get a key name from.\r\n * @return {string} valid key name which can be looked up in #keyMap_.\r\n */\r\ngoog.Uri.QueryData.prototype.getKeyName_ = function(arg) {\r\n var keyName = String(arg);\r\n if (this.ignoreCase_) {\r\n keyName = keyName.toLowerCase();\r\n }\r\n return keyName;\r\n};\r\n\r\n\r\n/**\r\n * Ignore case in parameter names.\r\n * NOTE: If there are already key/value pairs in the QueryData, and\r\n * ignoreCase_ is set to false, the keys will all be lower-cased.\r\n * @param {boolean} ignoreCase whether this goog.Uri should ignore case.\r\n */\r\ngoog.Uri.QueryData.prototype.setIgnoreCase = function(ignoreCase) {\r\n var resetKeys = ignoreCase && !this.ignoreCase_;\r\n if (resetKeys) {\r\n this.ensureKeyMapInitialized_();\r\n this.invalidateCache_();\r\n this.keyMap_.forEach(function(value, key) {\r\n var lowerCase = key.toLowerCase();\r\n if (key != lowerCase) {\r\n this.remove(key);\r\n this.setValues(lowerCase, value);\r\n }\r\n }, this);\r\n }\r\n this.ignoreCase_ = ignoreCase;\r\n};\r\n\r\n\r\n/**\r\n * Extends a query data object with another query data or map like object. This\r\n * operates 'in-place', it does not create a new QueryData object.\r\n *\r\n * @param {...(?goog.Uri.QueryData|?goog.structs.Map<?, ?>|?Object)} var_args\r\n * The object from which key value pairs will be copied. Note: does not\r\n * accept null.\r\n * @suppress {deprecated} Use deprecated goog.structs.forEach to allow different\r\n * types of parameters.\r\n */\r\ngoog.Uri.QueryData.prototype.extend = function(var_args) {\r\n for (var i = 0; i < arguments.length; i++) {\r\n var data = arguments[i];\r\n goog.structs.forEach(\r\n data, function(value, key) { this.add(key, value); }, this);\r\n }\r\n};\r\n","// Copyright 2006 The Closure Library Authors. All Rights Reserved.\r\n//\r\n// Licensed under the Apache License, Version 2.0 (the \"License\");\r\n// you may not use this file except in compliance with the License.\r\n// You may obtain a copy of the License at\r\n//\r\n// http://www.apache.org/licenses/LICENSE-2.0\r\n//\r\n// Unless required by applicable law or agreed to in writing, software\r\n// distributed under the License is distributed on an \"AS-IS\" BASIS,\r\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n// See the License for the specific language governing permissions and\r\n// limitations under the License.\r\n\r\n/**\r\n * @fileoverview Definition of various formatters for logging. Please minimize\r\n * dependencies this file has on other closure classes as any dependency it\r\n * takes won't be able to use the logging infrastructure.\r\n *\r\n */\r\n\r\ngoog.provide('goog.debug.Formatter');\r\ngoog.provide('goog.debug.HtmlFormatter');\r\ngoog.provide('goog.debug.TextFormatter');\r\n\r\ngoog.require('goog.debug');\r\ngoog.require('goog.debug.Logger');\r\ngoog.require('goog.debug.RelativeTimeProvider');\r\ngoog.require('goog.html.SafeHtml');\r\ngoog.require('goog.html.SafeUrl');\r\ngoog.require('goog.html.uncheckedconversions');\r\ngoog.require('goog.string.Const');\r\n\r\n\r\n\r\n/**\r\n * Base class for Formatters. A Formatter is used to format a LogRecord into\r\n * something that can be displayed to the user.\r\n *\r\n * @param {string=} opt_prefix The prefix to place before text records.\r\n * @constructor\r\n */\r\ngoog.debug.Formatter = function(opt_prefix) {\r\n this.prefix_ = opt_prefix || '';\r\n\r\n /**\r\n * A provider that returns the relative start time.\r\n * @type {goog.debug.RelativeTimeProvider}\r\n * @private\r\n */\r\n this.startTimeProvider_ =\r\n goog.debug.RelativeTimeProvider.getDefaultInstance();\r\n};\r\n\r\n\r\n/**\r\n * Whether to append newlines to the end of formatted log records.\r\n * @type {boolean}\r\n */\r\ngoog.debug.Formatter.prototype.appendNewline = true;\r\n\r\n\r\n/**\r\n * Whether to show absolute time in the DebugWindow.\r\n * @type {boolean}\r\n */\r\ngoog.debug.Formatter.prototype.showAbsoluteTime = true;\r\n\r\n\r\n/**\r\n * Whether to show relative time in the DebugWindow.\r\n * @type {boolean}\r\n */\r\ngoog.debug.Formatter.prototype.showRelativeTime = true;\r\n\r\n\r\n/**\r\n * Whether to show the logger name in the DebugWindow.\r\n * @type {boolean}\r\n */\r\ngoog.debug.Formatter.prototype.showLoggerName = true;\r\n\r\n\r\n/**\r\n * Whether to show the logger exception text.\r\n * @type {boolean}\r\n */\r\ngoog.debug.Formatter.prototype.showExceptionText = false;\r\n\r\n\r\n/**\r\n * Whether to show the severity level.\r\n * @type {boolean}\r\n */\r\ngoog.debug.Formatter.prototype.showSeverityLevel = false;\r\n\r\n\r\n/**\r\n * Formats a record.\r\n * @param {goog.debug.LogRecord} logRecord the logRecord to format.\r\n * @return {string} The formatted string.\r\n */\r\ngoog.debug.Formatter.prototype.formatRecord = goog.abstractMethod;\r\n\r\n\r\n/**\r\n * Formats a record as SafeHtml.\r\n * @param {goog.debug.LogRecord} logRecord the logRecord to format.\r\n * @return {!goog.html.SafeHtml} The formatted string as SafeHtml.\r\n */\r\ngoog.debug.Formatter.prototype.formatRecordAsHtml = goog.abstractMethod;\r\n\r\n\r\n/**\r\n * Sets the start time provider. By default, this is the default instance\r\n * but can be changed.\r\n * @param {goog.debug.RelativeTimeProvider} provider The provider to use.\r\n */\r\ngoog.debug.Formatter.prototype.setStartTimeProvider = function(provider) {\r\n this.startTimeProvider_ = provider;\r\n};\r\n\r\n\r\n/**\r\n * Returns the start time provider. By default, this is the default instance\r\n * but can be changed.\r\n * @return {goog.debug.RelativeTimeProvider} The start time provider.\r\n */\r\ngoog.debug.Formatter.prototype.getStartTimeProvider = function() {\r\n return this.startTimeProvider_;\r\n};\r\n\r\n\r\n/**\r\n * Resets the start relative time.\r\n */\r\ngoog.debug.Formatter.prototype.resetRelativeTimeStart = function() {\r\n this.startTimeProvider_.reset();\r\n};\r\n\r\n\r\n/**\r\n * Returns a string for the time/date of the LogRecord.\r\n * @param {goog.debug.LogRecord} logRecord The record to get a time stamp for.\r\n * @return {string} A string representation of the time/date of the LogRecord.\r\n * @private\r\n */\r\ngoog.debug.Formatter.getDateTimeStamp_ = function(logRecord) {\r\n var time = new Date(logRecord.getMillis());\r\n return goog.debug.Formatter.getTwoDigitString_((time.getFullYear() - 2000)) +\r\n goog.debug.Formatter.getTwoDigitString_((time.getMonth() + 1)) +\r\n goog.debug.Formatter.getTwoDigitString_(time.getDate()) + ' ' +\r\n goog.debug.Formatter.getTwoDigitString_(time.getHours()) + ':' +\r\n goog.debug.Formatter.getTwoDigitString_(time.getMinutes()) + ':' +\r\n goog.debug.Formatter.getTwoDigitString_(time.getSeconds()) + '.' +\r\n goog.debug.Formatter.getTwoDigitString_(\r\n Math.floor(time.getMilliseconds() / 10));\r\n};\r\n\r\n\r\n/**\r\n * Returns the number as a two-digit string, meaning it prepends a 0 if the\r\n * number if less than 10.\r\n * @param {number} n The number to format.\r\n * @return {string} A two-digit string representation of `n`.\r\n * @private\r\n */\r\ngoog.debug.Formatter.getTwoDigitString_ = function(n) {\r\n if (n < 10) {\r\n return '0' + n;\r\n }\r\n return String(n);\r\n};\r\n\r\n\r\n/**\r\n * Returns a string for the number of seconds relative to the start time.\r\n * Prepads with spaces so that anything less than 1000 seconds takes up the\r\n * same number of characters for better formatting.\r\n * @param {goog.debug.LogRecord} logRecord The log to compare time to.\r\n * @param {number} relativeTimeStart The start time to compare to.\r\n * @return {string} The number of seconds of the LogRecord relative to the\r\n * start time.\r\n * @private\r\n */\r\ngoog.debug.Formatter.getRelativeTime_ = function(logRecord, relativeTimeStart) {\r\n var ms = logRecord.getMillis() - relativeTimeStart;\r\n var sec = ms / 1000;\r\n var str = sec.toFixed(3);\r\n\r\n var spacesToPrepend = 0;\r\n if (sec < 1) {\r\n spacesToPrepend = 2;\r\n } else {\r\n while (sec < 100) {\r\n spacesToPrepend++;\r\n sec *= 10;\r\n }\r\n }\r\n while (spacesToPrepend-- > 0) {\r\n str = ' ' + str;\r\n }\r\n return str;\r\n};\r\n\r\n\r\n\r\n/**\r\n * Formatter that returns formatted html. See formatRecord for the classes\r\n * it uses for various types of formatted output.\r\n *\r\n * @param {string=} opt_prefix The prefix to place before text records.\r\n * @constructor\r\n * @extends {goog.debug.Formatter}\r\n */\r\ngoog.debug.HtmlFormatter = function(opt_prefix) {\r\n goog.debug.Formatter.call(this, opt_prefix);\r\n};\r\ngoog.inherits(goog.debug.HtmlFormatter, goog.debug.Formatter);\r\n\r\n\r\n/**\r\n * Exposes an exception that has been caught by a try...catch and outputs the\r\n * error as HTML with a stack trace.\r\n *\r\n * @param {*} err Error object or string.\r\n * @param {?Function=} fn If provided, when collecting the stack trace all\r\n * frames above the topmost call to this function, including that call,\r\n * will be left out of the stack trace.\r\n * @return {string} Details of exception, as HTML.\r\n */\r\ngoog.debug.HtmlFormatter.exposeException = function(err, fn) {\r\n var html = goog.debug.HtmlFormatter.exposeExceptionAsHtml(err, fn);\r\n return goog.html.SafeHtml.unwrap(html);\r\n};\r\n\r\n\r\n/**\r\n * Exposes an exception that has been caught by a try...catch and outputs the\r\n * error with a stack trace.\r\n *\r\n * @param {*} err Error object or string.\r\n * @param {?Function=} fn If provided, when collecting the stack trace all\r\n * frames above the topmost call to this function, including that call,\r\n * will be left out of the stack trace.\r\n * @return {!goog.html.SafeHtml} Details of exception.\r\n */\r\ngoog.debug.HtmlFormatter.exposeExceptionAsHtml = function(err, fn) {\r\n try {\r\n var e = goog.debug.normalizeErrorObject(err);\r\n // Create the error message\r\n var viewSourceUrl =\r\n goog.debug.HtmlFormatter.createViewSourceUrl_(e.fileName);\r\n var error = goog.html.SafeHtml.concat(\r\n goog.html.SafeHtml.htmlEscapePreservingNewlinesAndSpaces(\r\n 'Message: ' + e.message + '\\nUrl: '),\r\n goog.html.SafeHtml.create(\r\n 'a', {href: viewSourceUrl, target: '_new'}, e.fileName),\r\n goog.html.SafeHtml.htmlEscapePreservingNewlinesAndSpaces(\r\n '\\nLine: ' + e.lineNumber + '\\n\\nBrowser stack:\\n' + e.stack +\r\n '-> ' +\r\n '[end]\\n\\nJS stack traversal:\\n' + goog.debug.getStacktrace(fn) +\r\n '-> '));\r\n return error;\r\n } catch (e2) {\r\n return goog.html.SafeHtml.htmlEscapePreservingNewlinesAndSpaces(\r\n 'Exception trying to expose exception! You win, we lose. ' + e2);\r\n }\r\n};\r\n\r\n\r\n/**\r\n * @param {?string=} fileName\r\n * @return {!goog.html.SafeUrl} SafeUrl with view-source scheme, pointing at\r\n * fileName.\r\n * @private\r\n */\r\ngoog.debug.HtmlFormatter.createViewSourceUrl_ = function(fileName) {\r\n if (!goog.isDefAndNotNull(fileName)) {\r\n fileName = '';\r\n }\r\n if (!/^https?:\\/\\//i.test(fileName)) {\r\n return goog.html.SafeUrl.fromConstant(\r\n goog.string.Const.from('sanitizedviewsrc'));\r\n }\r\n var sanitizedFileName = goog.html.SafeUrl.sanitize(fileName);\r\n return goog.html.uncheckedconversions\r\n .safeUrlFromStringKnownToSatisfyTypeContract(\r\n goog.string.Const.from('view-source scheme plus HTTP/HTTPS URL'),\r\n 'view-source:' + goog.html.SafeUrl.unwrap(sanitizedFileName));\r\n};\r\n\r\n\r\n\r\n/**\r\n * Whether to show the logger exception text\r\n * @type {boolean}\r\n * @override\r\n */\r\ngoog.debug.HtmlFormatter.prototype.showExceptionText = true;\r\n\r\n\r\n/**\r\n * Formats a record\r\n * @param {goog.debug.LogRecord} logRecord the logRecord to format.\r\n * @return {string} The formatted string as html.\r\n * @override\r\n */\r\ngoog.debug.HtmlFormatter.prototype.formatRecord = function(logRecord) {\r\n if (!logRecord) {\r\n return '';\r\n }\r\n // OK not to use goog.html.SafeHtml.unwrap() here.\r\n return this.formatRecordAsHtml(logRecord).getTypedStringValue();\r\n};\r\n\r\n\r\n/**\r\n * Formats a record.\r\n * @param {goog.debug.LogRecord} logRecord the logRecord to format.\r\n * @return {!goog.html.SafeHtml} The formatted string as SafeHtml.\r\n * @override\r\n */\r\ngoog.debug.HtmlFormatter.prototype.formatRecordAsHtml = function(logRecord) {\r\n if (!logRecord) {\r\n return goog.html.SafeHtml.EMPTY;\r\n }\r\n\r\n var className;\r\n switch (logRecord.getLevel().value) {\r\n case goog.debug.Logger.Level.SHOUT.value:\r\n className = 'dbg-sh';\r\n break;\r\n case goog.debug.Logger.Level.SEVERE.value:\r\n className = 'dbg-sev';\r\n break;\r\n case goog.debug.Logger.Level.WARNING.value:\r\n className = 'dbg-w';\r\n break;\r\n case goog.debug.Logger.Level.INFO.value:\r\n className = 'dbg-i';\r\n break;\r\n case goog.debug.Logger.Level.FINE.value:\r\n default:\r\n className = 'dbg-f';\r\n break;\r\n }\r\n\r\n // HTML for user defined prefix, time, logger name, and severity.\r\n var sb = [];\r\n sb.push(this.prefix_, ' ');\r\n if (this.showAbsoluteTime) {\r\n sb.push('[', goog.debug.Formatter.getDateTimeStamp_(logRecord), '] ');\r\n }\r\n if (this.showRelativeTime) {\r\n sb.push(\r\n '[', goog.debug.Formatter.getRelativeTime_(\r\n logRecord, this.startTimeProvider_.get()),\r\n 's] ');\r\n }\r\n if (this.showLoggerName) {\r\n sb.push('[', logRecord.getLoggerName(), '] ');\r\n }\r\n if (this.showSeverityLevel) {\r\n sb.push('[', logRecord.getLevel().name, '] ');\r\n }\r\n var fullPrefixHtml =\r\n goog.html.SafeHtml.htmlEscapePreservingNewlinesAndSpaces(sb.join(''));\r\n\r\n // HTML for exception text and log record.\r\n var exceptionHtml = goog.html.SafeHtml.EMPTY;\r\n if (this.showExceptionText && logRecord.getException()) {\r\n exceptionHtml = goog.html.SafeHtml.concat(\r\n goog.html.SafeHtml.BR,\r\n goog.debug.HtmlFormatter.exposeExceptionAsHtml(\r\n logRecord.getException()));\r\n }\r\n var logRecordHtml = goog.html.SafeHtml.htmlEscapePreservingNewlinesAndSpaces(\r\n logRecord.getMessage());\r\n var recordAndExceptionHtml = goog.html.SafeHtml.create(\r\n 'span', {'class': className},\r\n goog.html.SafeHtml.concat(logRecordHtml, exceptionHtml));\r\n\r\n\r\n // Combine both pieces of HTML and, if needed, append a final newline.\r\n var html;\r\n if (this.appendNewline) {\r\n html = goog.html.SafeHtml.concat(\r\n fullPrefixHtml, recordAndExceptionHtml, goog.html.SafeHtml.BR);\r\n } else {\r\n html = goog.html.SafeHtml.concat(fullPrefixHtml, recordAndExceptionHtml);\r\n }\r\n return html;\r\n};\r\n\r\n\r\n\r\n/**\r\n * Formatter that returns formatted plain text\r\n *\r\n * @param {string=} opt_prefix The prefix to place before text records.\r\n * @constructor\r\n * @extends {goog.debug.Formatter}\r\n * @final\r\n */\r\ngoog.debug.TextFormatter = function(opt_prefix) {\r\n goog.debug.Formatter.call(this, opt_prefix);\r\n};\r\ngoog.inherits(goog.debug.TextFormatter, goog.debug.Formatter);\r\n\r\n\r\n/**\r\n * Formats a record as text\r\n * @param {goog.debug.LogRecord} logRecord the logRecord to format.\r\n * @return {string} The formatted string.\r\n * @override\r\n */\r\ngoog.debug.TextFormatter.prototype.formatRecord = function(logRecord) {\r\n var sb = [];\r\n sb.push(this.prefix_, ' ');\r\n if (this.showAbsoluteTime) {\r\n sb.push('[', goog.debug.Formatter.getDateTimeStamp_(logRecord), '] ');\r\n }\r\n if (this.showRelativeTime) {\r\n sb.push(\r\n '[', goog.debug.Formatter.getRelativeTime_(\r\n logRecord, this.startTimeProvider_.get()),\r\n 's] ');\r\n }\r\n\r\n if (this.showLoggerName) {\r\n sb.push('[', logRecord.getLoggerName(), '] ');\r\n }\r\n if (this.showSeverityLevel) {\r\n sb.push('[', logRecord.getLevel().name, '] ');\r\n }\r\n sb.push(logRecord.getMessage());\r\n if (this.showExceptionText) {\r\n var exception = logRecord.getException();\r\n if (exception) {\r\n var exceptionText =\r\n exception instanceof Error ? exception.message : exception.toString();\r\n sb.push('\\n', exceptionText);\r\n }\r\n }\r\n if (this.appendNewline) {\r\n sb.push('\\n');\r\n }\r\n return sb.join('');\r\n};\r\n\r\n\r\n/**\r\n * Formats a record as text\r\n * @param {goog.debug.LogRecord} logRecord the logRecord to format.\r\n * @return {!goog.html.SafeHtml} The formatted string as SafeHtml. This is\r\n * just an HTML-escaped version of the text obtained from formatRecord().\r\n * @override\r\n */\r\ngoog.debug.TextFormatter.prototype.formatRecordAsHtml = function(logRecord) {\r\n return goog.html.SafeHtml.htmlEscapePreservingNewlinesAndSpaces(\r\n goog.debug.TextFormatter.prototype.formatRecord(logRecord));\r\n};\r\n","// Copyright 2006 The Closure Library Authors. All Rights Reserved.\r\n//\r\n// Licensed under the Apache License, Version 2.0 (the \"License\");\r\n// you may not use this file except in compliance with the License.\r\n// You may obtain a copy of the License at\r\n//\r\n// http://www.apache.org/licenses/LICENSE-2.0\r\n//\r\n// Unless required by applicable law or agreed to in writing, software\r\n// distributed under the License is distributed on an \"AS-IS\" BASIS,\r\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n// See the License for the specific language governing permissions and\r\n// limitations under the License.\r\n\r\n/**\r\n * @fileoverview Base TestChannel implementation.\r\n *\r\n */\r\n\r\n\r\ngoog.provide('goog.labs.net.webChannel.BaseTestChannel');\r\n\r\ngoog.require('goog.labs.net.webChannel.Channel');\r\ngoog.require('goog.labs.net.webChannel.ChannelRequest');\r\ngoog.require('goog.labs.net.webChannel.WebChannelDebug');\r\ngoog.require('goog.labs.net.webChannel.requestStats');\r\ngoog.require('goog.net.WebChannel');\r\n\r\ngoog.forwardDeclare('goog.labs.net.webChannel.WebChannelBase');\r\n\r\n\r\n\r\n/**\r\n * A TestChannel is used during the first part of channel negotiation\r\n * with the server to create the channel. It helps us determine whether we're\r\n * behind a buffering proxy.\r\n *\r\n * @constructor\r\n * @struct\r\n * @param {!goog.labs.net.webChannel.Channel} channel The channel\r\n * that owns this test channel.\r\n * @param {!goog.labs.net.webChannel.WebChannelDebug} channelDebug A\r\n * WebChannelDebug instance to use for logging.\r\n * @implements {goog.labs.net.webChannel.Channel}\r\n */\r\ngoog.labs.net.webChannel.BaseTestChannel = function(channel, channelDebug) {\r\n /**\r\n * The channel that owns this test channel\r\n * @private {!goog.labs.net.webChannel.Channel}\r\n */\r\n this.channel_ = channel;\r\n\r\n /**\r\n * The channel debug to use for logging\r\n * @private {!goog.labs.net.webChannel.WebChannelDebug}\r\n */\r\n this.channelDebug_ = channelDebug;\r\n\r\n /**\r\n * Extra HTTP headers to add to all the requests sent to the server.\r\n * @private {Object}\r\n */\r\n this.extraHeaders_ = null;\r\n\r\n /**\r\n * The test request.\r\n * @private {goog.labs.net.webChannel.ChannelRequest}\r\n */\r\n this.request_ = null;\r\n\r\n /**\r\n * Whether we have received the first result as an intermediate result. This\r\n * helps us determine whether we're behind a buffering proxy.\r\n * @private {boolean}\r\n */\r\n this.receivedIntermediateResult_ = false;\r\n\r\n /**\r\n * The relative path for test requests.\r\n * @private {?string}\r\n */\r\n this.path_ = null;\r\n\r\n /**\r\n * The last status code received.\r\n * @private {number}\r\n */\r\n this.lastStatusCode_ = -1;\r\n\r\n /**\r\n * A subdomain prefix for using a subdomain in IE for the backchannel\r\n * requests.\r\n * @private {?string}\r\n */\r\n this.hostPrefix_ = null;\r\n\r\n /**\r\n * The effective client protocol as indicated by the initial handshake\r\n * response via the x-client-wire-protocol header.\r\n *\r\n * @private {?string}\r\n */\r\n this.clientProtocol_ = null;\r\n};\r\n\r\n\r\ngoog.scope(function() {\r\nvar WebChannel = goog.net.WebChannel;\r\nvar BaseTestChannel = goog.labs.net.webChannel.BaseTestChannel;\r\nvar WebChannelDebug = goog.labs.net.webChannel.WebChannelDebug;\r\nvar ChannelRequest = goog.labs.net.webChannel.ChannelRequest;\r\nvar requestStats = goog.labs.net.webChannel.requestStats;\r\nvar Channel = goog.labs.net.webChannel.Channel;\r\n\r\n\r\n/**\r\n * Enum type for the test channel state machine\r\n * @enum {number}\r\n * @private\r\n */\r\nBaseTestChannel.State_ = {\r\n /**\r\n * The state for the TestChannel state machine where we making the\r\n * initial call to get the server configured parameters.\r\n */\r\n INIT: 0,\r\n\r\n /**\r\n * The state for the TestChannel state machine where we're checking to\r\n * se if we're behind a buffering proxy.\r\n */\r\n CONNECTION_TESTING: 1\r\n};\r\n\r\n\r\n/**\r\n * The state of the state machine for this object.\r\n *\r\n * @private {?BaseTestChannel.State_}\r\n */\r\nBaseTestChannel.prototype.state_ = null;\r\n\r\n\r\n/**\r\n * Sets extra HTTP headers to add to all the requests sent to the server.\r\n *\r\n * @param {Object} extraHeaders The HTTP headers.\r\n */\r\nBaseTestChannel.prototype.setExtraHeaders = function(extraHeaders) {\r\n this.extraHeaders_ = extraHeaders;\r\n};\r\n\r\n\r\n/**\r\n * Starts the test channel. This initiates connections to the server.\r\n *\r\n * @param {string} path The relative uri for the test connection.\r\n */\r\nBaseTestChannel.prototype.connect = function(path) {\r\n this.path_ = path;\r\n var sendDataUri = this.channel_.getForwardChannelUri(this.path_);\r\n\r\n requestStats.notifyStatEvent(requestStats.Stat.TEST_STAGE_ONE_START);\r\n\r\n // If the channel already has the result of the handshake, then skip it.\r\n var handshakeResult = this.channel_.getConnectionState().handshakeResult;\r\n if (goog.isDefAndNotNull(handshakeResult)) {\r\n this.hostPrefix_ = this.channel_.correctHostPrefix(handshakeResult[0]);\r\n this.state_ = BaseTestChannel.State_.CONNECTION_TESTING;\r\n this.checkBufferingProxy_();\r\n return;\r\n }\r\n\r\n // the first request returns server specific parameters\r\n sendDataUri.setParameterValues('MODE', 'init');\r\n\r\n // http-session-id to be generated as the response\r\n if (!this.channel_.getBackgroundChannelTest() &&\r\n this.channel_.getHttpSessionIdParam()) {\r\n sendDataUri.setParameterValues(WebChannel.X_HTTP_SESSION_ID,\r\n this.channel_.getHttpSessionIdParam());\r\n }\r\n\r\n this.request_ = ChannelRequest.createChannelRequest(this, this.channelDebug_);\r\n\r\n this.request_.setExtraHeaders(this.extraHeaders_);\r\n\r\n this.request_.xmlHttpGet(\r\n sendDataUri, false /* decodeChunks */, null /* hostPrefix */);\r\n this.state_ = BaseTestChannel.State_.INIT;\r\n};\r\n\r\n\r\n/**\r\n * Begins the second stage of the test channel where we test to see if we're\r\n * behind a buffering proxy. The server sends back a multi-chunked response\r\n * with the first chunk containing the content '1' and then two seconds later\r\n * sending the second chunk containing the content '2'. Depending on how we\r\n * receive the content, we can tell if we're behind a buffering proxy.\r\n * @private\r\n */\r\nBaseTestChannel.prototype.checkBufferingProxy_ = function() {\r\n this.channelDebug_.debug('TestConnection: starting stage 2');\r\n\r\n // If the test result is already available, skip its execution.\r\n var bufferingProxyResult =\r\n this.channel_.getConnectionState().bufferingProxyResult;\r\n if (goog.isDefAndNotNull(bufferingProxyResult)) {\r\n this.channelDebug_.debug(function() {\r\n return 'TestConnection: skipping stage 2, precomputed result is ' +\r\n bufferingProxyResult ?\r\n 'Buffered' :\r\n 'Unbuffered';\r\n });\r\n requestStats.notifyStatEvent(requestStats.Stat.TEST_STAGE_TWO_START);\r\n if (bufferingProxyResult) { // Buffered/Proxy connection\r\n requestStats.notifyStatEvent(requestStats.Stat.PROXY);\r\n this.channel_.testConnectionFinished(this, false);\r\n } else { // Unbuffered/NoProxy connection\r\n requestStats.notifyStatEvent(requestStats.Stat.NOPROXY);\r\n this.channel_.testConnectionFinished(this, true);\r\n }\r\n return; // Skip the test\r\n }\r\n this.request_ = ChannelRequest.createChannelRequest(this, this.channelDebug_);\r\n this.request_.setExtraHeaders(this.extraHeaders_);\r\n var recvDataUri = this.channel_.getBackChannelUri(\r\n this.hostPrefix_,\r\n /** @type {string} */ (this.path_));\r\n\r\n requestStats.notifyStatEvent(requestStats.Stat.TEST_STAGE_TWO_START);\r\n recvDataUri.setParameterValues('TYPE', 'xmlhttp');\r\n\r\n var param = this.channel_.getHttpSessionIdParam();\r\n var value = this.channel_.getHttpSessionId();\r\n if (param && value) {\r\n recvDataUri.setParameterValue(param, value);\r\n }\r\n\r\n this.request_.xmlHttpGet(\r\n recvDataUri, false /** decodeChunks */, this.hostPrefix_);\r\n};\r\n\r\n\r\n/**\r\n * @override\r\n */\r\nBaseTestChannel.prototype.createXhrIo = function(hostPrefix) {\r\n return this.channel_.createXhrIo(hostPrefix);\r\n};\r\n\r\n\r\n/**\r\n * Aborts the test channel.\r\n */\r\nBaseTestChannel.prototype.abort = function() {\r\n if (this.request_) {\r\n this.request_.cancel();\r\n this.request_ = null;\r\n }\r\n this.lastStatusCode_ = -1;\r\n};\r\n\r\n\r\n/**\r\n * Returns whether the test channel is closed. The ChannelRequest object expects\r\n * this method to be implemented on its handler.\r\n *\r\n * @return {boolean} Whether the channel is closed.\r\n * @override\r\n */\r\nBaseTestChannel.prototype.isClosed = function() {\r\n return false;\r\n};\r\n\r\n\r\n/**\r\n * Callback from ChannelRequest for when new data is received\r\n *\r\n * @param {ChannelRequest} req The request object.\r\n * @param {string} responseText The text of the response.\r\n * @override\r\n */\r\nBaseTestChannel.prototype.onRequestData = function(req, responseText) {\r\n this.lastStatusCode_ = req.getLastStatusCode();\r\n if (this.state_ == BaseTestChannel.State_.INIT) {\r\n this.channelDebug_.debug('TestConnection: Got data for stage 1');\r\n\r\n this.applyControlHeaders_(req);\r\n\r\n if (!responseText) {\r\n this.channelDebug_.debug('TestConnection: Null responseText');\r\n // The server should always send text; something is wrong here\r\n this.channel_.testConnectionFailure(this, ChannelRequest.Error.BAD_DATA);\r\n return;\r\n }\r\n\r\n\r\n try {\r\n var channel = /** @type {!goog.labs.net.webChannel.WebChannelBase} */ (\r\n this.channel_);\r\n var respArray = channel.getWireCodec().decodeMessage(responseText);\r\n } catch (e) {\r\n this.channelDebug_.dumpException(e);\r\n this.channel_.testConnectionFailure(this, ChannelRequest.Error.BAD_DATA);\r\n return;\r\n }\r\n this.hostPrefix_ = this.channel_.correctHostPrefix(respArray[0]);\r\n } else if (this.state_ == BaseTestChannel.State_.CONNECTION_TESTING) {\r\n if (this.receivedIntermediateResult_) {\r\n requestStats.notifyStatEvent(requestStats.Stat.TEST_STAGE_TWO_DATA_TWO);\r\n } else {\r\n // '11111' is used instead of '1' to prevent a small amount of buffering\r\n // by Safari.\r\n if (responseText == '11111') {\r\n requestStats.notifyStatEvent(requestStats.Stat.TEST_STAGE_TWO_DATA_ONE);\r\n this.receivedIntermediateResult_ = true;\r\n if (this.checkForEarlyNonBuffered_()) {\r\n // If early chunk detection is on, and we passed the tests,\r\n // assume HTTP_OK, cancel the test and turn on noproxy mode.\r\n this.lastStatusCode_ = 200;\r\n this.request_.cancel();\r\n this.channelDebug_.debug(\r\n 'Test connection succeeded; using streaming connection');\r\n requestStats.notifyStatEvent(requestStats.Stat.NOPROXY);\r\n this.channel_.testConnectionFinished(this, true);\r\n }\r\n } else {\r\n requestStats.notifyStatEvent(\r\n requestStats.Stat.TEST_STAGE_TWO_DATA_BOTH);\r\n this.receivedIntermediateResult_ = false;\r\n }\r\n }\r\n }\r\n};\r\n\r\n\r\n/**\r\n * Callback from ChannelRequest that indicates a request has completed.\r\n *\r\n * @param {!ChannelRequest} req The request object.\r\n * @override\r\n */\r\nBaseTestChannel.prototype.onRequestComplete = function(req) {\r\n this.lastStatusCode_ = this.request_.getLastStatusCode();\r\n if (!this.request_.getSuccess()) {\r\n this.channelDebug_.debug(\r\n 'TestConnection: request failed, in state ' + this.state_);\r\n if (this.state_ == BaseTestChannel.State_.INIT) {\r\n requestStats.notifyStatEvent(requestStats.Stat.TEST_STAGE_ONE_FAILED);\r\n } else if (this.state_ == BaseTestChannel.State_.CONNECTION_TESTING) {\r\n requestStats.notifyStatEvent(requestStats.Stat.TEST_STAGE_TWO_FAILED);\r\n }\r\n this.channel_.testConnectionFailure(\r\n this,\r\n /** @type {ChannelRequest.Error} */\r\n (this.request_.getLastError()));\r\n return;\r\n }\r\n\r\n if (this.state_ == BaseTestChannel.State_.INIT) {\r\n this.state_ = BaseTestChannel.State_.CONNECTION_TESTING;\r\n\r\n this.channelDebug_.debug(\r\n 'TestConnection: request complete for initial check');\r\n\r\n this.checkBufferingProxy_();\r\n } else if (this.state_ == BaseTestChannel.State_.CONNECTION_TESTING) {\r\n this.channelDebug_.debug('TestConnection: request complete for stage 2');\r\n\r\n var goodConn = this.receivedIntermediateResult_;\r\n if (goodConn) {\r\n this.channelDebug_.debug(\r\n 'Test connection succeeded; using streaming connection');\r\n requestStats.notifyStatEvent(requestStats.Stat.NOPROXY);\r\n this.channel_.testConnectionFinished(this, true);\r\n } else {\r\n this.channelDebug_.debug('Test connection failed; not using streaming');\r\n requestStats.notifyStatEvent(requestStats.Stat.PROXY);\r\n this.channel_.testConnectionFinished(this, false);\r\n }\r\n }\r\n};\r\n\r\n\r\n/**\r\n * Apply any control headers from the initial handshake response.\r\n *\r\n * @param {!ChannelRequest} req The request object.\r\n * @private\r\n */\r\nBaseTestChannel.prototype.applyControlHeaders_ = function(req) {\r\n if (this.channel_.getBackgroundChannelTest()) {\r\n return;\r\n }\r\n\r\n var xhr = req.getXhr();\r\n if (xhr) {\r\n var protocolHeader = xhr.getStreamingResponseHeader(\r\n WebChannel.X_CLIENT_WIRE_PROTOCOL);\r\n this.clientProtocol_ = protocolHeader ? protocolHeader : null;\r\n\r\n if (this.channel_.getHttpSessionIdParam()) {\r\n var httpSessionIdHeader = xhr.getStreamingResponseHeader(\r\n WebChannel.X_HTTP_SESSION_ID);\r\n if (httpSessionIdHeader) {\r\n this.channel_.setHttpSessionId(httpSessionIdHeader);\r\n } else {\r\n this.channelDebug_.warning(\r\n 'Missing X_HTTP_SESSION_ID in the handshake response');\r\n }\r\n }\r\n }\r\n};\r\n\r\n\r\n/**\r\n * @return {?string} The client protocol as recorded with the init handshake\r\n * request.\r\n */\r\nBaseTestChannel.prototype.getClientProtocol = function() {\r\n return this.clientProtocol_;\r\n};\r\n\r\n\r\n/**\r\n * Returns the last status code received for a request.\r\n * @return {number} The last status code received for a request.\r\n */\r\nBaseTestChannel.prototype.getLastStatusCode = function() {\r\n return this.lastStatusCode_;\r\n};\r\n\r\n\r\n/**\r\n * @return {boolean} Whether we should be using secondary domains when the\r\n * server instructs us to do so.\r\n * @override\r\n */\r\nBaseTestChannel.prototype.shouldUseSecondaryDomains = function() {\r\n return this.channel_.shouldUseSecondaryDomains();\r\n};\r\n\r\n\r\n/**\r\n * @override\r\n */\r\nBaseTestChannel.prototype.isActive = function() {\r\n return this.channel_.isActive();\r\n};\r\n\r\n\r\n/**\r\n * @return {boolean} True if test stage 2 detected a non-buffered\r\n * channel early and early no buffering detection is enabled.\r\n * @private\r\n */\r\nBaseTestChannel.prototype.checkForEarlyNonBuffered_ = function() {\r\n return ChannelRequest.supportsXhrStreaming();\r\n};\r\n\r\n\r\n/**\r\n * @override\r\n */\r\nBaseTestChannel.prototype.getForwardChannelUri = goog.abstractMethod;\r\n\r\n\r\n/**\r\n * @override\r\n */\r\nBaseTestChannel.prototype.getBackChannelUri = goog.abstractMethod;\r\n\r\n\r\n/**\r\n * @override\r\n */\r\nBaseTestChannel.prototype.correctHostPrefix = goog.abstractMethod;\r\n\r\n\r\n/**\r\n * @override\r\n */\r\nBaseTestChannel.prototype.createDataUri = goog.abstractMethod;\r\n\r\n\r\n/**\r\n * @override\r\n */\r\nBaseTestChannel.prototype.testConnectionFinished = goog.abstractMethod;\r\n\r\n\r\n/**\r\n * @override\r\n */\r\nBaseTestChannel.prototype.testConnectionFailure = goog.abstractMethod;\r\n\r\n\r\n/**\r\n * @override\r\n */\r\nBaseTestChannel.prototype.getConnectionState = goog.abstractMethod;\r\n\r\n\r\n/**\r\n * @override\r\n */\r\nBaseTestChannel.prototype.setHttpSessionIdParam = goog.abstractMethod;\r\n\r\n\r\n/**\r\n * @override\r\n */\r\nBaseTestChannel.prototype.getHttpSessionIdParam = goog.abstractMethod;\r\n\r\n\r\n/**\r\n * @override\r\n */\r\nBaseTestChannel.prototype.setHttpSessionId = goog.abstractMethod;\r\n\r\n\r\n/**\r\n * @override\r\n */\r\nBaseTestChannel.prototype.getHttpSessionId = goog.abstractMethod;\r\n\r\n\r\n/**\r\n * @override\r\n */\r\nBaseTestChannel.prototype.getBackgroundChannelTest = goog.abstractMethod;\r\n}); // goog.scope\r\n","// Copyright 2013 The Closure Library Authors. All Rights Reserved.\r\n//\r\n// Licensed under the Apache License, Version 2.0 (the \"License\");\r\n// you may not use this file except in compliance with the License.\r\n// You may obtain a copy of the License at\r\n//\r\n// http://www.apache.org/licenses/LICENSE-2.0\r\n//\r\n// Unless required by applicable law or agreed to in writing, software\r\n// distributed under the License is distributed on an \"AS-IS\" BASIS,\r\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n// See the License for the specific language governing permissions and\r\n// limitations under the License.\r\n\r\n/**\r\n * @fileoverview Codec functions of the v8 wire protocol. Eventually we'd want\r\n * to support pluggable wire-format to improve wire efficiency and to enable\r\n * binary encoding. Such support will require an interface class, which\r\n * will be added later.\r\n */\r\n\r\n\r\ngoog.provide('goog.labs.net.webChannel.WireV8');\r\n\r\ngoog.require('goog.asserts');\r\ngoog.require('goog.json');\r\ngoog.require('goog.json.NativeJsonProcessor');\r\ngoog.require('goog.labs.net.webChannel.Wire');\r\ngoog.require('goog.structs');\r\n\r\ngoog.forwardDeclare('goog.structs.Map');\r\n\r\n\r\n\r\n/**\r\n * The v8 codec class.\r\n *\r\n * @constructor\r\n * @struct\r\n */\r\ngoog.labs.net.webChannel.WireV8 = function() {\r\n /**\r\n * Parser for a response payload. The parser should return an array.\r\n * @private {!goog.string.Parser}\r\n */\r\n this.parser_ = new goog.json.NativeJsonProcessor();\r\n};\r\n\r\n\r\ngoog.scope(function() {\r\nvar WireV8 = goog.labs.net.webChannel.WireV8;\r\nvar Wire = goog.labs.net.webChannel.Wire;\r\n\r\n\r\n/**\r\n * Encodes a standalone message into the wire format.\r\n *\r\n * May throw exception if the message object contains any invalid elements.\r\n *\r\n * @param {!Object|!goog.structs.Map} message The message data.\r\n * V8 only support JS objects (or Map).\r\n * @param {!Array<string>} buffer The text buffer to write the message to.\r\n * @param {string=} opt_prefix The prefix for each field of the object.\r\n */\r\nWireV8.prototype.encodeMessage = function(message, buffer, opt_prefix) {\r\n var prefix = opt_prefix || '';\r\n try {\r\n goog.structs.forEach(message, function(value, key) {\r\n var encodedValue = value;\r\n if (goog.isObject(value)) {\r\n encodedValue = goog.json.serialize(value);\r\n } // keep the fast-path for primitive types\r\n buffer.push(prefix + key + '=' + encodeURIComponent(encodedValue));\r\n });\r\n } catch (ex) {\r\n // We send a map here because lots of the retry logic relies on map IDs,\r\n // so we have to send something (possibly redundant).\r\n buffer.push(\r\n prefix + 'type' +\r\n '=' + encodeURIComponent('_badmap'));\r\n throw ex;\r\n }\r\n};\r\n\r\n\r\n/**\r\n * Encodes all the buffered messages of the forward channel.\r\n *\r\n * @param {!Array<Wire.QueuedMap>} messageQueue The message data.\r\n * V8 only support JS objects.\r\n * @param {number} count The number of messages to be encoded.\r\n * @param {?function(!Object)} badMapHandler Callback for bad messages.\r\n * @return {string} the encoded messages\r\n */\r\nWireV8.prototype.encodeMessageQueue = function(\r\n messageQueue, count, badMapHandler) {\r\n var offset = -1;\r\n while (true) {\r\n var sb = ['count=' + count];\r\n // To save a bit of bandwidth, specify the base mapId and the rest as\r\n // offsets from it.\r\n if (offset == -1) {\r\n if (count > 0) {\r\n offset = messageQueue[0].mapId;\r\n sb.push('ofs=' + offset);\r\n } else {\r\n offset = 0;\r\n }\r\n } else {\r\n sb.push('ofs=' + offset);\r\n }\r\n var done = true;\r\n for (var i = 0; i < count; i++) {\r\n var mapId = messageQueue[i].mapId;\r\n var map = messageQueue[i].map;\r\n mapId -= offset;\r\n if (mapId < 0) {\r\n // redo the encoding in case of retry/reordering, plus extra space\r\n offset = Math.max(0, messageQueue[i].mapId - 100);\r\n done = false;\r\n continue;\r\n }\r\n try {\r\n this.encodeMessage(map, sb, 'req' + mapId + '_');\r\n } catch (ex) {\r\n if (badMapHandler) {\r\n badMapHandler(map);\r\n }\r\n }\r\n }\r\n if (done) {\r\n return sb.join('&');\r\n }\r\n }\r\n};\r\n\r\n\r\n/**\r\n * Decodes a standalone message received from the wire. May throw exception\r\n * if text is ill-formatted.\r\n *\r\n * Must be valid JSON as it is insecure to use eval() to decode JS literals;\r\n * and eval() is disallowed in Chrome apps too.\r\n *\r\n * Invalid JS literals include null array elements, quotas etc.\r\n *\r\n * @param {string} messageText The string content as received from the wire.\r\n * @return {*} The decoded message object.\r\n */\r\nWireV8.prototype.decodeMessage = function(messageText) {\r\n var response = this.parser_.parse(messageText);\r\n goog.asserts.assert(goog.isArray(response)); // throw exception\r\n return response;\r\n};\r\n}); // goog.scope\r\n","// Copyright 2013 The Closure Library Authors. All Rights Reserved.\r\n//\r\n// Licensed under the Apache License, Version 2.0 (the \"License\");\r\n// you may not use this file except in compliance with the License.\r\n// You may obtain a copy of the License at\r\n//\r\n// http://www.apache.org/licenses/LICENSE-2.0\r\n//\r\n// Unless required by applicable law or agreed to in writing, software\r\n// distributed under the License is distributed on an \"AS-IS\" BASIS,\r\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n// See the License for the specific language governing permissions and\r\n// limitations under the License.\r\n\r\n/**\r\n * @fileoverview This class manages the network connectivity state.\r\n */\r\n\r\n\r\ngoog.provide('goog.labs.net.webChannel.ConnectionState');\r\n\r\n\r\n\r\n/**\r\n * The connectivity state of the channel.\r\n *\r\n * @constructor\r\n * @struct\r\n */\r\ngoog.labs.net.webChannel.ConnectionState = function() {\r\n /**\r\n * Handshake result.\r\n * @type {Array<string>}\r\n */\r\n this.handshakeResult = null;\r\n\r\n /**\r\n * The result of checking if there is a buffering proxy in the network.\r\n * True means the connection is buffered, False means unbuffered,\r\n * null means that the result is not available.\r\n * @type {?boolean}\r\n */\r\n this.bufferingProxyResult = null;\r\n};\r\n","// Copyright 2006 The Closure Library Authors. All Rights Reserved.\r\n//\r\n// Licensed under the Apache License, Version 2.0 (the \"License\");\r\n// you may not use this file except in compliance with the License.\r\n// You may obtain a copy of the License at\r\n//\r\n// http://www.apache.org/licenses/LICENSE-2.0\r\n//\r\n// Unless required by applicable law or agreed to in writing, software\r\n// distributed under the License is distributed on an \"AS-IS\" BASIS,\r\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n// See the License for the specific language governing permissions and\r\n// limitations under the License.\r\n\r\n/**\r\n * @fileoverview Datastructure: Set.\r\n *\r\n * @author arv@google.com (Erik Arvidsson)\r\n *\r\n * This class implements a set data structure. Adding and removing is O(1). It\r\n * supports both object and primitive values. Be careful because you can add\r\n * both 1 and new Number(1), because these are not the same. You can even add\r\n * multiple new Number(1) because these are not equal.\r\n */\r\n\r\n\r\ngoog.provide('goog.structs.Set');\r\n\r\ngoog.require('goog.structs');\r\ngoog.require('goog.structs.Collection');\r\ngoog.require('goog.structs.Map');\r\n\r\n/**\r\n * A set that can contain both primitives and objects. Adding and removing\r\n * elements is O(1). Primitives are treated as identical if they have the same\r\n * type and convert to the same string. Objects are treated as identical only\r\n * if they are references to the same object. WARNING: A goog.structs.Set can\r\n * contain both 1 and (new Number(1)), because they are not the same. WARNING:\r\n * Adding (new Number(1)) twice will yield two distinct elements, because they\r\n * are two different objects. WARNING: Any object that is added to a\r\n * goog.structs.Set will be modified! Because goog.getUid() is used to\r\n * identify objects, every object in the set will be mutated.\r\n * @param {Array<T>|Object<?,T>=} opt_values Initial values to start with.\r\n * @constructor\r\n * @implements {goog.structs.Collection<T>}\r\n * @final\r\n * @template T\r\n * @deprecated This type is misleading: use ES6 Set instead.\r\n */\r\ngoog.structs.Set = function(opt_values) {\r\n this.map_ = new goog.structs.Map;\r\n if (opt_values) {\r\n this.addAll(opt_values);\r\n }\r\n};\r\n\r\n/**\r\n * A function that returns a unique id.\r\n * @private @const {function(?Object): number}\r\n */\r\ngoog.structs.Set.getUid_ = goog.getUid;\r\n\r\n\r\n/**\r\n * Obtains a unique key for an element of the set. Primitives will yield the\r\n * same key if they have the same type and convert to the same string. Object\r\n * references will yield the same key only if they refer to the same object.\r\n * @param {*} val Object or primitive value to get a key for.\r\n * @return {string} A unique key for this value/object.\r\n * @private\r\n */\r\ngoog.structs.Set.getKey_ = function(val) {\r\n var type = typeof val;\r\n if (type == 'object' && val || type == 'function') {\r\n return 'o' + goog.structs.Set.getUid_(/** @type {Object} */ (val));\r\n } else {\r\n return type.substr(0, 1) + val;\r\n }\r\n};\r\n\r\n\r\n/**\r\n * @return {number} The number of elements in the set.\r\n * @override\r\n */\r\ngoog.structs.Set.prototype.getCount = function() {\r\n return this.map_.getCount();\r\n};\r\n\r\n\r\n/**\r\n * Add a primitive or an object to the set.\r\n * @param {T} element The primitive or object to add.\r\n * @override\r\n */\r\ngoog.structs.Set.prototype.add = function(element) {\r\n this.map_.set(goog.structs.Set.getKey_(element), element);\r\n};\r\n\r\n\r\n/**\r\n * Adds all the values in the given collection to this set.\r\n * @param {Array<T>|goog.structs.Collection<T>|Object<?,T>} col A collection\r\n * containing the elements to add.\r\n */\r\ngoog.structs.Set.prototype.addAll = function(col) {\r\n var values = goog.structs.getValues(col);\r\n var l = values.length;\r\n for (var i = 0; i < l; i++) {\r\n this.add(values[i]);\r\n }\r\n};\r\n\r\n\r\n/**\r\n * Removes all values in the given collection from this set.\r\n * @param {Array<T>|goog.structs.Collection<T>|Object<?,T>} col A collection\r\n * containing the elements to remove.\r\n */\r\ngoog.structs.Set.prototype.removeAll = function(col) {\r\n var values = goog.structs.getValues(col);\r\n var l = values.length;\r\n for (var i = 0; i < l; i++) {\r\n this.remove(values[i]);\r\n }\r\n};\r\n\r\n\r\n/**\r\n * Removes the given element from this set.\r\n * @param {T} element The primitive or object to remove.\r\n * @return {boolean} Whether the element was found and removed.\r\n * @override\r\n */\r\ngoog.structs.Set.prototype.remove = function(element) {\r\n return this.map_.remove(goog.structs.Set.getKey_(element));\r\n};\r\n\r\n\r\n/**\r\n * Removes all elements from this set.\r\n */\r\ngoog.structs.Set.prototype.clear = function() {\r\n this.map_.clear();\r\n};\r\n\r\n\r\n/**\r\n * Tests whether this set is empty.\r\n * @return {boolean} True if there are no elements in this set.\r\n */\r\ngoog.structs.Set.prototype.isEmpty = function() {\r\n return this.map_.isEmpty();\r\n};\r\n\r\n\r\n/**\r\n * Tests whether this set contains the given element.\r\n * @param {T} element The primitive or object to test for.\r\n * @return {boolean} True if this set contains the given element.\r\n * @override\r\n */\r\ngoog.structs.Set.prototype.contains = function(element) {\r\n return this.map_.containsKey(goog.structs.Set.getKey_(element));\r\n};\r\n\r\n\r\n/**\r\n * Tests whether this set contains all the values in a given collection.\r\n * Repeated elements in the collection are ignored, e.g. (new\r\n * goog.structs.Set([1, 2])).containsAll([1, 1]) is True.\r\n * @param {goog.structs.Collection<T>|Object} col A collection-like object.\r\n * @return {boolean} True if the set contains all elements.\r\n */\r\ngoog.structs.Set.prototype.containsAll = function(col) {\r\n return goog.structs.every(col, this.contains, this);\r\n};\r\n\r\n\r\n/**\r\n * Finds all values that are present in both this set and the given collection.\r\n * @param {Array<S>|Object<?,S>} col A collection.\r\n * @return {!goog.structs.Set<T|S>} A new set containing all the values\r\n * (primitives or objects) present in both this set and the given\r\n * collection.\r\n * @template S\r\n */\r\ngoog.structs.Set.prototype.intersection = function(col) {\r\n var result = new goog.structs.Set();\r\n\r\n var values = goog.structs.getValues(col);\r\n for (var i = 0; i < values.length; i++) {\r\n var value = values[i];\r\n if (this.contains(value)) {\r\n result.add(value);\r\n }\r\n }\r\n\r\n return result;\r\n};\r\n\r\n\r\n/**\r\n * Finds all values that are present in this set and not in the given\r\n * collection.\r\n * @param {Array<T>|goog.structs.Collection<T>|Object<?,T>} col A collection.\r\n * @return {!goog.structs.Set} A new set containing all the values\r\n * (primitives or objects) present in this set but not in the given\r\n * collection.\r\n */\r\ngoog.structs.Set.prototype.difference = function(col) {\r\n var result = this.clone();\r\n result.removeAll(col);\r\n return result;\r\n};\r\n\r\n\r\n/**\r\n * Returns an array containing all the elements in this set.\r\n * @return {!Array<T>} An array containing all the elements in this set.\r\n */\r\ngoog.structs.Set.prototype.getValues = function() {\r\n return this.map_.getValues();\r\n};\r\n\r\n\r\n/**\r\n * Creates a shallow clone of this set.\r\n * @return {!goog.structs.Set<T>} A new set containing all the same elements as\r\n * this set.\r\n */\r\ngoog.structs.Set.prototype.clone = function() {\r\n return new goog.structs.Set(this);\r\n};\r\n\r\n\r\n/**\r\n * Tests whether the given collection consists of the same elements as this set,\r\n * regardless of order, without repetition. Primitives are treated as equal if\r\n * they have the same type and convert to the same string; objects are treated\r\n * as equal if they are references to the same object. This operation is O(n).\r\n * @param {goog.structs.Collection<T>|Object} col A collection.\r\n * @return {boolean} True if the given collection consists of the same elements\r\n * as this set, regardless of order, without repetition.\r\n */\r\ngoog.structs.Set.prototype.equals = function(col) {\r\n return this.getCount() == goog.structs.getCount(col) && this.isSubsetOf(col);\r\n};\r\n\r\n\r\n/**\r\n * Tests whether the given collection contains all the elements in this set.\r\n * Primitives are treated as equal if they have the same type and convert to the\r\n * same string; objects are treated as equal if they are references to the same\r\n * object. This operation is O(n).\r\n * @param {goog.structs.Collection<T>|Object} col A collection.\r\n * @return {boolean} True if this set is a subset of the given collection.\r\n */\r\ngoog.structs.Set.prototype.isSubsetOf = function(col) {\r\n var colCount = goog.structs.getCount(col);\r\n if (this.getCount() > colCount) {\r\n return false;\r\n }\r\n // TODO(user) Find the minimal collection size where the conversion makes\r\n // the contains() method faster.\r\n if (!(col instanceof goog.structs.Set) && colCount > 5) {\r\n // Convert to a goog.structs.Set so that goog.structs.contains runs in\r\n // O(1) time instead of O(n) time.\r\n col = new goog.structs.Set(col);\r\n }\r\n return goog.structs.every(\r\n this, function(value) { return goog.structs.contains(col, value); });\r\n};\r\n\r\n\r\n/**\r\n * Returns an iterator that iterates over the elements in this set.\r\n * @param {boolean=} opt_keys This argument is ignored.\r\n * @return {!goog.iter.Iterator} An iterator over the elements in this set.\r\n */\r\ngoog.structs.Set.prototype.__iterator__ = function(opt_keys) {\r\n return this.map_.__iterator__(false);\r\n};\r\n","// Copyright 2013 The Closure Library Authors. All Rights Reserved.\r\n//\r\n// Licensed under the Apache License, Version 2.0 (the \"License\");\r\n// you may not use this file except in compliance with the License.\r\n// You may obtain a copy of the License at\r\n//\r\n// http://www.apache.org/licenses/LICENSE-2.0\r\n//\r\n// Unless required by applicable law or agreed to in writing, software\r\n// distributed under the License is distributed on an \"AS-IS\" BASIS,\r\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n// See the License for the specific language governing permissions and\r\n// limitations under the License.\r\n\r\n/**\r\n * @fileoverview Interface and shared data structures for implementing\r\n * different wire protocol versions.\r\n */\r\n\r\n\r\ngoog.provide('goog.labs.net.webChannel.Wire');\r\n\r\ngoog.forwardDeclare('goog.structs.Map');\r\n\r\n\r\n\r\n/**\r\n * The interface class.\r\n *\r\n * @interface\r\n */\r\ngoog.labs.net.webChannel.Wire = function() {};\r\n\r\n\r\ngoog.scope(function() {\r\nvar Wire = goog.labs.net.webChannel.Wire;\r\n\r\n\r\n/**\r\n * The latest protocol version that this class supports. We request this version\r\n * from the server when opening the connection. Should match\r\n * LATEST_CHANNEL_VERSION on the server code.\r\n * @type {number}\r\n */\r\nWire.LATEST_CHANNEL_VERSION = 8;\r\n\r\n\r\n/**\r\n * The JSON field key for the raw data wrapper object.\r\n * @type {string}\r\n */\r\nWire.RAW_DATA_KEY = '__data__';\r\n\r\n\r\n\r\n/**\r\n * Simple container class for a (mapId, map) pair.\r\n * @param {number} mapId The id for this map.\r\n * @param {!Object|!goog.structs.Map} map The map itself.\r\n * @param {!Object=} opt_context The context associated with the map.\r\n * @constructor\r\n * @struct\r\n */\r\nWire.QueuedMap = function(mapId, map, opt_context) {\r\n /**\r\n * The id for this map.\r\n * @type {number}\r\n */\r\n this.mapId = mapId;\r\n\r\n /**\r\n * The map itself.\r\n * @type {!Object|!goog.structs.Map}\r\n */\r\n this.map = map;\r\n\r\n /**\r\n * The context for the map.\r\n * @type {Object}\r\n */\r\n this.context = opt_context || null;\r\n};\r\n\r\n\r\n/**\r\n * @return {number|undefined} the size of the raw JSON message or\r\n * undefined if the message is not encoded as a raw JSON message\r\n */\r\nWire.QueuedMap.prototype.getRawDataSize = function() {\r\n if (Wire.RAW_DATA_KEY in this.map) {\r\n var data = this.map[Wire.RAW_DATA_KEY];\r\n if (goog.isString(data)) {\r\n return data.length;\r\n }\r\n }\r\n\r\n return undefined;\r\n};\r\n}); // goog.scope\r\n","// Copyright 2013 The Closure Library Authors. All Rights Reserved.\r\n//\r\n// Licensed under the Apache License, Version 2.0 (the \"License\");\r\n// you may not use this file except in compliance with the License.\r\n// You may obtain a copy of the License at\r\n//\r\n// http://www.apache.org/licenses/LICENSE-2.0\r\n//\r\n// Unless required by applicable law or agreed to in writing, software\r\n// distributed under the License is distributed on an \"AS-IS\" BASIS,\r\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n// See the License for the specific language governing permissions and\r\n// limitations under the License.\r\n\r\n/**\r\n * @fileoverview A pool of forward channel requests to enable real-time\r\n * messaging from the client to server.\r\n */\r\n\r\ngoog.module('goog.labs.net.webChannel.ForwardChannelRequestPool');\r\n\r\ngoog.module.declareLegacyNamespace();\r\n\r\nvar ChannelRequest = goog.require('goog.labs.net.webChannel.ChannelRequest');\r\nvar Set = goog.require('goog.structs.Set');\r\nvar Wire = goog.require('goog.labs.net.webChannel.Wire');\r\nvar array = goog.require('goog.array');\r\nvar googString = goog.require('goog.string');\r\n\r\n\r\n/**\r\n * This class represents the state of all forward channel requests.\r\n *\r\n * @param {number=} opt_maxPoolSize The maximum pool size.\r\n *\r\n * @struct @constructor @final\r\n */\r\nvar ForwardChannelRequestPool = function(opt_maxPoolSize) {\r\n /**\r\n * The max pool size as configured.\r\n *\r\n * @private {number}\r\n */\r\n this.maxPoolSizeConfigured_ =\r\n opt_maxPoolSize || ForwardChannelRequestPool.MAX_POOL_SIZE_;\r\n\r\n /**\r\n * The current size limit of the request pool. This limit is meant to be\r\n * read-only after the channel is fully opened.\r\n *\r\n * If SPDY or HTTP2 is enabled, set it to the max pool size, which is also\r\n * configurable.\r\n *\r\n * @private {number}\r\n */\r\n this.maxSize_ = ForwardChannelRequestPool.isSpdyOrHttp2Enabled_() ?\r\n this.maxPoolSizeConfigured_ :\r\n 1;\r\n\r\n /**\r\n * The container for all the pending request objects.\r\n *\r\n * @private {Set<ChannelRequest>}\r\n */\r\n this.requestPool_ = null;\r\n\r\n if (this.maxSize_ > 1) {\r\n this.requestPool_ = new Set();\r\n }\r\n\r\n /**\r\n * The single request object when the pool size is limited to one.\r\n *\r\n * @private {ChannelRequest}\r\n */\r\n this.request_ = null;\r\n\r\n /**\r\n * Saved pending messages when the pool is cancelled.\r\n *\r\n * @private {!Array<Wire.QueuedMap>}\r\n */\r\n this.pendingMessages_ = [];\r\n};\r\n\r\n\r\n/**\r\n * The default size limit of the request pool.\r\n *\r\n * @private {number}\r\n */\r\nForwardChannelRequestPool.MAX_POOL_SIZE_ = 10;\r\n\r\n\r\n/**\r\n * @return {boolean} True if SPDY or HTTP2 is enabled. Uses chrome-specific APIs\r\n * as a fallback and will always return false for other browsers where\r\n * PerformanceNavigationTiming is not available.\r\n * @private\r\n */\r\nForwardChannelRequestPool.isSpdyOrHttp2Enabled_ = function() {\r\n if (goog.global.PerformanceNavigationTiming) {\r\n var entrys = /** @type {!Array<!PerformanceNavigationTiming>} */ (\r\n goog.global.performance.getEntriesByType('navigation'));\r\n return entrys.length > 0 &&\r\n (entrys[0].nextHopProtocol == 'hq' ||\r\n entrys[0].nextHopProtocol == 'h2');\r\n }\r\n return !!(\r\n goog.global.chrome && goog.global.chrome.loadTimes &&\r\n goog.global.chrome.loadTimes() &&\r\n goog.global.chrome.loadTimes().wasFetchedViaSpdy);\r\n};\r\n\r\n\r\n/**\r\n * Once we know the client protocol (from the handshake), check if we need\r\n * enable the request pool accordingly. This is more robust than using\r\n * browser-internal APIs (specific to Chrome).\r\n *\r\n * @param {string} clientProtocol The client protocol\r\n */\r\nForwardChannelRequestPool.prototype.applyClientProtocol = function(\r\n clientProtocol) {\r\n if (this.requestPool_) {\r\n return;\r\n }\r\n\r\n if (googString.contains(clientProtocol, 'spdy') ||\r\n googString.contains(clientProtocol, 'quic') ||\r\n googString.contains(clientProtocol, 'h2')) {\r\n this.maxSize_ = this.maxPoolSizeConfigured_;\r\n this.requestPool_ = new Set();\r\n if (this.request_) {\r\n this.addRequest(this.request_);\r\n this.request_ = null;\r\n }\r\n }\r\n};\r\n\r\n\r\n/**\r\n * @return {boolean} True if the pool is full.\r\n */\r\nForwardChannelRequestPool.prototype.isFull = function() {\r\n if (this.request_) {\r\n return true;\r\n }\r\n\r\n if (this.requestPool_) {\r\n return this.requestPool_.getCount() >= this.maxSize_;\r\n }\r\n\r\n return false;\r\n};\r\n\r\n\r\n/**\r\n * @return {number} The current size limit.\r\n */\r\nForwardChannelRequestPool.prototype.getMaxSize = function() {\r\n return this.maxSize_;\r\n};\r\n\r\n\r\n/**\r\n * @return {number} The number of pending requests in the pool.\r\n */\r\nForwardChannelRequestPool.prototype.getRequestCount = function() {\r\n if (this.request_) {\r\n return 1;\r\n }\r\n\r\n if (this.requestPool_) {\r\n return this.requestPool_.getCount();\r\n }\r\n\r\n return 0;\r\n};\r\n\r\n\r\n/**\r\n * @param {ChannelRequest} req The channel request.\r\n * @return {boolean} True if the request is a included inside the pool.\r\n */\r\nForwardChannelRequestPool.prototype.hasRequest = function(req) {\r\n if (this.request_) {\r\n return this.request_ == req;\r\n }\r\n\r\n if (this.requestPool_) {\r\n return this.requestPool_.contains(req);\r\n }\r\n\r\n return false;\r\n};\r\n\r\n\r\n/**\r\n * Adds a new request to the pool.\r\n *\r\n * @param {!ChannelRequest} req The new channel request.\r\n */\r\nForwardChannelRequestPool.prototype.addRequest = function(req) {\r\n if (this.requestPool_) {\r\n this.requestPool_.add(req);\r\n } else {\r\n this.request_ = req;\r\n }\r\n};\r\n\r\n\r\n/**\r\n * Removes the given request from the pool.\r\n *\r\n * @param {ChannelRequest} req The channel request.\r\n * @return {boolean} Whether the request has been removed from the pool.\r\n */\r\nForwardChannelRequestPool.prototype.removeRequest = function(req) {\r\n if (this.request_ && this.request_ == req) {\r\n this.request_ = null;\r\n return true;\r\n }\r\n\r\n if (this.requestPool_ && this.requestPool_.contains(req)) {\r\n this.requestPool_.remove(req);\r\n return true;\r\n }\r\n\r\n return false;\r\n};\r\n\r\n\r\n/**\r\n * Clears the pool and cancel all the pending requests.\r\n */\r\nForwardChannelRequestPool.prototype.cancel = function() {\r\n // save any pending messages\r\n this.pendingMessages_ = this.getPendingMessages();\r\n\r\n if (this.request_) {\r\n this.request_.cancel();\r\n this.request_ = null;\r\n return;\r\n }\r\n\r\n if (this.requestPool_ && !this.requestPool_.isEmpty()) {\r\n array.forEach(this.requestPool_.getValues(), function(val) {\r\n val.cancel();\r\n });\r\n this.requestPool_.clear();\r\n }\r\n};\r\n\r\n\r\n/**\r\n * @return {boolean} Whether there are any pending requests.\r\n */\r\nForwardChannelRequestPool.prototype.hasPendingRequest = function() {\r\n return (this.request_ != null) ||\r\n (this.requestPool_ != null && !this.requestPool_.isEmpty());\r\n};\r\n\r\n\r\n/**\r\n * @return {!Array<Wire.QueuedMap>} All the pending messages from the pool,\r\n * as a new array.\r\n */\r\nForwardChannelRequestPool.prototype.getPendingMessages = function() {\r\n if (this.request_ != null) {\r\n return this.pendingMessages_.concat(this.request_.getPendingMessages());\r\n }\r\n\r\n if (this.requestPool_ != null && !this.requestPool_.isEmpty()) {\r\n var result = this.pendingMessages_;\r\n array.forEach(this.requestPool_.getValues(), function(val) {\r\n result = result.concat(val.getPendingMessages());\r\n });\r\n return result;\r\n }\r\n\r\n return array.clone(this.pendingMessages_);\r\n};\r\n\r\n\r\n/**\r\n * Records pending messages, e.g. when a request receives a failed response.\r\n *\r\n * @param {!Array<Wire.QueuedMap>} messages Pending messages.\r\n */\r\nForwardChannelRequestPool.prototype.addPendingMessages = function(messages) {\r\n this.pendingMessages_ = this.pendingMessages_.concat(messages);\r\n};\r\n\r\n\r\n/**\r\n * Clears any recorded pending messages.\r\n */\r\nForwardChannelRequestPool.prototype.clearPendingMessages = function() {\r\n this.pendingMessages_.length = 0;\r\n};\r\n\r\n\r\n/**\r\n * Cancels all pending requests and force the completion of channel requests.\r\n *\r\n * Need go through the standard onRequestComplete logic to expose the max-retry\r\n * failure in the standard way.\r\n *\r\n * @param {function(!ChannelRequest)} onComplete The completion callback.\r\n * @return {boolean} true if any request has been forced to complete.\r\n */\r\nForwardChannelRequestPool.prototype.forceComplete = function(onComplete) {\r\n if (this.request_ != null) {\r\n this.request_.cancel();\r\n onComplete(this.request_);\r\n return true;\r\n }\r\n\r\n if (this.requestPool_ && !this.requestPool_.isEmpty()) {\r\n array.forEach(this.requestPool_.getValues(), function(val) {\r\n val.cancel();\r\n onComplete(val);\r\n });\r\n return true;\r\n }\r\n\r\n return false;\r\n};\r\n\r\nexports = ForwardChannelRequestPool;\r\n","// Copyright 2012 The Closure Library Authors. All Rights Reserved.\r\n//\r\n// Licensed under the Apache License, Version 2.0 (the \"License\");\r\n// you may not use this file except in compliance with the License.\r\n// You may obtain a copy of the License at\r\n//\r\n// http://www.apache.org/licenses/LICENSE-2.0\r\n//\r\n// Unless required by applicable law or agreed to in writing, software\r\n// distributed under the License is distributed on an \"AS-IS\" BASIS,\r\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n// See the License for the specific language governing permissions and\r\n// limitations under the License.\r\n\r\n\r\n/**\r\n * @fileoverview Defines a class for parsing JSON using the browser's built in\r\n * JSON library.\r\n */\r\n\r\ngoog.provide('goog.json.NativeJsonProcessor');\r\n\r\ngoog.require('goog.asserts');\r\ngoog.require('goog.json.Processor');\r\n\r\n\r\n\r\n/**\r\n * A class that parses and stringifies JSON using the browser's built-in JSON\r\n * library, if it is available.\r\n *\r\n * Note that the native JSON api has subtle differences across browsers, so\r\n * use this implementation with care. See json_test#assertSerialize\r\n * for details on the differences from goog.json.\r\n *\r\n * This implementation is signficantly faster than goog.json, at least on\r\n * Chrome. See json_perf.html for a perf test showing the difference.\r\n *\r\n * @param {?goog.json.Replacer=} opt_replacer An optional replacer to use during\r\n * serialization.\r\n * @param {?goog.json.Reviver=} opt_reviver An optional reviver to use during\r\n * parsing.\r\n * @constructor\r\n * @implements {goog.json.Processor}\r\n * @final\r\n */\r\ngoog.json.NativeJsonProcessor = function(opt_replacer, opt_reviver) {\r\n goog.asserts.assert(goog.isDef(goog.global['JSON']), 'JSON not defined');\r\n\r\n /**\r\n * @type {goog.json.Replacer|null|undefined}\r\n * @private\r\n */\r\n this.replacer_ = opt_replacer;\r\n\r\n /**\r\n * @type {goog.json.Reviver|null|undefined}\r\n * @private\r\n */\r\n this.reviver_ = opt_reviver;\r\n};\r\n\r\n\r\n/** @override */\r\ngoog.json.NativeJsonProcessor.prototype.stringify = function(object) {\r\n return goog.global['JSON'].stringify(object, this.replacer_);\r\n};\r\n\r\n\r\n/** @override */\r\ngoog.json.NativeJsonProcessor.prototype.parse = function(s) {\r\n return goog.global['JSON'].parse(s, this.reviver_);\r\n};\r\n","// Copyright 2013 The Closure Library Authors. All Rights Reserved.\r\n//\r\n// Licensed under the Apache License, Version 2.0 (the \"License\");\r\n// you may not use this file except in compliance with the License.\r\n// You may obtain a copy of the License at\r\n//\r\n// http://www.apache.org/licenses/LICENSE-2.0\r\n//\r\n// Unless required by applicable law or agreed to in writing, software\r\n// distributed under the License is distributed on an \"AS-IS\" BASIS,\r\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n// See the License for the specific language governing permissions and\r\n// limitations under the License.\r\n\r\n/**\r\n * @fileoverview Utility functions for managing networking, such as\r\n * testing network connectivity.\r\n */\r\n\r\n\r\ngoog.provide('goog.labs.net.webChannel.netUtils');\r\n\r\ngoog.require('goog.Uri');\r\ngoog.require('goog.labs.net.webChannel.WebChannelDebug');\r\n\r\ngoog.scope(function() {\r\nvar netUtils = goog.labs.net.webChannel.netUtils;\r\nvar WebChannelDebug = goog.labs.net.webChannel.WebChannelDebug;\r\n\r\n\r\n/**\r\n * Default timeout to allow for URI pings.\r\n * @type {number}\r\n */\r\nnetUtils.NETWORK_TIMEOUT = 10000;\r\n\r\n\r\n/**\r\n * Pings the network with an image URI to check if an error is a server error\r\n * or user's network error.\r\n *\r\n * The caller needs to add a 'rand' parameter to make sure the response is\r\n * not fulfilled by browser cache.\r\n *\r\n * @param {function(boolean)} callback The function to call back with results.\r\n * @param {goog.Uri=} opt_imageUri The URI (of an image) to use for the network\r\n * test.\r\n */\r\nnetUtils.testNetwork = function(callback, opt_imageUri) {\r\n var uri = opt_imageUri;\r\n if (!uri) {\r\n // default google.com image\r\n uri = new goog.Uri('//www.google.com/images/cleardot.gif');\r\n\r\n if (!(goog.global.location && goog.global.location.protocol == 'http')) {\r\n uri.setScheme('https'); // e.g. chrome-extension\r\n }\r\n uri.makeUnique();\r\n }\r\n\r\n netUtils.testLoadImage(uri.toString(), netUtils.NETWORK_TIMEOUT, callback);\r\n};\r\n\r\n\r\n/**\r\n * Test loading the given image, retrying if necessary.\r\n * @param {string} url URL to the image.\r\n * @param {number} timeout Milliseconds before giving up.\r\n * @param {function(boolean)} callback Function to call with results.\r\n * @param {number} retries The number of times to retry.\r\n * @param {!WebChannelDebug} channelDebug The debug object\r\n * @param {number=} opt_pauseBetweenRetriesMS Optional number of milliseconds\r\n * between retries - defaults to 0.\r\n */\r\nnetUtils.testLoadImageWithRetries = function(\r\n url, timeout, callback, retries, channelDebug, opt_pauseBetweenRetriesMS) {\r\n channelDebug.debug('TestLoadImageWithRetries: ' + opt_pauseBetweenRetriesMS);\r\n if (retries == 0) {\r\n // no more retries, give up\r\n callback(false);\r\n return;\r\n }\r\n\r\n var pauseBetweenRetries = opt_pauseBetweenRetriesMS || 0;\r\n retries--;\r\n netUtils.testLoadImage(url, timeout, function(succeeded) {\r\n if (succeeded) {\r\n callback(true);\r\n } else {\r\n // try again\r\n goog.global.setTimeout(function() {\r\n netUtils.testLoadImageWithRetries(\r\n url, timeout, callback, retries, channelDebug, pauseBetweenRetries);\r\n }, pauseBetweenRetries);\r\n }\r\n });\r\n};\r\n\r\n\r\n/**\r\n * Test loading the given image.\r\n * @param {string} url URL to the image.\r\n * @param {number} timeout Milliseconds before giving up.\r\n * @param {function(boolean)} callback Function to call with results.\r\n * @suppress {strictMissingProperties} Part of the go/strict_warnings_migration\r\n */\r\nnetUtils.testLoadImage = function(url, timeout, callback) {\r\n var channelDebug = new WebChannelDebug();\r\n channelDebug.debug('TestLoadImage: loading ' + url);\r\n if (goog.global.Image) {\r\n var img = new Image();\r\n img.onload = goog.partial(\r\n netUtils.imageCallback_, channelDebug, img, 'TestLoadImage: loaded',\r\n true, callback);\r\n img.onerror = goog.partial(\r\n netUtils.imageCallback_, channelDebug, img, 'TestLoadImage: error',\r\n false, callback);\r\n img.onabort = goog.partial(\r\n netUtils.imageCallback_, channelDebug, img, 'TestLoadImage: abort',\r\n false, callback);\r\n img.ontimeout = goog.partial(\r\n netUtils.imageCallback_, channelDebug, img, 'TestLoadImage: timeout',\r\n false, callback);\r\n\r\n goog.global.setTimeout(function() {\r\n if (img.ontimeout) {\r\n img.ontimeout();\r\n }\r\n }, timeout);\r\n img.src = url;\r\n } else {\r\n // log ERROR_OTHER from environements where Image is not supported\r\n callback(false);\r\n }\r\n};\r\n\r\n\r\n/**\r\n * Wrap the image callback with debug and cleanup logic.\r\n * @param {!WebChannelDebug} channelDebug The WebChannelDebug object.\r\n * @param {!Image} img The image element.\r\n * @param {string} debugText The debug text.\r\n * @param {boolean} result The result of image loading.\r\n * @param {function(boolean)} callback The image callback.\r\n * @private\r\n */\r\nnetUtils.imageCallback_ = function(\r\n channelDebug, img, debugText, result, callback) {\r\n try {\r\n channelDebug.debug(debugText);\r\n netUtils.clearImageCallbacks_(img);\r\n callback(result);\r\n } catch (e) {\r\n channelDebug.dumpException(e);\r\n }\r\n};\r\n\r\n\r\n/**\r\n * Clears handlers to avoid memory leaks.\r\n * @param {Image} img The image to clear handlers from.\r\n * @private\r\n * @suppress {strictMissingProperties} Part of the go/strict_warnings_migration\r\n */\r\nnetUtils.clearImageCallbacks_ = function(img) {\r\n img.onload = null;\r\n img.onerror = null;\r\n img.onabort = null;\r\n img.ontimeout = null;\r\n};\r\n}); // goog.scope\r\n","// Copyright 2013 The Closure Library Authors. All Rights Reserved.\r\n//\r\n// Licensed under the Apache License, Version 2.0 (the \"License\");\r\n// you may not use this file except in compliance with the License.\r\n// You may obtain a copy of the License at\r\n//\r\n// http://www.apache.org/licenses/LICENSE-2.0\r\n//\r\n// Unless required by applicable law or agreed to in writing, software\r\n// distributed under the License is distributed on an \"AS-IS\" BASIS,\r\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n// See the License for the specific language governing permissions and\r\n// limitations under the License.\r\n\r\n\r\n/**\r\n * @fileoverview Utility to attempt native JSON processing, falling back to\r\n * goog.json if not available.\r\n *\r\n * This is intended as a drop-in for current users of goog.json who want\r\n * to take advantage of native JSON if present.\r\n *\r\n * @author nnaze@google.com (Nathan Naze)\r\n */\r\n\r\ngoog.provide('goog.json.hybrid');\r\n\r\ngoog.require('goog.asserts');\r\ngoog.require('goog.json');\r\n\r\n\r\n/**\r\n * Attempts to serialize the JSON string natively, falling back to\r\n * `goog.json.serialize` if unsuccessful.\r\n * @param {!Object} obj JavaScript object to serialize to JSON.\r\n * @return {string} Resulting JSON string.\r\n */\r\ngoog.json.hybrid.stringify =\r\n goog.json.USE_NATIVE_JSON ? goog.global['JSON']['stringify'] : function(\r\n obj) {\r\n if (goog.global.JSON) {\r\n try {\r\n return goog.global.JSON.stringify(obj);\r\n } catch (e) {\r\n // Native serialization failed. Fall through to retry with\r\n // goog.json.serialize.\r\n }\r\n }\r\n\r\n return goog.json.serialize(obj);\r\n };\r\n\r\n\r\n/**\r\n * Attempts to parse the JSON string natively, falling back to\r\n * the supplied `fallbackParser` if unsuccessful.\r\n * @param {string} jsonString JSON string to parse.\r\n * @param {function(string):Object} fallbackParser Fallback JSON parser used\r\n * if native\r\n * @return {?Object} Resulting JSON object.\r\n * @private\r\n */\r\ngoog.json.hybrid.parse_ = function(jsonString, fallbackParser) {\r\n if (goog.global.JSON) {\r\n try {\r\n var obj = goog.global.JSON.parse(jsonString);\r\n goog.asserts.assert(typeof obj == 'object');\r\n return /** @type {?Object} */ (obj);\r\n } catch (e) {\r\n // Native parse failed. Fall through to retry with goog.json.parse.\r\n }\r\n }\r\n\r\n return fallbackParser(jsonString);\r\n};\r\n\r\n\r\n/**\r\n * Attempts to parse the JSON string natively, falling back to\r\n * `goog.json.parse` if unsuccessful.\r\n * @param {string} jsonString JSON string to parse.\r\n * @return {?Object} Resulting JSON object.\r\n */\r\ngoog.json.hybrid.parse =\r\n goog.json.USE_NATIVE_JSON ? goog.global['JSON']['parse'] : function(\r\n jsonString) {\r\n return goog.json.hybrid.parse_(jsonString, goog.json.parse);\r\n };\r\n","// Copyright 2011 The Closure Library Authors. All Rights Reserved.\r\n//\r\n// Licensed under the Apache License, Version 2.0 (the \"License\");\r\n// you may not use this file except in compliance with the License.\r\n// You may obtain a copy of the License at\r\n//\r\n// http://www.apache.org/licenses/LICENSE-2.0\r\n//\r\n// Unless required by applicable law or agreed to in writing, software\r\n// distributed under the License is distributed on an \"AS-IS\" BASIS,\r\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n// See the License for the specific language governing permissions and\r\n// limitations under the License.\r\n\r\n/**\r\n * @fileoverview Constants for HTTP status codes.\r\n */\r\n\r\ngoog.provide('goog.net.HttpStatus');\r\n\r\n\r\n/**\r\n * HTTP Status Codes defined in RFC 2616, RFC 6585, RFC 4918 and RFC 7538.\r\n * @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html\r\n * @see http://tools.ietf.org/html/rfc6585\r\n * @see https://tools.ietf.org/html/rfc4918\r\n * @see https://tools.ietf.org/html/rfc7538\r\n * @enum {number}\r\n */\r\ngoog.net.HttpStatus = {\r\n // Informational 1xx\r\n CONTINUE: 100,\r\n SWITCHING_PROTOCOLS: 101,\r\n\r\n // Successful 2xx\r\n OK: 200,\r\n CREATED: 201,\r\n ACCEPTED: 202,\r\n NON_AUTHORITATIVE_INFORMATION: 203,\r\n NO_CONTENT: 204,\r\n RESET_CONTENT: 205,\r\n PARTIAL_CONTENT: 206,\r\n MULTI_STATUS: 207,\r\n\r\n // Redirection 3xx\r\n MULTIPLE_CHOICES: 300,\r\n MOVED_PERMANENTLY: 301,\r\n FOUND: 302,\r\n SEE_OTHER: 303,\r\n NOT_MODIFIED: 304,\r\n USE_PROXY: 305,\r\n TEMPORARY_REDIRECT: 307,\r\n PERMANENT_REDIRECT: 308,\r\n\r\n // Client Error 4xx\r\n BAD_REQUEST: 400,\r\n UNAUTHORIZED: 401,\r\n PAYMENT_REQUIRED: 402,\r\n FORBIDDEN: 403,\r\n NOT_FOUND: 404,\r\n METHOD_NOT_ALLOWED: 405,\r\n NOT_ACCEPTABLE: 406,\r\n PROXY_AUTHENTICATION_REQUIRED: 407,\r\n REQUEST_TIMEOUT: 408,\r\n CONFLICT: 409,\r\n GONE: 410,\r\n LENGTH_REQUIRED: 411,\r\n PRECONDITION_FAILED: 412,\r\n REQUEST_ENTITY_TOO_LARGE: 413,\r\n REQUEST_URI_TOO_LONG: 414,\r\n UNSUPPORTED_MEDIA_TYPE: 415,\r\n REQUEST_RANGE_NOT_SATISFIABLE: 416,\r\n EXPECTATION_FAILED: 417,\r\n UNPROCESSABLE_ENTITY: 422,\r\n LOCKED: 423,\r\n FAILED_DEPENDENCY: 424,\r\n PRECONDITION_REQUIRED: 428,\r\n TOO_MANY_REQUESTS: 429,\r\n REQUEST_HEADER_FIELDS_TOO_LARGE: 431,\r\n\r\n // Server Error 5xx\r\n INTERNAL_SERVER_ERROR: 500,\r\n NOT_IMPLEMENTED: 501,\r\n BAD_GATEWAY: 502,\r\n SERVICE_UNAVAILABLE: 503,\r\n GATEWAY_TIMEOUT: 504,\r\n HTTP_VERSION_NOT_SUPPORTED: 505,\r\n INSUFFICIENT_STORAGE: 507,\r\n NETWORK_AUTHENTICATION_REQUIRED: 511,\r\n\r\n /*\r\n * IE returns this code for 204 due to its use of URLMon, which returns this\r\n * code for 'Operation Aborted'. The status text is 'Unknown', the response\r\n * headers are ''. Known to occur on IE 6 on XP through IE9 on Win7.\r\n */\r\n QUIRK_IE_NO_CONTENT: 1223\r\n};\r\n\r\n\r\n/**\r\n * Returns whether the given status should be considered successful.\r\n *\r\n * Successful codes are OK (200), CREATED (201), ACCEPTED (202),\r\n * NO CONTENT (204), PARTIAL CONTENT (206), NOT MODIFIED (304),\r\n * and IE's no content code (1223).\r\n *\r\n * @param {number} status The status code to test.\r\n * @return {boolean} Whether the status code should be considered successful.\r\n */\r\ngoog.net.HttpStatus.isSuccess = function(status) {\r\n switch (status) {\r\n case goog.net.HttpStatus.OK:\r\n case goog.net.HttpStatus.CREATED:\r\n case goog.net.HttpStatus.ACCEPTED:\r\n case goog.net.HttpStatus.NO_CONTENT:\r\n case goog.net.HttpStatus.PARTIAL_CONTENT:\r\n case goog.net.HttpStatus.NOT_MODIFIED:\r\n case goog.net.HttpStatus.QUIRK_IE_NO_CONTENT:\r\n return true;\r\n\r\n default:\r\n return false;\r\n }\r\n};\r\n","// Copyright 2017 The Closure Library Authors. All Rights Reserved.\r\n//\r\n// Licensed under the Apache License, Version 2.0 (the \"License\");\r\n// you may not use this file except in compliance with the License.\r\n// You may obtain a copy of the License at\r\n//\r\n// http://www.apache.org/licenses/LICENSE-2.0\r\n//\r\n// Unless required by applicable law or agreed to in writing, software\r\n// distributed under the License is distributed on an \"AS-IS\" BASIS,\r\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n// See the License for the specific language governing permissions and\r\n// limitations under the License.\r\n\r\n/**\r\n * @fileoverview Provides CORS support for HTTP based RPC requests.\r\n *\r\n * As part of net.rpc package, CORS features provided by this class\r\n * depend on the server support. Please check related specs to decide how\r\n * to enable any of the features provided by this class.\r\n *\r\n */\r\n\r\ngoog.module('goog.net.rpc.HttpCors');\r\n\r\nvar GoogUri = goog.require('goog.Uri');\r\nvar googObject = goog.require('goog.object');\r\nvar googString = goog.require('goog.string');\r\nvar googUriUtils = goog.require('goog.uri.utils');\r\n\r\n\r\n/**\r\n * The default URL parameter name to overwrite http headers with a URL param\r\n * to avoid CORS preflight.\r\n *\r\n * See https://github.com/whatwg/fetch/issues/210#issue-129531743 for the spec.\r\n *\r\n * @type {string}\r\n */\r\nexports.HTTP_HEADERS_PARAM_NAME = '$httpHeaders';\r\n\r\n\r\n/**\r\n * The default URL parameter name to overwrite http method with a URL param\r\n * to avoid CORS preflight.\r\n *\r\n * See https://github.com/whatwg/fetch/issues/210#issue-129531743 for the spec.\r\n *\r\n * @type {string}\r\n */\r\nexports.HTTP_METHOD_PARAM_NAME = '$httpMethod';\r\n\r\n\r\n/**\r\n * Generates the URL parameter value with custom headers encoded as\r\n * HTTP/1.1 headers block.\r\n *\r\n * @param {!Object<string, string>} headers The custom headers.\r\n * @return {string} The URL param to overwrite custom HTTP headers.\r\n */\r\nexports.generateHttpHeadersOverwriteParam = function(headers) {\r\n var result = '';\r\n googObject.forEach(headers, function(value, key) {\r\n result += key;\r\n result += ':';\r\n result += value;\r\n result += '\\r\\n';\r\n });\r\n return result;\r\n};\r\n\r\n\r\n/**\r\n * Generates the URL-encoded URL parameter value with custom headers encoded as\r\n * HTTP/1.1 headers block.\r\n *\r\n * @param {!Object<string, string>} headers The custom headers.\r\n * @return {string} The URL param to overwrite custom HTTP headers.\r\n */\r\nexports.generateEncodedHttpHeadersOverwriteParam = function(headers) {\r\n return googString.urlEncode(\r\n exports.generateHttpHeadersOverwriteParam(headers));\r\n};\r\n\r\n\r\n/**\r\n * Sets custom HTTP headers via an overwrite URL param.\r\n *\r\n * @param {!GoogUri|string} url The URI object or a string path.\r\n * @param {string} urlParam The URL param name.\r\n * @param {!Object<string, string>} extraHeaders The HTTP headers.\r\n * @return {!GoogUri|string} The URI object or a string path with headers\r\n * encoded as a url param.\r\n */\r\nexports.setHttpHeadersWithOverwriteParam = function(\r\n url, urlParam, extraHeaders) {\r\n if (googObject.isEmpty(extraHeaders)) {\r\n return url;\r\n }\r\n var httpHeaders = exports.generateHttpHeadersOverwriteParam(extraHeaders);\r\n if (goog.isString(url)) {\r\n return googUriUtils.appendParam(\r\n url, googString.urlEncode(urlParam), httpHeaders);\r\n } else {\r\n url.setParameterValue(urlParam, httpHeaders); // duplicate removed!\r\n return url;\r\n }\r\n};\r\n","// Copyright 2013 The Closure Library Authors. All Rights Reserved.\r\n//\r\n// Licensed under the Apache License, Version 2.0 (the \"License\");\r\n// you may not use this file except in compliance with the License.\r\n// You may obtain a copy of the License at\r\n//\r\n// http://www.apache.org/licenses/LICENSE-2.0\r\n//\r\n// Unless required by applicable law or agreed to in writing, software\r\n// distributed under the License is distributed on an \"AS-IS\" BASIS,\r\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n// See the License for the specific language governing permissions and\r\n// limitations under the License.\r\n\r\n/**\r\n * @fileoverview Transport support for WebChannel.\r\n *\r\n * The <code>WebChannelTransport</code> implementation serves as the factory\r\n * for <code>WebChannel</code>, which offers an abstraction for\r\n * point-to-point socket-like communication similar to what BrowserChannel\r\n * or HTML5 WebSocket offers.\r\n *\r\n */\r\n\r\ngoog.provide('goog.net.WebChannelTransport');\r\n\r\ngoog.forwardDeclare('goog.net.WebChannel');\r\ngoog.forwardDeclare('goog.net.WebChannel.Options');\r\n\r\n\r\n\r\n/**\r\n * A WebChannelTransport instance represents a shared context of logical\r\n * connectivity between a browser client and a remote origin.\r\n *\r\n * Over a single WebChannelTransport instance, multiple WebChannels may be\r\n * created against different URLs, which may all share the same\r\n * underlying connectivity (i.e. TCP connection) whenever possible.\r\n *\r\n * When multi-domains are supported, such as CORS, multiple origins may be\r\n * supported over a single WebChannelTransport instance at the same time.\r\n *\r\n * Sharing between different window contexts such as tabs is not addressed\r\n * by WebChannelTransport. Applications may choose HTML5 shared workers\r\n * or other techniques to access the same transport instance\r\n * across different window contexts.\r\n *\r\n * @interface\r\n */\r\ngoog.net.WebChannelTransport = function() {};\r\n\r\n\r\n/**\r\n * The client version. This integer value will be passed to the server\r\n * when a channel is opened to inform the server the client \"capabilities\".\r\n *\r\n * Wire protocol version is a different concept and is internal to the\r\n * transport implementation.\r\n *\r\n * @const\r\n * @type {number}\r\n */\r\ngoog.net.WebChannelTransport.CLIENT_VERSION = 22;\r\n\r\n\r\n/**\r\n * Create a new WebChannel instance.\r\n *\r\n * The new WebChannel is to be opened against the server-side resource\r\n * as specified by the given URL. See {@link goog.net.WebChannel} for detailed\r\n * semantics.\r\n *\r\n * @param {string} url The URL path for the new WebChannel instance.\r\n * @param {!goog.net.WebChannel.Options=} opt_options Configuration for the\r\n * new WebChannel instance. The configuration object is reusable after\r\n * the new channel instance is created.\r\n * @return {!goog.net.WebChannel} the newly created WebChannel instance.\r\n */\r\ngoog.net.WebChannelTransport.prototype.createWebChannel = goog.abstractMethod;\r\n","// Copyright 2010 The Closure Library Authors. All Rights Reserved.\r\n//\r\n// Licensed under the Apache License, Version 2.0 (the \"License\");\r\n// you may not use this file except in compliance with the License.\r\n// You may obtain a copy of the License at\r\n//\r\n// http://www.apache.org/licenses/LICENSE-2.0\r\n//\r\n// Unless required by applicable law or agreed to in writing, software\r\n// distributed under the License is distributed on an \"AS-IS\" BASIS,\r\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n// See the License for the specific language governing permissions and\r\n// limitations under the License.\r\n\r\n/**\r\n * @fileoverview Utilities for dealing with POSIX path strings. Based on\r\n * Python's os.path and posixpath.\r\n * @author nnaze@google.com (Nathan Naze)\r\n */\r\n\r\ngoog.provide('goog.string.path');\r\n\r\ngoog.require('goog.array');\r\ngoog.require('goog.string');\r\n\r\n\r\n/**\r\n * Returns the final component of a pathname.\r\n * See http://docs.python.org/library/os.path.html#os.path.basename\r\n * @param {string} path A pathname.\r\n * @return {string} path The final component of a pathname, i.e. everything\r\n * after the final slash.\r\n */\r\ngoog.string.path.baseName = function(path) {\r\n var i = path.lastIndexOf('/') + 1;\r\n return path.slice(i);\r\n};\r\n\r\n\r\n/**\r\n * Alias to goog.string.path.baseName.\r\n * @param {string} path A pathname.\r\n * @return {string} path The final component of a pathname.\r\n * @deprecated Use goog.string.path.baseName.\r\n */\r\ngoog.string.path.basename = goog.string.path.baseName;\r\n\r\n\r\n/**\r\n * Returns the directory component of a pathname.\r\n * See http://docs.python.org/library/os.path.html#os.path.dirname\r\n * @param {string} path A pathname.\r\n * @return {string} The directory component of a pathname, i.e. everything\r\n * leading up to the final slash.\r\n */\r\ngoog.string.path.dirname = function(path) {\r\n var i = path.lastIndexOf('/') + 1;\r\n var head = path.slice(0, i);\r\n // If the path isn't all forward slashes, trim the trailing slashes.\r\n if (!/^\\/+$/.test(head)) {\r\n head = head.replace(/\\/+$/, '');\r\n }\r\n return head;\r\n};\r\n\r\n\r\n/**\r\n * Extracts the extension part of a pathname.\r\n * @param {string} path The path name to process.\r\n * @return {string} The extension if any, otherwise the empty string.\r\n */\r\ngoog.string.path.extension = function(path) {\r\n var separator = '.';\r\n // Combining all adjacent periods in the basename to a single period.\r\n var baseName = goog.string.path.baseName(path).replace(/\\.+/g, separator);\r\n var separatorIndex = baseName.lastIndexOf(separator);\r\n return separatorIndex <= 0 ? '' : baseName.substr(separatorIndex + 1);\r\n};\r\n\r\n\r\n// TODO(johnlenz): goog.string.path.join should not accept undefined\r\n/**\r\n * Joins one or more path components (e.g. 'foo/' and 'bar' make 'foo/bar').\r\n * An absolute component will discard all previous component.\r\n * See http://docs.python.org/library/os.path.html#os.path.join\r\n * @param {...(string|undefined)} var_args One of more path components.\r\n * @return {string} The path components joined.\r\n */\r\ngoog.string.path.join = function(var_args) {\r\n var path = arguments[0];\r\n\r\n for (var i = 1; i < arguments.length; i++) {\r\n var arg = arguments[i];\r\n if (goog.string.startsWith(arg, '/')) {\r\n path = arg;\r\n } else if (path == '' || goog.string.endsWith(path, '/')) {\r\n path += arg;\r\n } else {\r\n path += '/' + arg;\r\n }\r\n }\r\n\r\n return path;\r\n};\r\n\r\n\r\n/**\r\n * Normalizes a pathname by collapsing duplicate separators, parent directory\r\n * references ('..'), and current directory references ('.').\r\n * See http://docs.python.org/library/os.path.html#os.path.normpath\r\n * @param {string} path One or more path components.\r\n * @return {string} The path after normalization.\r\n */\r\ngoog.string.path.normalizePath = function(path) {\r\n if (path == '') {\r\n return '.';\r\n }\r\n\r\n var initialSlashes = '';\r\n // POSIX will keep two slashes, but three or more will be collapsed to one.\r\n if (goog.string.startsWith(path, '/')) {\r\n initialSlashes = '/';\r\n if (goog.string.startsWith(path, '//') &&\r\n !goog.string.startsWith(path, '///')) {\r\n initialSlashes = '//';\r\n }\r\n }\r\n\r\n var parts = path.split('/');\r\n var newParts = [];\r\n\r\n for (var i = 0; i < parts.length; i++) {\r\n var part = parts[i];\r\n\r\n // '' and '.' don't change the directory, ignore.\r\n if (part == '' || part == '.') {\r\n continue;\r\n }\r\n\r\n // A '..' should pop a directory unless this is not an absolute path and\r\n // we're at the root, or we've travelled upwards relatively in the last\r\n // iteration.\r\n if (part != '..' || (!initialSlashes && !newParts.length) ||\r\n goog.array.peek(newParts) == '..') {\r\n newParts.push(part);\r\n } else {\r\n newParts.pop();\r\n }\r\n }\r\n\r\n var returnPath = initialSlashes + newParts.join('/');\r\n return returnPath || '.';\r\n};\r\n\r\n\r\n/**\r\n * Splits a pathname into \"dirname\" and \"baseName\" components, where \"baseName\"\r\n * is everything after the final slash. Either part may return an empty string.\r\n * See http://docs.python.org/library/os.path.html#os.path.split\r\n * @param {string} path A pathname.\r\n * @return {!Array<string>} An array of [dirname, basename].\r\n */\r\ngoog.string.path.split = function(path) {\r\n var head = goog.string.path.dirname(path);\r\n var tail = goog.string.path.baseName(path);\r\n return [head, tail];\r\n};\r\n\r\n// TODO(nnaze): Implement other useful functions from os.path\r\n","// Copyright 2013 The Closure Library Authors. All Rights Reserved.\r\n//\r\n// Licensed under the Apache License, Version 2.0 (the \"License\");\r\n// you may not use this file except in compliance with the License.\r\n// You may obtain a copy of the License at\r\n//\r\n// http://www.apache.org/licenses/LICENSE-2.0\r\n//\r\n// Unless required by applicable law or agreed to in writing, software\r\n// distributed under the License is distributed on an \"AS-IS\" BASIS,\r\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n// See the License for the specific language governing permissions and\r\n// limitations under the License.\r\n\r\n/**\r\n * @fileoverview Implementation of a WebChannel transport using WebChannelBase.\r\n *\r\n * When WebChannelBase is used as the underlying transport, the capabilities\r\n * of the WebChannel are limited to what's supported by the implementation.\r\n * Particularly, multiplexing is not possible, and only strings are\r\n * supported as message types.\r\n *\r\n */\r\n\r\ngoog.provide('goog.labs.net.webChannel.WebChannelBaseTransport');\r\n\r\ngoog.require('goog.asserts');\r\ngoog.require('goog.events.EventTarget');\r\ngoog.require('goog.json');\r\ngoog.require('goog.labs.net.webChannel.ChannelRequest');\r\ngoog.require('goog.labs.net.webChannel.WebChannelBase');\r\ngoog.require('goog.labs.net.webChannel.Wire');\r\ngoog.require('goog.log');\r\ngoog.require('goog.net.WebChannel');\r\ngoog.require('goog.net.WebChannelTransport');\r\ngoog.require('goog.object');\r\ngoog.require('goog.string');\r\ngoog.require('goog.string.path');\r\n\r\n\r\n\r\n/**\r\n * Implementation of {@link goog.net.WebChannelTransport} with\r\n * {@link goog.labs.net.webChannel.WebChannelBase} as the underlying channel\r\n * implementation.\r\n *\r\n * @constructor\r\n * @struct\r\n * @implements {goog.net.WebChannelTransport}\r\n * @final\r\n */\r\ngoog.labs.net.webChannel.WebChannelBaseTransport = function() {\r\n if (!goog.labs.net.webChannel.ChannelRequest.supportsXhrStreaming()) {\r\n throw new Error('Environmental error: no available transport.');\r\n }\r\n};\r\n\r\n\r\ngoog.scope(function() {\r\nvar WebChannelBaseTransport = goog.labs.net.webChannel.WebChannelBaseTransport;\r\nvar WebChannelBase = goog.labs.net.webChannel.WebChannelBase;\r\nvar Wire = goog.labs.net.webChannel.Wire;\r\n\r\n\r\n/**\r\n * @override\r\n */\r\nWebChannelBaseTransport.prototype.createWebChannel = function(\r\n url, opt_options) {\r\n return new WebChannelBaseTransport.Channel(url, opt_options);\r\n};\r\n\r\n\r\n\r\n/**\r\n * Implementation of the {@link goog.net.WebChannel} interface.\r\n *\r\n * @param {string} url The URL path for the new WebChannel instance.\r\n * @param {!goog.net.WebChannel.Options=} opt_options Configuration for the\r\n * new WebChannel instance.\r\n *\r\n * @constructor\r\n * @implements {goog.net.WebChannel}\r\n * @extends {goog.events.EventTarget}\r\n * @final\r\n */\r\nWebChannelBaseTransport.Channel = function(url, opt_options) {\r\n WebChannelBaseTransport.Channel.base(this, 'constructor');\r\n\r\n /**\r\n * @private {!WebChannelBase} The underlying channel object.\r\n */\r\n this.channel_ = new WebChannelBase(\r\n opt_options, goog.net.WebChannelTransport.CLIENT_VERSION);\r\n\r\n /**\r\n * @private {string} The URL of the target server end-point.\r\n */\r\n this.url_ = url;\r\n\r\n /**\r\n * The test URL of the target server end-point. This value defaults to\r\n * this.url_ + '/test'.\r\n *\r\n * @private {string}\r\n */\r\n this.testUrl_ = (opt_options && opt_options.testUrl) ?\r\n opt_options.testUrl :\r\n goog.string.path.join(this.url_, 'test');\r\n\r\n /**\r\n * @private {goog.log.Logger} The logger for this class.\r\n */\r\n this.logger_ =\r\n goog.log.getLogger('goog.labs.net.webChannel.WebChannelBaseTransport');\r\n\r\n /**\r\n * @private {Object<string, string>} Extra URL parameters\r\n * to be added to each HTTP request.\r\n */\r\n this.messageUrlParams_ =\r\n (opt_options && opt_options.messageUrlParams) || null;\r\n\r\n var messageHeaders = (opt_options && opt_options.messageHeaders) || null;\r\n\r\n // default is false\r\n if (opt_options && opt_options.clientProtocolHeaderRequired) {\r\n if (messageHeaders) {\r\n goog.object.set(\r\n messageHeaders, goog.net.WebChannel.X_CLIENT_PROTOCOL,\r\n goog.net.WebChannel.X_CLIENT_PROTOCOL_WEB_CHANNEL);\r\n } else {\r\n messageHeaders = goog.object.create(\r\n goog.net.WebChannel.X_CLIENT_PROTOCOL,\r\n goog.net.WebChannel.X_CLIENT_PROTOCOL_WEB_CHANNEL);\r\n }\r\n }\r\n\r\n this.channel_.setExtraHeaders(messageHeaders);\r\n\r\n var initHeaders = (opt_options && opt_options.initMessageHeaders) || null;\r\n\r\n if (opt_options && opt_options.messageContentType) {\r\n if (initHeaders) {\r\n goog.object.set(\r\n initHeaders, goog.net.WebChannel.X_WEBCHANNEL_CONTENT_TYPE,\r\n opt_options.messageContentType);\r\n } else {\r\n initHeaders = goog.object.create(\r\n goog.net.WebChannel.X_WEBCHANNEL_CONTENT_TYPE,\r\n opt_options.messageContentType);\r\n }\r\n }\r\n\r\n if (opt_options && opt_options.clientProfile) {\r\n if (initHeaders) {\r\n goog.object.set(\r\n initHeaders, goog.net.WebChannel.X_WEBCHANNEL_CLIENT_PROFILE,\r\n opt_options.clientProfile);\r\n } else {\r\n initHeaders = goog.object.create(\r\n goog.net.WebChannel.X_WEBCHANNEL_CLIENT_PROFILE,\r\n opt_options.clientProfile);\r\n }\r\n }\r\n\r\n this.channel_.setInitHeaders(initHeaders);\r\n\r\n var httpHeadersOverwriteParam =\r\n opt_options && opt_options.httpHeadersOverwriteParam;\r\n if (httpHeadersOverwriteParam &&\r\n !goog.string.isEmptyOrWhitespace(httpHeadersOverwriteParam)) {\r\n this.channel_.setHttpHeadersOverwriteParam(httpHeadersOverwriteParam);\r\n }\r\n\r\n /**\r\n * @private {boolean} Whether to enable CORS.\r\n */\r\n this.supportsCrossDomainXhr_ =\r\n (opt_options && opt_options.supportsCrossDomainXhr) || false;\r\n\r\n /**\r\n * @private {boolean} Whether to send raw Json and bypass v8 wire format.\r\n */\r\n this.sendRawJson_ = (opt_options && opt_options.sendRawJson) || false;\r\n\r\n // Note that httpSessionIdParam will be ignored if the same parameter name\r\n // has already been specified with messageUrlParams\r\n var httpSessionIdParam = opt_options && opt_options.httpSessionIdParam;\r\n if (httpSessionIdParam &&\r\n !goog.string.isEmptyOrWhitespace(httpSessionIdParam)) {\r\n this.channel_.setHttpSessionIdParam(httpSessionIdParam);\r\n if (goog.object.containsKey(this.messageUrlParams_, httpSessionIdParam)) {\r\n goog.object.remove(this.messageUrlParams_, httpSessionIdParam);\r\n goog.log.warning(this.logger_,\r\n 'Ignore httpSessionIdParam also specified with messageUrlParams: '\r\n + httpSessionIdParam);\r\n }\r\n }\r\n\r\n /**\r\n * The channel handler.\r\n *\r\n * @private {!WebChannelBaseTransport.Channel.Handler_}\r\n */\r\n this.channelHandler_ = new WebChannelBaseTransport.Channel.Handler_(this);\r\n};\r\ngoog.inherits(WebChannelBaseTransport.Channel, goog.events.EventTarget);\r\n\r\n\r\n/**\r\n * @override\r\n * @suppress {checkTypes}\r\n */\r\nWebChannelBaseTransport.Channel.prototype.addEventListener = function(\r\n type, handler, /** boolean= */ opt_capture, opt_handlerScope) {\r\n WebChannelBaseTransport.Channel.base(\r\n this, 'addEventListener', type, handler, opt_capture, opt_handlerScope);\r\n};\r\n\r\n\r\n/**\r\n * @override\r\n * @suppress {checkTypes}\r\n */\r\nWebChannelBaseTransport.Channel.prototype.removeEventListener = function(\r\n type, handler, /** boolean= */ opt_capture, opt_handlerScope) {\r\n WebChannelBaseTransport.Channel.base(\r\n this, 'removeEventListener', type, handler, opt_capture,\r\n opt_handlerScope);\r\n};\r\n\r\n\r\n/**\r\n * Test path is always set to \"/url/test\".\r\n *\r\n * @override\r\n */\r\nWebChannelBaseTransport.Channel.prototype.open = function() {\r\n this.channel_.setHandler(this.channelHandler_);\r\n if (this.supportsCrossDomainXhr_) {\r\n this.channel_.setSupportsCrossDomainXhrs(true);\r\n }\r\n this.channel_.connect(\r\n this.testUrl_, this.url_, (this.messageUrlParams_ || undefined));\r\n};\r\n\r\n\r\n/**\r\n * @override\r\n */\r\nWebChannelBaseTransport.Channel.prototype.close = function() {\r\n this.channel_.disconnect();\r\n};\r\n\r\n\r\n/**\r\n * @override\r\n */\r\nWebChannelBaseTransport.Channel.prototype.halfClose = function() {\r\n // to be implemented\r\n throw new Error('Not implemented');\r\n};\r\n\r\n\r\n/**\r\n * The WebChannelBase only supports object types.\r\n *\r\n * @param {!goog.net.WebChannel.MessageData} message The message to send.\r\n *\r\n * @override\r\n */\r\nWebChannelBaseTransport.Channel.prototype.send = function(message) {\r\n goog.asserts.assert(\r\n goog.isObject(message) || goog.isString(message),\r\n 'only object type or raw string is supported');\r\n\r\n if (goog.isString(message)) {\r\n var rawJson = {};\r\n rawJson[Wire.RAW_DATA_KEY] = message;\r\n this.channel_.sendMap(rawJson);\r\n } else if (this.sendRawJson_) {\r\n var rawJson = {};\r\n rawJson[Wire.RAW_DATA_KEY] = goog.json.serialize(message);\r\n this.channel_.sendMap(rawJson);\r\n } else {\r\n this.channel_.sendMap(message);\r\n }\r\n};\r\n\r\n\r\n/**\r\n * @override\r\n */\r\nWebChannelBaseTransport.Channel.prototype.disposeInternal = function() {\r\n this.channel_.setHandler(null);\r\n delete this.channelHandler_;\r\n this.channel_.disconnect();\r\n delete this.channel_;\r\n\r\n WebChannelBaseTransport.Channel.base(this, 'disposeInternal');\r\n};\r\n\r\n\r\n\r\n/**\r\n * The message event.\r\n *\r\n * @param {!Array<?>|!Object} array The data array from the underlying channel.\r\n * @constructor\r\n * @extends {goog.net.WebChannel.MessageEvent}\r\n * @final\r\n */\r\nWebChannelBaseTransport.Channel.MessageEvent = function(array) {\r\n WebChannelBaseTransport.Channel.MessageEvent.base(this, 'constructor');\r\n\r\n // single-metadata only\r\n var metadata = array['__sm__'];\r\n if (metadata) {\r\n this.metadataKey = goog.object.getAnyKey(metadata);\r\n if (this.metadataKey) {\r\n this.data = goog.object.get(metadata, this.metadataKey);\r\n } else {\r\n this.data = metadata; // empty\r\n }\r\n } else {\r\n this.data = array;\r\n }\r\n};\r\ngoog.inherits(\r\n WebChannelBaseTransport.Channel.MessageEvent,\r\n goog.net.WebChannel.MessageEvent);\r\n\r\n\r\n\r\n/**\r\n * The error event.\r\n *\r\n * @param {WebChannelBase.Error} error The error code.\r\n * @constructor\r\n * @extends {goog.net.WebChannel.ErrorEvent}\r\n * @final\r\n */\r\nWebChannelBaseTransport.Channel.ErrorEvent = function(error) {\r\n WebChannelBaseTransport.Channel.ErrorEvent.base(this, 'constructor');\r\n\r\n /**\r\n * High-level status code.\r\n */\r\n this.status = goog.net.WebChannel.ErrorStatus.NETWORK_ERROR;\r\n\r\n /**\r\n * @const {WebChannelBase.Error} Internal error code, for debugging use only.\r\n */\r\n this.errorCode = error;\r\n};\r\ngoog.inherits(\r\n WebChannelBaseTransport.Channel.ErrorEvent, goog.net.WebChannel.ErrorEvent);\r\n\r\n\r\n\r\n/**\r\n * Implementation of {@link WebChannelBase.Handler} interface.\r\n *\r\n * @param {!WebChannelBaseTransport.Channel} channel The enclosing WebChannel.\r\n *\r\n * @constructor\r\n * @extends {WebChannelBase.Handler}\r\n * @private\r\n */\r\nWebChannelBaseTransport.Channel.Handler_ = function(channel) {\r\n WebChannelBaseTransport.Channel.Handler_.base(this, 'constructor');\r\n\r\n /**\r\n * @type {!WebChannelBaseTransport.Channel}\r\n * @private\r\n */\r\n this.channel_ = channel;\r\n};\r\ngoog.inherits(WebChannelBaseTransport.Channel.Handler_, WebChannelBase.Handler);\r\n\r\n\r\n/**\r\n * @override\r\n */\r\nWebChannelBaseTransport.Channel.Handler_.prototype.channelOpened = function(\r\n channel) {\r\n goog.log.info(\r\n this.channel_.logger_, 'WebChannel opened on ' + this.channel_.url_);\r\n this.channel_.dispatchEvent(goog.net.WebChannel.EventType.OPEN);\r\n};\r\n\r\n\r\n/**\r\n * @override\r\n */\r\nWebChannelBaseTransport.Channel.Handler_.prototype.channelHandleArray =\r\n function(channel, array) {\r\n goog.asserts.assert(array, 'array expected to be defined');\r\n this.channel_.dispatchEvent(\r\n new WebChannelBaseTransport.Channel.MessageEvent(array));\r\n};\r\n\r\n\r\n/**\r\n * @override\r\n */\r\nWebChannelBaseTransport.Channel.Handler_.prototype.channelError = function(\r\n channel, error) {\r\n goog.log.info(\r\n this.channel_.logger_, 'WebChannel aborted on ' + this.channel_.url_ +\r\n ' due to channel error: ' + error);\r\n this.channel_.dispatchEvent(\r\n new WebChannelBaseTransport.Channel.ErrorEvent(error));\r\n};\r\n\r\n\r\n/**\r\n * @override\r\n */\r\nWebChannelBaseTransport.Channel.Handler_.prototype.channelClosed = function(\r\n channel, opt_pendingMaps, opt_undeliveredMaps) {\r\n goog.log.info(\r\n this.channel_.logger_, 'WebChannel closed on ' + this.channel_.url_);\r\n this.channel_.dispatchEvent(goog.net.WebChannel.EventType.CLOSE);\r\n};\r\n\r\n\r\n/**\r\n * @override\r\n */\r\nWebChannelBaseTransport.Channel.prototype.getRuntimeProperties = function() {\r\n return new WebChannelBaseTransport.ChannelProperties(this.channel_);\r\n};\r\n\r\n\r\n\r\n/**\r\n * Implementation of the {@link goog.net.WebChannel.RuntimeProperties}.\r\n *\r\n * @param {!WebChannelBase} channel The underlying channel object.\r\n *\r\n * @constructor\r\n * @implements {goog.net.WebChannel.RuntimeProperties}\r\n * @final\r\n */\r\nWebChannelBaseTransport.ChannelProperties = function(channel) {\r\n /**\r\n * The underlying channel object.\r\n *\r\n * @private {!WebChannelBase}\r\n */\r\n this.channel_ = channel;\r\n\r\n};\r\n\r\n\r\n/**\r\n * @override\r\n */\r\nWebChannelBaseTransport.ChannelProperties.prototype.getConcurrentRequestLimit =\r\n function() {\r\n return this.channel_.getForwardChannelRequestPool().getMaxSize();\r\n};\r\n\r\n\r\n/**\r\n * @override\r\n */\r\nWebChannelBaseTransport.ChannelProperties.prototype.isSpdyEnabled = function() {\r\n return this.getConcurrentRequestLimit() > 1;\r\n};\r\n\r\n\r\n/**\r\n * @override\r\n */\r\nWebChannelBaseTransport.ChannelProperties.prototype.getPendingRequestCount =\r\n function() {\r\n return this.channel_.getForwardChannelRequestPool().getRequestCount();\r\n};\r\n\r\n\r\n/**\r\n * @override\r\n */\r\nWebChannelBaseTransport.ChannelProperties.prototype.getHttpSessionId =\r\n function() {\r\n return this.channel_.getHttpSessionId();\r\n};\r\n\r\n\r\n/**\r\n * @override\r\n */\r\nWebChannelBaseTransport.ChannelProperties.prototype.commit = function(\r\n callback) {\r\n this.channel_.setForwardChannelFlushCallback(callback);\r\n};\r\n\r\n\r\n/**\r\n * @override\r\n */\r\nWebChannelBaseTransport.ChannelProperties.prototype.getNonAckedMessageCount =\r\n goog.abstractMethod;\r\n\r\n\r\n/**\r\n * @override\r\n */\r\nWebChannelBaseTransport.ChannelProperties.prototype.notifyNonAckedMessageCount =\r\n goog.abstractMethod;\r\n\r\n\r\n/**\r\n * @override\r\n */\r\nWebChannelBaseTransport.ChannelProperties.prototype.onCommit =\r\n goog.abstractMethod;\r\n\r\n\r\n/**\r\n * @override\r\n */\r\nWebChannelBaseTransport.ChannelProperties.prototype.ackCommit =\r\n goog.abstractMethod;\r\n\r\n\r\n/** @override */\r\nWebChannelBaseTransport.ChannelProperties.prototype.getLastStatusCode =\r\n function() {\r\n return this.channel_.getLastStatusCode();\r\n};\r\n}); // goog.scope\r\n","// Copyright 2013 The Closure Library Authors. All Rights Reserved.\r\n//\r\n// Licensed under the Apache License, Version 2.0 (the \"License\");\r\n// you may not use this file except in compliance with the License.\r\n// You may obtain a copy of the License at\r\n//\r\n// http://www.apache.org/licenses/LICENSE-2.0\r\n//\r\n// Unless required by applicable law or agreed to in writing, software\r\n// distributed under the License is distributed on an \"AS-IS\" BASIS,\r\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n// See the License for the specific language governing permissions and\r\n// limitations under the License.\r\n\r\n/**\r\n * @fileoverview Default factory for <code>WebChannelTransport</code> to\r\n * avoid exposing concrete classes to clients.\r\n *\r\n */\r\n\r\ngoog.provide('goog.net.createWebChannelTransport');\r\n\r\ngoog.require('goog.functions');\r\ngoog.require('goog.labs.net.webChannel.WebChannelBaseTransport');\r\n\r\n\r\n/**\r\n * Create a new WebChannelTransport instance using the default implementation.\r\n * Throws an error message if no default transport available in the current\r\n * environment.\r\n *\r\n * @return {!goog.net.WebChannelTransport} the newly created transport instance.\r\n */\r\ngoog.net.createWebChannelTransport =\r\n /** @type {function(): !goog.net.WebChannelTransport} */ (\r\n goog.partial(\r\n goog.functions.create,\r\n goog.labs.net.webChannel.WebChannelBaseTransport));\r\n","// Copyright 2008 The Closure Library Authors. All Rights Reserved.\r\n//\r\n// Licensed under the Apache License, Version 2.0 (the \"License\");\r\n// you may not use this file except in compliance with the License.\r\n// You may obtain a copy of the License at\r\n//\r\n// http://www.apache.org/licenses/LICENSE-2.0\r\n//\r\n// Unless required by applicable law or agreed to in writing, software\r\n// distributed under the License is distributed on an \"AS-IS\" BASIS,\r\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n// See the License for the specific language governing permissions and\r\n// limitations under the License.\r\n\r\n/**\r\n * @fileoverview Utilities for creating functions. Loosely inspired by these\r\n * java classes from the Guava library:\r\n * com.google.common.base.Functions\r\n * https://google.github.io/guava/releases/snapshot-jre/api/docs/index.html?com/google/common/base/Functions.html\r\n *\r\n * com.google.common.base.Predicates\r\n * https://google.github.io/guava/releases/snapshot-jre/api/docs/index.html?com/google/common/base/Predicates.html\r\n *\r\n * More about these can be found at\r\n * https://github.com/google/guava/wiki/FunctionalExplained\r\n *\r\n * @author nicksantos@google.com (Nick Santos)\r\n */\r\n\r\n\r\ngoog.provide('goog.functions');\r\n\r\n\r\n/**\r\n * Creates a function that always returns the same value.\r\n * @param {T} retValue The value to return.\r\n * @return {function():T} The new function.\r\n * @template T\r\n */\r\ngoog.functions.constant = function(retValue) {\r\n return function() { return retValue; };\r\n};\r\n\r\n\r\n/**\r\n * Always returns false.\r\n * @type {function(...): boolean}\r\n */\r\ngoog.functions.FALSE = function() {\r\n return false;\r\n};\r\n\r\n\r\n/**\r\n * Always returns true.\r\n * @type {function(...): boolean}\r\n */\r\ngoog.functions.TRUE = function() {\r\n return true;\r\n};\r\n\r\n\r\n/**\r\n * Always returns NULL.\r\n * @type {function(...): null}\r\n */\r\ngoog.functions.NULL = function() {\r\n return null;\r\n};\r\n\r\n\r\n/**\r\n * A simple function that returns the first argument of whatever is passed\r\n * into it.\r\n * @param {T=} opt_returnValue The single value that will be returned.\r\n * @param {...*} var_args Optional trailing arguments. These are ignored.\r\n * @return {T} The first argument passed in, or undefined if nothing was passed.\r\n * @template T\r\n */\r\ngoog.functions.identity = function(opt_returnValue, var_args) {\r\n return opt_returnValue;\r\n};\r\n\r\n\r\n/**\r\n * Creates a function that always throws an error with the given message.\r\n * @param {string} message The error message.\r\n * @return {!Function} The error-throwing function.\r\n */\r\ngoog.functions.error = function(message) {\r\n return function() {\r\n throw new Error(message);\r\n };\r\n};\r\n\r\n\r\n/**\r\n * Creates a function that throws the given object.\r\n * @param {*} err An object to be thrown.\r\n * @return {!Function} The error-throwing function.\r\n */\r\ngoog.functions.fail = function(err) {\r\n return function() { throw err; };\r\n};\r\n\r\n\r\n/**\r\n * Given a function, create a function that keeps opt_numArgs arguments and\r\n * silently discards all additional arguments.\r\n * @param {Function} f The original function.\r\n * @param {number=} opt_numArgs The number of arguments to keep. Defaults to 0.\r\n * @return {!Function} A version of f that only keeps the first opt_numArgs\r\n * arguments.\r\n */\r\ngoog.functions.lock = function(f, opt_numArgs) {\r\n opt_numArgs = opt_numArgs || 0;\r\n return function() {\r\n var self = /** @type {*} */ (this);\r\n return f.apply(self, Array.prototype.slice.call(arguments, 0, opt_numArgs));\r\n };\r\n};\r\n\r\n\r\n/**\r\n * Creates a function that returns its nth argument.\r\n * @param {number} n The position of the return argument.\r\n * @return {!Function} A new function.\r\n */\r\ngoog.functions.nth = function(n) {\r\n return function() { return arguments[n]; };\r\n};\r\n\r\n\r\n/**\r\n * Like goog.partial(), except that arguments are added after arguments to the\r\n * returned function.\r\n *\r\n * Usage:\r\n * function f(arg1, arg2, arg3, arg4) { ... }\r\n * var g = goog.functions.partialRight(f, arg3, arg4);\r\n * g(arg1, arg2);\r\n *\r\n * @param {!Function} fn A function to partially apply.\r\n * @param {...*} var_args Additional arguments that are partially applied to fn\r\n * at the end.\r\n * @return {!Function} A partially-applied form of the function goog.partial()\r\n * was invoked as a method of.\r\n */\r\ngoog.functions.partialRight = function(fn, var_args) {\r\n var rightArgs = Array.prototype.slice.call(arguments, 1);\r\n return function() {\r\n var self = /** @type {*} */ (this);\r\n var newArgs = Array.prototype.slice.call(arguments);\r\n newArgs.push.apply(newArgs, rightArgs);\r\n return fn.apply(self, newArgs);\r\n };\r\n};\r\n\r\n\r\n/**\r\n * Given a function, create a new function that swallows its return value\r\n * and replaces it with a new one.\r\n * @param {Function} f A function.\r\n * @param {T} retValue A new return value.\r\n * @return {function(...?):T} A new function.\r\n * @template T\r\n */\r\ngoog.functions.withReturnValue = function(f, retValue) {\r\n return goog.functions.sequence(f, goog.functions.constant(retValue));\r\n};\r\n\r\n\r\n/**\r\n * Creates a function that returns whether its argument equals the given value.\r\n *\r\n * Example:\r\n * var key = goog.object.findKey(obj, goog.functions.equalTo('needle'));\r\n *\r\n * @param {*} value The value to compare to.\r\n * @param {boolean=} opt_useLooseComparison Whether to use a loose (==)\r\n * comparison rather than a strict (===) one. Defaults to false.\r\n * @return {function(*):boolean} The new function.\r\n */\r\ngoog.functions.equalTo = function(value, opt_useLooseComparison) {\r\n return function(other) {\r\n return opt_useLooseComparison ? (value == other) : (value === other);\r\n };\r\n};\r\n\r\n\r\n/**\r\n * Creates the composition of the functions passed in.\r\n * For example, (goog.functions.compose(f, g))(a) is equivalent to f(g(a)).\r\n * @param {function(...?):T} fn The final function.\r\n * @param {...Function} var_args A list of functions.\r\n * @return {function(...?):T} The composition of all inputs.\r\n * @template T\r\n */\r\ngoog.functions.compose = function(fn, var_args) {\r\n var functions = arguments;\r\n var length = functions.length;\r\n return function() {\r\n var self = /** @type {*} */ (this);\r\n var result;\r\n if (length) {\r\n result = functions[length - 1].apply(self, arguments);\r\n }\r\n\r\n for (var i = length - 2; i >= 0; i--) {\r\n result = functions[i].call(self, result);\r\n }\r\n return result;\r\n };\r\n};\r\n\r\n\r\n/**\r\n * Creates a function that calls the functions passed in in sequence, and\r\n * returns the value of the last function. For example,\r\n * (goog.functions.sequence(f, g))(x) is equivalent to f(x),g(x).\r\n * @param {...Function} var_args A list of functions.\r\n * @return {!Function} A function that calls all inputs in sequence.\r\n */\r\ngoog.functions.sequence = function(var_args) {\r\n var functions = arguments;\r\n var length = functions.length;\r\n return function() {\r\n var self = /** @type {*} */ (this);\r\n var result;\r\n for (var i = 0; i < length; i++) {\r\n result = functions[i].apply(self, arguments);\r\n }\r\n return result;\r\n };\r\n};\r\n\r\n\r\n/**\r\n * Creates a function that returns true if each of its components evaluates\r\n * to true. The components are evaluated in order, and the evaluation will be\r\n * short-circuited as soon as a function returns false.\r\n * For example, (goog.functions.and(f, g))(x) is equivalent to f(x) && g(x).\r\n * @param {...Function} var_args A list of functions.\r\n * @return {function(...?):boolean} A function that ANDs its component\r\n * functions.\r\n */\r\ngoog.functions.and = function(var_args) {\r\n var functions = arguments;\r\n var length = functions.length;\r\n return function() {\r\n var self = /** @type {*} */ (this);\r\n for (var i = 0; i < length; i++) {\r\n if (!functions[i].apply(self, arguments)) {\r\n return false;\r\n }\r\n }\r\n return true;\r\n };\r\n};\r\n\r\n\r\n/**\r\n * Creates a function that returns true if any of its components evaluates\r\n * to true. The components are evaluated in order, and the evaluation will be\r\n * short-circuited as soon as a function returns true.\r\n * For example, (goog.functions.or(f, g))(x) is equivalent to f(x) || g(x).\r\n * @param {...Function} var_args A list of functions.\r\n * @return {function(...?):boolean} A function that ORs its component\r\n * functions.\r\n */\r\ngoog.functions.or = function(var_args) {\r\n var functions = arguments;\r\n var length = functions.length;\r\n return function() {\r\n var self = /** @type {*} */ (this);\r\n for (var i = 0; i < length; i++) {\r\n if (functions[i].apply(self, arguments)) {\r\n return true;\r\n }\r\n }\r\n return false;\r\n };\r\n};\r\n\r\n\r\n/**\r\n * Creates a function that returns the Boolean opposite of a provided function.\r\n * For example, (goog.functions.not(f))(x) is equivalent to !f(x).\r\n * @param {!Function} f The original function.\r\n * @return {function(...?):boolean} A function that delegates to f and returns\r\n * opposite.\r\n */\r\ngoog.functions.not = function(f) {\r\n return function() {\r\n var self = /** @type {*} */ (this);\r\n return !f.apply(self, arguments);\r\n };\r\n};\r\n\r\n\r\n/**\r\n * Generic factory function to construct an object given the constructor\r\n * and the arguments. Intended to be bound to create object factories.\r\n *\r\n * Example:\r\n *\r\n * var factory = goog.partial(goog.functions.create, Class);\r\n *\r\n * @param {function(new:T, ...)} constructor The constructor for the Object.\r\n * @param {...*} var_args The arguments to be passed to the constructor.\r\n * @return {T} A new instance of the class given in `constructor`.\r\n * @template T\r\n */\r\ngoog.functions.create = function(constructor, var_args) {\r\n /**\r\n * @constructor\r\n * @final\r\n */\r\n var temp = function() {};\r\n temp.prototype = constructor.prototype;\r\n\r\n // obj will have constructor's prototype in its chain and\r\n // 'obj instanceof constructor' will be true.\r\n var obj = new temp();\r\n\r\n // obj is initialized by constructor.\r\n // arguments is only array-like so lacks shift(), but can be used with\r\n // the Array prototype function.\r\n constructor.apply(obj, Array.prototype.slice.call(arguments, 1));\r\n return obj;\r\n};\r\n\r\n\r\n/**\r\n * @define {boolean} Whether the return value cache should be used.\r\n * This should only be used to disable caches when testing.\r\n */\r\ngoog.functions.CACHE_RETURN_VALUE =\r\n goog.define('goog.functions.CACHE_RETURN_VALUE', true);\r\n\r\n\r\n/**\r\n * Gives a wrapper function that caches the return value of a parameterless\r\n * function when first called.\r\n *\r\n * When called for the first time, the given function is called and its\r\n * return value is cached (thus this is only appropriate for idempotent\r\n * functions). Subsequent calls will return the cached return value. This\r\n * allows the evaluation of expensive functions to be delayed until first used.\r\n *\r\n * To cache the return values of functions with parameters, see goog.memoize.\r\n *\r\n * @param {function():T} fn A function to lazily evaluate.\r\n * @return {function():T} A wrapped version the function.\r\n * @template T\r\n */\r\ngoog.functions.cacheReturnValue = function(fn) {\r\n var called = false;\r\n var value;\r\n\r\n return function() {\r\n if (!goog.functions.CACHE_RETURN_VALUE) {\r\n return fn();\r\n }\r\n\r\n if (!called) {\r\n value = fn();\r\n called = true;\r\n }\r\n\r\n return value;\r\n };\r\n};\r\n\r\n\r\n/**\r\n * Wraps a function to allow it to be called, at most, once. All\r\n * additional calls are no-ops.\r\n *\r\n * This is particularly useful for initialization functions\r\n * that should be called, at most, once.\r\n *\r\n * @param {function():*} f Function to call.\r\n * @return {function():undefined} Wrapped function.\r\n */\r\ngoog.functions.once = function(f) {\r\n // Keep a reference to the function that we null out when we're done with\r\n // it -- that way, the function can be GC'd when we're done with it.\r\n var inner = f;\r\n return function() {\r\n if (inner) {\r\n var tmp = inner;\r\n inner = null;\r\n tmp();\r\n }\r\n };\r\n};\r\n\r\n\r\n/**\r\n * Wraps a function to allow it to be called, at most, once per interval\r\n * (specified in milliseconds). If the wrapper function is called N times within\r\n * that interval, only the Nth call will go through.\r\n *\r\n * This is particularly useful for batching up repeated actions where the\r\n * last action should win. This can be used, for example, for refreshing an\r\n * autocomplete pop-up every so often rather than updating with every keystroke,\r\n * since the final text typed by the user is the one that should produce the\r\n * final autocomplete results. For more stateful debouncing with support for\r\n * pausing, resuming, and canceling debounced actions, use\r\n * `goog.async.Debouncer`.\r\n *\r\n * @param {function(this:SCOPE, ...?)} f Function to call.\r\n * @param {number} interval Interval over which to debounce. The function will\r\n * only be called after the full interval has elapsed since the last call.\r\n * @param {SCOPE=} opt_scope Object in whose scope to call the function.\r\n * @return {function(...?): undefined} Wrapped function.\r\n * @template SCOPE\r\n */\r\ngoog.functions.debounce = function(f, interval, opt_scope) {\r\n var timeout = 0;\r\n return /** @type {function(...?)} */ (function(var_args) {\r\n goog.global.clearTimeout(timeout);\r\n var args = arguments;\r\n timeout = goog.global.setTimeout(function() {\r\n f.apply(opt_scope, args);\r\n }, interval);\r\n });\r\n};\r\n\r\n\r\n/**\r\n * Wraps a function to allow it to be called, at most, once per interval\r\n * (specified in milliseconds). If the wrapper function is called N times in\r\n * that interval, both the 1st and the Nth calls will go through.\r\n *\r\n * This is particularly useful for limiting repeated user requests where the\r\n * the last action should win, but you also don't want to wait until the end of\r\n * the interval before sending a request out, as it leads to a perception of\r\n * slowness for the user.\r\n *\r\n * @param {function(this:SCOPE, ...?)} f Function to call.\r\n * @param {number} interval Interval over which to throttle. The function can\r\n * only be called once per interval.\r\n * @param {SCOPE=} opt_scope Object in whose scope to call the function.\r\n * @return {function(...?): undefined} Wrapped function.\r\n * @template SCOPE\r\n */\r\ngoog.functions.throttle = function(f, interval, opt_scope) {\r\n var timeout = 0;\r\n var shouldFire = false;\r\n var args = [];\r\n\r\n var handleTimeout = function() {\r\n timeout = 0;\r\n if (shouldFire) {\r\n shouldFire = false;\r\n fire();\r\n }\r\n };\r\n\r\n var fire = function() {\r\n timeout = goog.global.setTimeout(handleTimeout, interval);\r\n f.apply(opt_scope, args);\r\n };\r\n\r\n return /** @type {function(...?)} */ (function(var_args) {\r\n args = arguments;\r\n if (!timeout) {\r\n fire();\r\n } else {\r\n shouldFire = true;\r\n }\r\n });\r\n};\r\n\r\n\r\n/**\r\n * Wraps a function to allow it to be called, at most, once per interval\r\n * (specified in milliseconds). If the wrapper function is called N times within\r\n * that interval, only the 1st call will go through.\r\n *\r\n * This is particularly useful for limiting repeated user requests where the\r\n * first request is guaranteed to have all the data required to perform the\r\n * final action, so there's no need to wait until the end of the interval before\r\n * sending the request out.\r\n *\r\n * @param {function(this:SCOPE, ...?)} f Function to call.\r\n * @param {number} interval Interval over which to rate-limit. The function will\r\n * only be called once per interval, and ignored for the remainer of the\r\n * interval.\r\n * @param {SCOPE=} opt_scope Object in whose scope to call the function.\r\n * @return {function(...?): undefined} Wrapped function.\r\n * @template SCOPE\r\n */\r\ngoog.functions.rateLimit = function(f, interval, opt_scope) {\r\n var timeout = 0;\r\n\r\n var handleTimeout = function() {\r\n timeout = 0;\r\n };\r\n\r\n return /** @type {function(...?)} */ (function(var_args) {\r\n if (!timeout) {\r\n timeout = goog.global.setTimeout(handleTimeout, interval);\r\n f.apply(opt_scope, arguments);\r\n }\r\n });\r\n};\r\n","/**\n * @license\n * Copyright 2017 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Bring in closure-library dependencies\n */\n\ngoog.provide('firebase.webchannel.wrapper');\n\n// goog.net.WebChannelTransport\ngoog.require('goog.net.createWebChannelTransport');\ngoog.require('goog.labs.net.webChannel.WebChannelBaseTransport');\n/**\n * NOTE: The `createWebChannel` function takes an options object as a second param\n * whose properties are typically mangled. We override these in externs/overrides.js\n * Without those externs, this does not function properly.\n */\ngoog.labs.net.webChannel.WebChannelBaseTransport.prototype['createWebChannel'] =\n goog.labs.net.webChannel.WebChannelBaseTransport.prototype.createWebChannel;\ngoog.labs.net.webChannel.WebChannelBaseTransport.Channel.prototype['send'] =\n goog.labs.net.webChannel.WebChannelBaseTransport.Channel.prototype.send;\ngoog.labs.net.webChannel.WebChannelBaseTransport.Channel.prototype['open'] =\n goog.labs.net.webChannel.WebChannelBaseTransport.Channel.prototype.open;\ngoog.labs.net.webChannel.WebChannelBaseTransport.Channel.prototype['close'] =\n goog.labs.net.webChannel.WebChannelBaseTransport.Channel.prototype.close;\n\n// goog.net.ErrorCode\ngoog.require('goog.net.ErrorCode');\ngoog.net.ErrorCode['NO_ERROR'] = goog.net.ErrorCode.NO_ERROR;\ngoog.net.ErrorCode['TIMEOUT'] = goog.net.ErrorCode.TIMEOUT;\ngoog.net.ErrorCode['HTTP_ERROR'] = goog.net.ErrorCode.HTTP_ERROR;\n\n// goog.net.ErrorType\ngoog.require('goog.net.EventType');\ngoog.net.EventType['COMPLETE'] = goog.net.EventType.COMPLETE;\n\n// goog.net.WebChannel\ngoog.require('goog.net.WebChannel');\ngoog.require('goog.events.EventTarget');\ngoog.net.WebChannel['EventType'] = goog.net.WebChannel.EventType;\ngoog.net.WebChannel.EventType['OPEN'] = goog.net.WebChannel.EventType.OPEN;\ngoog.net.WebChannel.EventType['CLOSE'] = goog.net.WebChannel.EventType.CLOSE;\ngoog.net.WebChannel.EventType['ERROR'] = goog.net.WebChannel.EventType.ERROR;\ngoog.net.WebChannel.EventType['MESSAGE'] =\n goog.net.WebChannel.EventType.MESSAGE;\ngoog.events.EventTarget.prototype['listen'] =\n goog.events.EventTarget.prototype.listen;\n\n// goog.net.XhrIo\ngoog.require('goog.net.XhrIo');\ngoog.net.XhrIo.prototype['listenOnce'] = goog.net.XhrIo.prototype.listenOnce;\ngoog.net.XhrIo.prototype['getLastError'] =\n goog.net.XhrIo.prototype.getLastError;\ngoog.net.XhrIo.prototype['getLastErrorCode'] =\n goog.net.XhrIo.prototype.getLastErrorCode;\ngoog.net.XhrIo.prototype['getStatus'] = goog.net.XhrIo.prototype.getStatus;\ngoog.net.XhrIo.prototype['getResponseJson'] =\n goog.net.XhrIo.prototype.getResponseJson;\ngoog.net.XhrIo.prototype['getResponseText'] =\n goog.net.XhrIo.prototype.getResponseText;\ngoog.net.XhrIo.prototype['send'] = goog.net.XhrIo.prototype.send;\n\n/**\n * This ignore statement is required as closure will minify these properties\n * if done in the typical prettier format\n */\n// prettier-ignore\nmodule['exports'] = {\n 'createWebChannelTransport': goog.net.createWebChannelTransport,\n 'ErrorCode': goog.net.ErrorCode,\n 'EventType': goog.net.EventType,\n 'WebChannel': goog.net.WebChannel,\n 'XhrIo': goog.net.XhrIo\n};\n"],"names":["goog","goog.global","this","goog.isString","val","goog.isNumber","goog.getObjectByName","name","opt_obj","parts","split","cur","i","length","goog.nullFunction","goog.typeOf","value","s","className","Object","prototype","toString","call","splice","propertyIsEnumerable","goog.isArray","goog.isArrayLike","type","goog.isObject","goog.UID_PROPERTY_","Math","random","goog.uidCounter_","goog.bindNative_","fn","selfObj","var_args","apply","bind","arguments","goog.bindJs_","boundArgs","Array","slice","newArgs","unshift","goog.bind","Function","indexOf","goog.partial","args","push","goog.now","Date","now","goog.inherits","childCtor","parentCtor","tempCtor","superClass_","constructor","base","childCtor.base","me","methodName","goog.Disposable","disposed_","onDisposeCallbacks_","OFF","dispose","goog.Disposable.prototype.dispose","disposeInternal","goog.Disposable.MONITORING_MODE","goog.Disposable.MonitoringMode.OFF","uid","obj","goog.Disposable.prototype.disposeInternal","shift","goog.array.indexOf","arr","opt_fromIndex","fromIndex","goog.array.forEach","forEach","f","l","arr2","goog.array.find","goog.net.XhrIo.isContentTypeHeader_","charAt","goog.array.concat","concat","goog.array.toArray","object","rv","goog.string.internal.isEmptyOrWhitespace","str","test","goog.string.internal.trim","String","trim","exec","goog.string.internal.contains","subString","goog.string.internal.compareElements_","left","right","goog.labs.userAgent.util.userAgent_","navigator","goog.global.navigator","userAgent","goog.object.forEach","key","goog.object.clone","res","goog.object.PROTOTYPE_FIELDS_","goog.object.extend","target","source","j","goog.object.PROTOTYPE_FIELDS_.length","hasOwnProperty","goog.reflect.sinkValue","x","goog.reflect.cache","valueFn","cacheObj","goog.userAgent.isVersionOrHigherCache_","goog.userAgent.OPERA","goog.userAgent.IE","goog.userAgent.EDGE","goog.userAgent.EDGE_OR_IE","goog.userAgent.GECKO","toLowerCase","goog.userAgent.WEBKIT","goog.userAgent.getDocumentMode_","doc","undefined","goog.userAgent.VERSION","version","goog.userAgent.getVersionRegexResult_","docMode","parseFloat","goog.userAgent.isVersionOrHigher","order","v1Subs","v2Subs","subCount","max","subIdx","v1Sub","v2Sub","v1Comp","v2Comp","v1CompNum","parseInt","v2CompNum","mode","HAS_W3C_EVENT_SUPPORT","Number","goog.userAgent.DOCUMENT_MODE","SET_KEY_CODE_TO_PREVENT_DEFAULT","PASSIVE_EVENTS","goog.global.addEventListener","addEventListener","defineProperty","passive","options","get","goog.global.removeEventListener","removeEventListener","e","purify","goog.events.Event","opt_target","currentTarget","returnValue_","preventDefault","goog.events.Event.prototype.preventDefault","goog.events.BrowserEvent","opt_e","opt_currentTarget","goog.events.Event.call","goog.events.BrowserEvent.base","relatedTarget","button","screenY","screenX","clientY","clientX","metaKey","shiftKey","altKey","ctrlKey","pointerId","pointerType","event_","init","relevantTouch","changedTouches","srcElement","MOUSEOVER","fromElement","MOUSEOUT","toElement","pageX","pageY","goog.events.BrowserEvent.IE_POINTER_TYPE_MAP","defaultPrevented","arg","TOUCH","PEN","MOUSE","goog.events.BrowserEvent.prototype.preventDefault","goog.events.BrowserEvent.superClass_.preventDefault.call","be","returnValue","goog.events.BrowserFeature.SET_KEY_CODE_TO_PREVENT_DEFAULT","VK_F1","keyCode","VK_F12","ex","goog.events.Listenable.IMPLEMENTED_BY_PROP","goog.events.ListenableKey.counter_","goog.events.Listener","listener","src","capture","opt_handler","proxy","handler","removed","callOnce","goog.events.Listener.prototype.markAsRemoved","goog.events.ListenerMap","listeners","typeCount_","add","goog.events.ListenerMap.prototype.add","opt_useCapture","opt_listenerScope","typeStr","listenerArray","index","goog.events.ListenerMap.findListenerIndex_","listenerObj","goog.events.ListenerMap.prototype.removeByKey","markAsRemoved","goog.events.LISTENER_MAP_PROP_","goog.events.onStringMap_","opt_options","once","goog.events.listen","goog.events.wrapListener","listen","goog.events.listen_","goog.events.BrowserFeature.HAS_W3C_EVENT_SUPPORT","listenerMap","goog.events.getListenerMap_","goog.events.getProxy","goog.events.BrowserFeature.PASSIVE_EVENTS","attachEvent","goog.events.getOnString_","addListener","removeListener","proxyCallbackFunction","goog.events.handleBrowserEvent_","eventObject","v","goog.events.listenOnce","listenOnce","goog.events.unlisten","eventTargetListeners_","goog.events.unlistenByKey","removeByKey","detachEvent","goog.events.listenerCountEstimate_","goog.events.onString_","goog.events.fireListener","listenerFn","listenerHandler","opt_evt","evt","retval","goog.events.LISTENER_WRAPPER_PROP_","handleEvent","goog.events.EventTarget","goog.Disposable.call","actualEventTarget_","parentEventTarget_","goog.events.EventTarget.prototype","goog.events.EventTarget.prototype.addEventListener","opt_capture","opt_handlerScope","goog.events.EventTarget.prototype.removeEventListener","dispatchEvent","goog.events.EventTarget.prototype.dispatchEvent","ancestorsTree","ancestor","getParentEventTarget","oldEvent","opt_ancestorsTree","fireListeners","goog.events.EventTarget.prototype.disposeInternal","goog.events.EventTarget.superClass_.disposeInternal.call","removeAllListeners","goog_events_EventTarget_prototype$listen","goog.events.EventTarget.prototype.listen","goog_events_EventTarget_prototype$listenOnce","goog.events.EventTarget.prototype.listenOnce","goog.events.EventTarget.prototype.fireListeners","unlistenByKey","goog.json.serialize","create","reset","create_","reset_","occupants_","head_","goog.async.FreeList","item","next","goog.async.WorkQueue","workTail_","workHead_","goog.async.WorkQueue.freelist_","goog.async.WorkItem","goog.async.WorkQueue.prototype.add","scope","goog.async.WorkQueue.freelist_.get","set","goog.async.WorkQueue.prototype.remove","goog.async.run.workQueue_.remove","goog.async.WorkItem.prototype.set","goog.async.WorkItem.prototype.reset","goog.async.throwException","exception","goog.global.setTimeout","setTimeout","goog.async.run","callback","opt_context","goog.async.run.schedule_","goog.async.run.initializeRunner_","goog.async.run.workQueueScheduled_","goog.async.run.workQueue_.add","promise","goog.global.Promise.resolve","Promise","resolve","then","goog.async.run.processWorkQueue","goog.async.run.workQueue_","remove","put","goog.async.WorkQueue.freelist_.put","goog.async.WorkQueue.DEFAULT_MAX_UNUSED","goog.Timer","opt_interval","opt_timerObject","goog.events.EventTarget.call","interval_","timerObject_","boundTick_","tick_","last_","goog.Timer.prototype","goog_Timer_prototype$enabled","goog_Timer_prototype$timer_","goog.Timer.prototype.tick_","enabled","elapsed","goog.Timer.intervalScale","timer_","clearTimeout","dispatchTick","goog.Timer.TICK","stop","start","goog.Timer.prototype.start","goog.Timer.prototype.stop","goog.Timer.prototype.disposeInternal","goog.Timer.superClass_.disposeInternal.call","goog.Timer.callOnce","opt_delay","goog.Timer.INVALID_TIMEOUT_ID_","goog.async.Throttle","interval","goog.async.Throttle.base","listener_","callback_","onTimer_","args_","goog.async.Throttle.prototype","shouldFire_","goog_async_Throttle_prototype$timer_","fire","goog.async.Throttle.prototype.fire","doAction_","goog.async.Throttle.prototype.disposeInternal","goog.async.Throttle.superClass_.disposeInternal.call","goog.async.Throttle.prototype.disposeInternal.base","goog.global.clearTimeout","goog.async.Throttle.prototype.onTimer_","goog.async.Throttle.prototype.doAction_","goog.events.EventHandler","opt_scope","handler_","keys_","goog.events.EventHandler.typeArray_","goog.events.EventHandler.prototype.listen_","opt_fn","self","goog.events.EventHandler.prototype.removeAll","goog.events.EventHandler.prototype.disposeInternal","goog.events.EventHandler.superClass_.disposeInternal.call","removeAll","goog.events.EventHandler.prototype.handleEvent","goog.labs.net.webChannel.WebChannelDebug","goog.labs.net.webChannel.requestStats.statEventTarget_","requestStats.ServerReachabilityEvent","goog.labs.net.webChannel.requestStats.Event.SERVER_REACHABILITY_EVENT","goog.labs.net.webChannel.requestStats.ServerReachabilityEvent","requestStats.notifyServerReachabilityEvent","reachabilityType","goog.labs.net.webChannel.requestStats.statEventTarget_.dispatchEvent","requestStats.StatEvent","eventTarget","goog.labs.net.webChannel.requestStats.Event.STAT_EVENT","goog.labs.net.webChannel.requestStats.StatEvent","requestStats.notifyStatEvent","stat","requestStats.TimingEvent","goog.labs.net.webChannel.requestStats.Event.TIMING_EVENT","goog.labs.net.webChannel.requestStats.TimingEvent","requestStats.setTimeout","ms","goog.net.ErrorCode","NO_ERROR","ACCESS_DENIED","FILE_NOT_FOUND","FF_SILENT_ERROR","CUSTOM_ERROR","EXCEPTION","HTTP_ERROR","ABORT","TIMEOUT","OFFLINE","goog.net.EventType","COMPLETE","SUCCESS","ERROR","READY","READY_STATE_CHANGE","INCREMENTAL_DATA","PROGRESS","DOWNLOAD_PROGRESS","UPLOAD_PROGRESS","goog.net.XmlHttpFactory","cachedOptions_","goog.net.XmlHttpFactory.prototype.getOptions","goog.net.WebChannel","goog.net.WebChannel.EventType","OPEN","CLOSE","MESSAGE","goog.net.WebChannel.MessageEvent","goog.net.WebChannel.MessageEvent.base","goog.net.WebChannel.ErrorEvent","goog.net.WebChannel.ErrorEvent.base","goog.net.DefaultXmlHttpFactory","goog.net.XmlHttp.factory_","factory","goog.labs.net.webChannel.ChannelRequest","channel","opt_requestId","opt_retryId","channel_","rid_","retryId_","eventHandler_","timeout_","goog.labs.net.webChannel.ChannelRequest.TIMEOUT_MS_","EDGE_POLLING_INTERVAL_","pollingTimer_","extraHeaders_","successful_","postData_","requestUri_","baseUri_","type_","requestStartTime_","watchDogTimeoutTime_","watchDogTimerId_","pendingMessages_","xmlHttp_","xmlHttpChunkStart_","lastError_","verb_","lastStatusCode_","cancelled_","readyStateChangeThrottleMs_","readyStateChangeThrottle_","initialResponseDecoded_","decodeInitialResponse_","decodeChunks_","goog.labs.net.webChannel.ChannelRequest.INVALID_CHUNK_","goog.labs.net.webChannel.ChannelRequest.INCOMPLETE_CHUNK_","goog.labs.net.webChannel.ChannelRequest.prototype","ChannelRequest.prototype.setTimeout","timeout","ChannelRequest.prototype.xmlHttpPost","uri","postData","XML_HTTP","makeUnique","clone","decodeChunks","sendXmlHttp_","ChannelRequest.prototype.xmlHttpGet","hostPrefix","ChannelRequest.prototype.sendXmlHttp_","ensureWatchDogTimer_","setParameterValues","createXhrIo","shouldUseSecondaryDomains","useSecondaryDomains","xmlHttpHandler_","listen_","readyStateChangeHandler_","headers","send","goog.labs.net.webChannel.requestStats.notifyServerReachabilityEvent","REQUEST_MADE","ChannelRequest.prototype.readyStateChangeHandler_","xhr","throttle","INTERACTIVE","getReadyState","ChannelRequest.prototype.xmlHttpHandler_","xmlhttp","readyState","onXmlHttpReadyStateChanged_","errorCode","getLastErrorCode","statusCode","getStatus","getResponseText","REQUEST_FAILED","REQUEST_SUCCEEDED","cancelWatchDogTimer_","status","responseText","getStreamingResponseHeader","goog.net.WebChannel.X_HTTP_INITIAL_RESPONSE","initialResponse","safeOnRequestData_","UNKNOWN_SESSION_ID","goog.labs.net.webChannel.requestStats.notifyStatEvent","REQUEST_UNKNOWN_SESSION_ID","cleanup_","dispatchFailure_","decodeNextChunks_","pollResponse_","onRequestComplete","STATUS","REQUEST_BAD_STATUS","ChannelRequest.prototype.decodeNextChunks_","decodeNextChunksSuccessful","chunkText","getNextChunk_","BAD_DATA","REQUEST_INCOMPLETE_DATA","REQUEST_BAD_DATA","NO_DATA","REQUEST_NO_DATA","ChannelRequest.prototype.pollResponse_","ChannelRequest.prototype.getNextChunk_","sizeStartIndex","sizeEndIndex","size","substring","sizeAsString","isNaN","chunkStartIndex","substr","cancel","ChannelRequest.prototype.cancel","ChannelRequest.prototype.ensureWatchDogTimer_","startWatchDogTimer_","ChannelRequest.prototype.startWatchDogTimer_","time","goog.labs.net.webChannel.requestStats.setTimeout","onWatchDogTimeout_","ChannelRequest.prototype.cancelWatchDogTimer_","ChannelRequest.prototype.onWatchDogTimeout_","CLOSE_REQUEST","handleTimeout_","REQUEST_TIMEOUT","ChannelRequest.prototype.dispatchFailure_","isClosed","ChannelRequest.prototype.cleanup_","abort","ChannelRequest.prototype.safeOnRequestData_","data","onRequestData","BACK_CHANNEL_ACTIVITY","goog.structs.getValues","col","getValues","goog.structs.forEach","getKeys","values","keys","goog.structs.Map","opt_map","map_","count_","argLength","addAll","goog.structs.Map.prototype","goog.structs.Map.prototype.getValues","cleanupKeysArray_","goog.structs.Map.prototype.getKeys","goog.structs.Map.prototype.clear","goog.structs.Map.prototype.remove","goog.structs.Map.hasKey_","goog.structs.Map.prototype.cleanupKeysArray_","srcIndex","destIndex","seen","goog.structs.Map.prototype.get","opt_val","goog.structs.Map.prototype.set","goog.structs.Map.prototype.forEach","goog.uri.utils.splitRe_","goog.uri.utils.parseQueryData","encodedQuery","pairs","indexOfEquals","decodeURIComponent","replace","goog.Uri","opt_uri","opt_ignoreCase","domain_","userInfo_","scheme_","port_","fragment_","path_","ignoreCase_","m","setScheme","setUserInfo","setDomain","setPort","setPath","setQueryData","queryData_","setFragment","match","SCHEME","goog.Uri.decodeOrEmpty_","USER_INFO","DOMAIN","PORT","PATH","QUERY_DATA","FRAGMENT","goog.Uri.QueryData","goog.Uri.prototype.toString","out","scheme","getScheme","goog.Uri.encodeSpecialChars_","goog.Uri.reDisallowedInSchemeOrUserInfo_","domain","getDomain","userInfo","getUserInfo","encodeURIComponent","doubleEncodedString","port","getPort","path","getPath","hasDomain","goog.Uri.reDisallowedInAbsolutePath_","goog.Uri.reDisallowedInRelativePath_","query","getEncodedQuery","fragment","getFragment","goog.Uri.reDisallowedInFragment_","join","goog.Uri.prototype.resolve","relativeUri","absoluteUri","overridden","hasPath","lastSlashIndex","lastIndexOf","leadingSlash","prefix","segments","pos","segment","pop","goog.Uri.prototype.clone","goog.Uri.prototype.setScheme","newScheme","opt_decode","goog.Uri.prototype.setDomain","newDomain","goog.Uri.prototype.setPort","newPort","goog.Uri.prototype.setQueryData","queryData","setIgnoreCase","goog.Uri.reDisallowedInQuery_","goog.Uri.prototype.setParameterValue","goog.Uri.prototype.setParameterValues","setValues","goog.Uri.prototype.makeUnique","setParameterValue","RANDOM","floor","abs","goog.Uri.parse","goog.Uri.create","opt_scheme","opt_domain","opt_port","opt_path","opt_preserveReserved","decodeURI","unescapedPart","extra","opt_removeDoubleEncoding","encoded","encodeURI","goog.Uri.encodeChar_","ch","n","charCodeAt","opt_query","keyMap_","encodedQuery_","goog.Uri.QueryData.prototype.ensureKeyMapInitialized_","goog.Uri.QueryData.prototype","goog.Uri.QueryData.prototype.add","ensureKeyMapInitialized_","invalidateCache_","getKeyName_","goog.Uri.QueryData.prototype.remove","goog.Uri.QueryData.prototype.containsKey","goog.Uri.QueryData.prototype.forEach","goog.Uri.QueryData.prototype.getKeys","vals","goog.Uri.QueryData.prototype.getValues","opt_key","containsKey","goog.Uri.QueryData.prototype.set","goog.Uri.QueryData.prototype.get","opt_default","goog.Uri.QueryData.prototype.setValues","goog.Uri.QueryData.prototype.toString","sb","encodedKey","param","goog.Uri.QueryData.prototype.clone","goog.Uri.QueryData.prototype.getKeyName_","keyName","goog.Uri.QueryData.prototype.setIgnoreCase","ignoreCase","lowerCase","goog.debug.Formatter","goog.debug.TextFormatter","goog.labs.net.webChannel.BaseTestChannel","request_","receivedIntermediateResult_","clientProtocol_","hostPrefix_","goog.labs.net.webChannel.BaseTestChannel.prototype","goog_labs_net_webChannel_BaseTestChannel_prototype$state_","BaseTestChannel.prototype.checkBufferingProxy_","bufferingProxyResult","connState_","TEST_STAGE_TWO_START","PROXY","testConnectionFinished","NOPROXY","createDataUri","recvDataUri","httpSessionIdParam_","httpSessionId_","xmlHttpGet","BaseTestChannel.prototype.createXhrIo","BaseTestChannel.prototype.abort","BaseTestChannel.prototype.isClosed","BaseTestChannel.prototype.onRequestData","req","INIT","state_","applyControlHeaders_","backgroundChannelTest_","protocolHeader","goog.net.WebChannel.X_CLIENT_WIRE_PROTOCOL","httpSessionIdHeader","goog.net.WebChannel.X_HTTP_SESSION_ID","respArray","wireCodec_","parser_","parse","response","testChannel","signalError_","serverHostPrefix","CONNECTION_TESTING","TEST_STAGE_TWO_DATA_TWO","TEST_STAGE_TWO_DATA_ONE","documentMode","TEST_STAGE_TWO_DATA_BOTH","BaseTestChannel.prototype.onRequestComplete","checkBufferingProxy_","TEST_STAGE_ONE_FAILED","TEST_STAGE_TWO_FAILED","BaseTestChannel.prototype.shouldUseSecondaryDomains","goog_labs_net_webChannel_BaseTestChannel_prototype$isActive","BaseTestChannel.prototype.isActive","isActive","goog.labs.net.webChannel.ConnectionState","handshakeResult","goog.structs.Set","goog.structs.Set.getKey_","goog.structs.Set.prototype.add","element","goog.structs.Set.prototype.getValues","Wire.QueuedMap","mapId","map","ForwardChannelRequestPool","opt_maxPoolSize","maxPoolSizeConfigured_","module$contents$goog$labs$net$webChannel$ForwardChannelRequestPool_ForwardChannelRequestPool.MAX_POOL_SIZE_","goog.global.PerformanceNavigationTiming","PerformanceNavigationTiming","entrys","goog.global.performance.getEntriesByType","performance","getEntriesByType","nextHopProtocol","goog.global.chrome","chrome","goog.global.chrome.loadTimes","loadTimes","wasFetchedViaSpdy","maxSize_","requestPool_","ForwardChannelRequestPool.prototype.applyClientProtocol","clientProtocol","addRequest","ForwardChannelRequestPool.prototype.isFull","ForwardChannelRequestPool.prototype.getRequestCount","ForwardChannelRequestPool.prototype.hasRequest","ForwardChannelRequestPool.prototype.addRequest","ForwardChannelRequestPool.prototype.removeRequest","ForwardChannelRequestPool.prototype.cancel","getPendingMessages","clear","ForwardChannelRequestPool.prototype.getPendingMessages","result","goog.json.NativeJsonProcessor","stringify","goog.json.NativeJsonProcessor.prototype.stringify","opt_replacer","goog.json.NativeJsonProcessor.prototype.parse","opt_reviver","goog.labs.net.webChannel.WireV8","WireV8.prototype.encodeMessage","message","buffer","opt_prefix","encodedValue","netUtils.testLoadImage","url","channelDebug","goog.global.Image","Image","img","onload","goog.labs.net.webChannel.netUtils.imageCallback_","onerror","onabort","ontimeout","goog.labs.net.webChannel.netUtils.NETWORK_TIMEOUT","netUtils.imageCallback_","debugText","goog.json.hybrid.parse","goog.net.XhrIo","opt_xmlHttpFactory","goog.net.XhrIo.base","xmlHttpFactory_","active_","xhrOptions_","xhr_","lastUri_","lastErrorCode_","inAbort_","inOpen_","inSend_","errorDispatched_","timeoutInterval_","timeoutId_","responseType_","goog.net.XhrIo.ResponseType.DEFAULT","useXhr2Timeout_","withCredentials_","DEFAULT","goog.net.XhrIo.HTTP_SCHEME_PATTERN","goog.net.XhrIo.METHODS_WITH_FORM_DATA","goog.net.XhrIo.prototype","goog_net_XhrIo_prototype$send","goog.net.XhrIo.prototype.send","opt_method","opt_content","opt_headers","method","toUpperCase","XMLHttpRequest","getOptions","goog.net.XmlHttp.factory_.getOptions","onreadystatechange","onReadyStateChange_","open","err","error_","content","contentTypeKey","contentIsFormData","goog.net.XhrIo.CONTENT_TYPE_HEADER","goog.net.XhrIo.FORM_CONTENT_TYPE","setRequestHeader","responseType","withCredentials","cleanUpTimeoutTimer_","goog.net.XhrIo.shouldUseXhr2Timeout_","header","goog_net_XhrIo_prototype$timeout_","goog.net.XhrIo.prototype.timeout_","goog.net.XhrIo.prototype.error_","dispatchErrors_","cleanUpXhr_","goog.net.XhrIo.prototype.dispatchErrors_","goog.net.XhrIo.prototype.abort","opt_failureCode","goog.net.XhrIo.prototype.disposeInternal","goog.net.XhrIo.superClass_.disposeInternal.call","goog.net.XhrIo.prototype.disposeInternal.base","goog.net.XhrIo.prototype.onReadyStateChange_","isDisposed","onReadyStateChangeHelper_","onReadyStateChangeEntryPoint_","goog.net.XhrIo.prototype.onReadyStateChangeEntryPoint_","goog.net.XhrIo.prototype.onReadyStateChangeHelper_","LOCAL_REQUEST_ERROR","isComplete","isSuccess","OK","CREATED","ACCEPTED","NO_CONTENT","PARTIAL_CONTENT","NOT_MODIFIED","QUIRK_IE_NO_CONTENT","goog.global.self","goog.global.self.location","location","protocol","goog.global.self.location.protocol","goog.net.XhrIo.HTTP_SCHEME_PATTERN.test","LOADED","getStatusText","statusText","goog.net.XhrIo.prototype.cleanUpXhr_","opt_fromDispose","clearedOnReadyStateChange","USE_NULL_FUNCTION","goog.net.XhrIo.prototype.cleanUpTimeoutTimer_","goog.net.XhrIo.prototype.getReadyState","UNINITIALIZED","goog.net.XhrIo.prototype.getStatus","goog.net.XhrIo.prototype.getResponseText","getResponseJson","goog.net.XhrIo.prototype.getResponseJson","opt_xssiPrefix","goog.net.XhrIo.prototype.getStreamingResponseHeader","getResponseHeader","goog.net.XhrIo.prototype.getLastErrorCode","goog_net_XhrIo_prototype$getLastError","goog.net.XhrIo.prototype.getLastError","exports.generateHttpHeadersOverwriteParam","exports.setHttpHeadersWithOverwriteParam","urlParam","extraHeaders","httpHeaders","module$exports$goog$net$rpc$HttpCors.generateHttpHeadersOverwriteParam","hashIndex","questionIndex","goog.labs.net.webChannel.WebChannelBase","outgoingMaps_","backChannelUri_","forwardChannelUri_","backChannelRequest_","extraParams_","httpHeadersOverwriteParam_","initHeaders_","nextMapId_","nextRid_","failFast_","useChunked_","connectionTest_","deadBackChannelTimerId_","backChannelTimerId_","forwardChannelTimerId_","allowChunkedMode_","lastPostResponseArrayId_","lastArrayId_","backChannelAttemptId_","backChannelRetryCount_","forwardChannelRetryCount_","baseRetryDelayMs_","retryDelaySeedMs_","forwardChannelMaxRetries_","forwardChannelRequestTimeoutMs_","xmlHttpFactory","backChannelRequestTimeoutMs_","supportsCrossDomainXhrs_","supportsCrossDomainXhr","sid_","forwardChannelRequestPool_","concurrentRequestLimit","backgroundChannelTest","fastHandshake_","fastHandshake","forceLongPolling","forwardChannelFlushedCallback_","goog.labs.net.webChannel.WebChannelBase.prototype","channelVersion_","goog.labs.net.webChannel.Wire.LATEST_CHANNEL_VERSION","goog_labs_net_webChannel_WebChannelBase_prototype$state_","WebChannelBase.prototype.disconnect","cancelRequests_","OPENED","rid","addAdditionalParams_","request","requestSent","goog.global.navigator.sendBeacon","sendBeacon","eltImg","onClose_","WebChannelBase.prototype.cancelRequests_","clearDeadBackchannelTimer_","clearForwardChannelTimer_","WebChannelBase.prototype.sendMap","goog.labs.net.webChannel.Wire.QueuedMap","ensureForwardChannel_","WebChannelBase.prototype.isClosed","WebChannelBase.prototype.ensureForwardChannel_","isFull","onStartForwardChannelTimer_","WebChannelBase.prototype.maybeRetryForwardChannel_","getRequestCount","OPENING","getForwardChannelMaxRetries","getRetryTime_","WebChannelBase.prototype.onStartForwardChannelTimer_","opt_retryRequest","startForwardChannel_","total","goog.labs.net.webChannel.Wire.RAW_DATA_KEY","goog.labs.net.webChannel.WebChannelBase.MAX_CHARS_PER_GET_","goog.labs.net.webChannel.WebChannelBase.MAX_MAPS_PER_REQUEST_","requestText","dequeueOutgoingMaps_","goog.net.WebChannelTransport.CLIENT_VERSION","module$exports$goog$net$rpc$HttpCors.setHttpHeadersWithOverwriteParam","xmlHttpPost","makeForwardChannelRequest_","WebChannelBase.prototype.makeForwardChannelRequest_","requeuePendingMaps_","round","WebChannelBase.prototype.addAdditionalParams_","params","WebChannelBase.prototype.dequeueOutgoingMaps_","maxNum","count","min","badMapHandler","badMapError","offset","messageQueue","done","encodeMessage","pendingMessages","WebChannelBase.prototype.ensureBackChannel_","onStartBackChannelTimer_","WebChannelBase.prototype.maybeRetryBackChannel_","goog.labs.net.webChannel.WebChannelBase.BACK_CHANNEL_MAX_RETRIES","WebChannelBase.prototype.onStartBackChannelTimer_","startBackChannel_","WebChannelBase.prototype.testConnectionFinished","useChunked","applyClientProtocol","connectChannel_","WebChannelBase.prototype.onRequestData","CLOSED","hasRequest","responseValues","handlePostResponse_","goog.labs.net.webChannel.WebChannelBase.RTT_ESTIMATE","maybeRetryBackChannel_","BACKCHANNEL_MISSING","goog.labs.net.webChannel.WebChannelBase.OUTSTANDING_DATA_BACKCHANNEL_RETRY_CUTOFF","numOutstandingBackchannelBytes","onBackChannelDead_","onForwardChannelFlushed_","BAD_RESPONSE","nextArray","onInput_","negotiatedVersion","serverKeepaliveMs","channelOpened","removeRequest","opt_timeout","ensureBackChannel_","STOP","disconnect","channelHandleArray","WebChannelBase.prototype.onBackChannelDead_","BACKCHANNEL_DEAD","WebChannelBase.prototype.clearDeadBackchannelTimer_","WebChannelBase.prototype.onRequestComplete","BACK_CHANNEL","FORWARD_CHANNEL","rtt","lastError","maybeRetryForwardChannel_","WebChannelBase.prototype.getRetryTime_","retryCount","retryTime","goog.labs.net.webChannel.WebChannelBase.INACTIVE_CHANNEL_RETRY_FACTOR","WebChannelBase.prototype.signalError_","error","imageUri","testNetworkCallback_","goog.global.location","goog.global.location.protocol","goog.labs.net.webChannel.netUtils.testLoadImage","ERROR_OTHER","onError_","channelError","WebChannelBase.prototype.testNetworkCallback_","networkUp","ERROR_NETWORK","WebChannelBase.prototype.onClose_","channelClosed","WebChannelBase.prototype.createDataUri","locationPage","hostName","hostname","getHttpSessionIdParam","getHttpSessionId","WebChannelBase.prototype.createXhrIo","WebChannelBase.prototype.isActive","WebChannelBase.prototype.shouldUseSecondaryDomains","goog.labs.net.webChannel.WebChannelBase.Handler.prototype","WebChannelBase.Handler.prototype.channelOpened","WebChannelBase.Handler.prototype.channelHandleArray","WebChannelBase.Handler.prototype.channelError","WebChannelBase.Handler.prototype.channelClosed","WebChannelBase.Handler.prototype.badMapError","goog.string.path.join","suffix","goog.labs.net.webChannel.WebChannelBaseTransport","createWebChannel","WebChannelBaseTransport.prototype.createWebChannel","goog.labs.net.webChannel.WebChannelBaseTransport.Channel","WebChannelBaseTransport.Channel","goog.labs.net.webChannel.WebChannelBaseTransport.Channel.base","url_","testUrl_","testUrl","messageUrlParams_","messageUrlParams","messageHeaders","clientProtocolHeaderRequired","goog.net.WebChannel.X_CLIENT_PROTOCOL","goog.net.WebChannel.X_CLIENT_PROTOCOL_WEB_CHANNEL","initHeaders","initMessageHeaders","messageContentType","goog.net.WebChannel.X_WEBCHANNEL_CONTENT_TYPE","clientProfile","goog.net.WebChannel.X_WEBCHANNEL_CLIENT_PROFILE","httpHeadersOverwriteParam","supportsCrossDomainXhr_","sendRawJson_","sendRawJson","httpSessionIdParam","channelHandler_","goog.labs.net.webChannel.WebChannelBaseTransport.Channel.Handler_","goog.labs.net.webChannel.WebChannelBaseTransport.Channel.prototype","WebChannelBaseTransport.Channel.prototype.addEventListener","goog.labs.net.webChannel.WebChannelBaseTransport.Channel.superClass_.addEventListener.call","goog.labs.net.webChannel.WebChannelBaseTransport.Channel.prototype.addEventListener.base","WebChannelBaseTransport.Channel.prototype.removeEventListener","goog.labs.net.webChannel.WebChannelBaseTransport.Channel.superClass_.removeEventListener.call","goog.labs.net.webChannel.WebChannelBaseTransport.Channel.prototype.removeEventListener.base","goog_labs_net_webChannel_WebChannelBaseTransport_Channel_prototype$open","WebChannelBaseTransport.Channel.prototype.open","supportCrossDomain","CONNECT_ATTEMPT","channelPath","opt_extraParams","connectTest_","urlPath","testPath","sendDataUri","TEST_STAGE_ONE_START","close","WebChannelBaseTransport.Channel.prototype.close","goog_labs_net_webChannel_WebChannelBaseTransport_Channel_prototype$send","WebChannelBaseTransport.Channel.prototype.send","rawJson","sendMap","WebChannelBaseTransport.Channel.prototype.disposeInternal","goog.labs.net.webChannel.WebChannelBaseTransport.Channel.superClass_.disposeInternal.call","goog.labs.net.webChannel.WebChannelBaseTransport.Channel.prototype.disposeInternal.base","WebChannelBaseTransport.Channel.MessageEvent","array","goog.net.WebChannel.MessageEvent.call","goog.labs.net.webChannel.WebChannelBaseTransport.Channel.MessageEvent.base","metadata","metadataKey","goog.labs.net.webChannel.WebChannelBaseTransport.Channel.MessageEvent","WebChannelBaseTransport.Channel.ErrorEvent","goog.net.WebChannel.ErrorEvent.call","goog.labs.net.webChannel.WebChannelBaseTransport.Channel.ErrorEvent.base","NETWORK_ERROR","goog.labs.net.webChannel.WebChannelBaseTransport.Channel.ErrorEvent","WebChannelBaseTransport.Channel.Handler_","goog.labs.net.webChannel.WebChannelBase.Handler","WebChannelBaseTransport.Channel.Handler_.prototype.channelOpened","WebChannelBaseTransport.Channel.Handler_.prototype.channelHandleArray","WebChannelBaseTransport.Channel.Handler_.prototype.channelError","WebChannelBaseTransport.Channel.Handler_.prototype.channelClosed","goog.net.createWebChannelTransport","goog.functions.create","temp","getLastError","module"],"mappings":"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"} |