Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / remoting / webapp / base / js / error.js
blob8e321c9f2e849fa59f328d9256e71af5838ed617
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.
5 'use strict';
7 /** @suppress {duplicate} */
8 var remoting = remoting || {};
10 /**
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.
14  *
15  * @constructor
16  * @param {remoting.Error.Tag} tag
17  * @param {string=} opt_detail
18  */
19 remoting.Error = function(tag, opt_detail) {
20   /** @private @const {remoting.Error.Tag} */
21   this.tag_ = tag;
23   /** @const {?string} */
24   this.detail_ = opt_detail || null;
27 /**
28  * @override
29  */
30 remoting.Error.prototype.toString = function() {
31   var result = this.tag_;
32   if (this.detail_ != null) {
33     result += ' (' + this.detail_ + ')';
34   }
35   return result;
38 /**
39  * @return {remoting.Error.Tag} The tag used to create this Error.
40  */
41 remoting.Error.prototype.getTag = function() {
42   return this.tag_;
45 /**
46  * @return {?string} The detail string passed to the constructor, if any.
47  */
48 remoting.Error.prototype.getDetail = function() {
49   return this.detail_;
52 /**
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}
58  */
59 remoting.Error.prototype.hasTag = function(tag, var_args) {
60   var thisTag = this.tag_;
61   return Array.prototype.some.call(
62       arguments,
63       function(/** remoting.Error.Tag */ tag) {
64         return thisTag == tag;
65       });
68 /**
69  * @return {boolean} True if this object's tag is NONE, meaning this
70  *     object represents the lack of an error.
71  */
72 remoting.Error.prototype.isNone = function() {
73   return this.hasTag(remoting.Error.Tag.NONE);
76 /**
77  * Convenience method for creating the second most common error type.
78  * @return {!remoting.Error}
79  */
80 remoting.Error.none = function() {
81   return new remoting.Error(remoting.Error.Tag.NONE);
84 /**
85  * Convenience method for creating the most common error type.
86  * @param {string=} opt_detail
87  * @return {!remoting.Error}
88  */
89 remoting.Error.unexpected = function(opt_detail) {
90   return new remoting.Error(remoting.Error.Tag.UNEXPECTED, opt_detail);
93 /**
94  * @enum {string} All error messages from messages.json
95  */
96 remoting.Error.Tag = {
97   NONE: '',
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.
139  */
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);
153   } else {
154     console.warn('Unexpected HTTP error code: ' + httpStatus);
155     return remoting.Error.unexpected();
156   }
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}
165  */
166 remoting.Error.handler = function(onError) {
167   return function(/** * */ error) {
168     if (error instanceof remoting.Error) {
169       onError(/** @type {!remoting.Error} */ (error));
170     } else {
171       console.error('Unexpected error:', error);
172       onError(remoting.Error.unexpected());
173     }
174   };