1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
7 /** @suppress {duplicate} */
8 var remoting = remoting || {};
11 * A wrapper for remoting.Error.Tag. Having a wrapper makes it
12 * possible to use instanceof checks on caught exceptions. It also
13 * allows adding more detailed error information if desired.
16 * @param {remoting.Error.Tag} tag
17 * @param {string=} opt_detail
19 remoting.Error = function(tag, opt_detail) {
20 /** @private @const {remoting.Error.Tag} */
23 /** @const {?string} */
24 this.detail_ = opt_detail || null;
30 remoting.Error.prototype.toString = function() {
31 var result = this.tag_;
32 if (this.detail_ != null) {
33 result += ' (' + this.detail_ + ')';
39 * @return {remoting.Error.Tag} The tag used to create this Error.
41 remoting.Error.prototype.getTag = function() {
46 * @return {?string} The detail string passed to the constructor, if any.
48 remoting.Error.prototype.getDetail = function() {
53 * Checks the type of an error.
54 * @param {remoting.Error.Tag} tag
55 * @param {...remoting.Error.Tag} var_args
56 * @return {boolean} True if this object has one of the specified tags.
57 * @suppress {reportUnknownTypes}
59 remoting.Error.prototype.hasTag = function(tag, var_args) {
60 var thisTag = this.tag_;
61 return Array.prototype.some.call(
63 function(/** remoting.Error.Tag */ tag) {
64 return thisTag == tag;
69 * @return {boolean} True if this object's tag is NONE, meaning this
70 * object represents the lack of an error.
72 remoting.Error.prototype.isNone = function() {
73 return this.hasTag(remoting.Error.Tag.NONE);
77 * Convenience method for creating the second most common error type.
78 * @return {!remoting.Error}
80 remoting.Error.none = function() {
81 return new remoting.Error(remoting.Error.Tag.NONE);
85 * Convenience method for creating the most common error type.
86 * @param {string=} opt_detail
87 * @return {!remoting.Error}
89 remoting.Error.unexpected = function(opt_detail) {
90 return new remoting.Error(remoting.Error.Tag.UNEXPECTED, opt_detail);
94 * @enum {string} All error messages from messages.json
96 remoting.Error.Tag = {
99 // Used to signify that an operation was cancelled by the user. This should
100 // not normally cause the error text to be shown to the user, so the
101 // i18n-content prefix is not needed in this case.
102 CANCELLED: '__CANCELLED__',
103 // Used to signify that the local computer was suspended for long enough that
104 // the connection is expected to drop, allowing a reconnect attempt to be
105 // scheduled sooner. This is not shown to the user so i18n-content prefix is
106 // not needed in this case.
107 CLIENT_SUSPENDED: '__CLIENT_SUSPENDED__',
109 INVALID_ACCESS_CODE: /*i18n-content*/ 'ERROR_INVALID_ACCESS_CODE',
110 MISSING_PLUGIN: /*i18n-content*/ 'ERROR_MISSING_PLUGIN',
111 AUTHENTICATION_FAILED: /*i18n-content*/ 'ERROR_AUTHENTICATION_FAILED',
112 HOST_IS_OFFLINE: /*i18n-content*/ 'ERROR_HOST_IS_OFFLINE',
113 INCOMPATIBLE_PROTOCOL: /*i18n-content*/ 'ERROR_INCOMPATIBLE_PROTOCOL',
114 BAD_PLUGIN_VERSION: /*i18n-content*/ 'ERROR_BAD_PLUGIN_VERSION',
115 NETWORK_FAILURE: /*i18n-content*/ 'ERROR_NETWORK_FAILURE',
116 HOST_OVERLOAD: /*i18n-content*/ 'ERROR_HOST_OVERLOAD',
117 UNEXPECTED: /*i18n-content*/ 'ERROR_UNEXPECTED',
118 SERVICE_UNAVAILABLE: /*i18n-content*/ 'ERROR_SERVICE_UNAVAILABLE',
119 NOT_AUTHENTICATED: /*i18n-content*/ 'ERROR_NOT_AUTHENTICATED',
120 NOT_FOUND: /*i18n-content*/ 'ERROR_NOT_FOUND',
121 INVALID_HOST_DOMAIN: /*i18n-content*/ 'ERROR_INVALID_HOST_DOMAIN',
122 P2P_FAILURE: /*i18n-content*/ 'ERROR_P2P_FAILURE',
123 REGISTRATION_FAILED: /*i18n-content*/ 'ERROR_HOST_REGISTRATION_FAILED',
124 NOT_AUTHORIZED: /*i18n-content*/ 'ERROR_NOT_AUTHORIZED',
125 // TODO(garykac): Move app-specific errors into separate location.
126 APP_NOT_AUTHORIZED: /*i18n-content*/ 'ERROR_APP_NOT_AUTHORIZED'
129 // A whole bunch of semi-redundant constants, mostly to reduce to size
130 // of the diff that introduced the remoting.Error class.
132 // Please don't add any more constants here; just call the
133 // remoting.Error constructor directly
136 * @param {number} httpStatus An HTTP status code.
137 * @return {!remoting.Error} The remoting.Error enum corresponding to the
138 * specified HTTP status code.
140 remoting.Error.fromHttpStatus = function(httpStatus) {
141 if (httpStatus == 0) {
142 return new remoting.Error(remoting.Error.Tag.NETWORK_FAILURE);
143 } else if (httpStatus >= 200 && httpStatus < 300) {
144 return remoting.Error.none();
145 } else if (httpStatus == 400 || httpStatus == 401) {
146 return new remoting.Error(remoting.Error.Tag.AUTHENTICATION_FAILED);
147 } else if (httpStatus == 403) {
148 return new remoting.Error(remoting.Error.Tag.NOT_AUTHORIZED);
149 } else if (httpStatus == 404) {
150 return new remoting.Error(remoting.Error.Tag.NOT_FOUND);
151 } else if (httpStatus >= 500 && httpStatus < 600) {
152 return new remoting.Error(remoting.Error.Tag.SERVICE_UNAVAILABLE);
154 console.warn('Unexpected HTTP error code: ' + httpStatus);
155 return remoting.Error.unexpected();
160 * Create an error-handling function suitable for passing to a
161 * Promise's "catch" method.
163 * @param {function(!remoting.Error):void} onError
164 * @return {function(*):void}
166 remoting.Error.handler = function(onError) {
167 return function(/** * */ error) {
168 if (error instanceof remoting.Error) {
169 onError(/** @type {!remoting.Error} */ (error));
171 console.error('Unexpected error:', error);
172 onError(remoting.Error.unexpected());