1use error_support::{ErrorHandling, GetErrorHandling};
6use rc_crypto::hawk;
7use std::string;
8
9#[derive(Debug, thiserror::Error)]
14pub enum FxaError {
15 #[error("authentication error")]
20 Authentication,
21 #[error("forbidden")]
26 Forbidden,
27 #[error("network error")]
30 Network,
31 #[error("no authentication flow was active")]
37 NoExistingAuthFlow,
38 #[error("the requested authentication flow was not active")]
46 WrongAuthFlow,
47 #[error("Origin mismatch")]
52 OriginMismatch,
53 #[error("The sync scoped key was missing")]
55 SyncScopedKeyMissingInServerResponse,
56 #[error("panic in native code")]
60 Panic,
61 #[error("other error: {0}")]
63 Other(String),
64}
65
66#[derive(Debug, thiserror::Error)]
69pub enum Error {
70 #[error("Server asked the client to back off, please wait {0} seconds to try again")]
71 BackoffError(u64),
72
73 #[error("Unknown OAuth State")]
74 UnknownOAuthState,
75
76 #[error("No cached scoped keys for scope {0}")]
77 NoScopedKey(String),
78
79 #[error("No stored refresh token")]
80 NoRefreshToken,
81
82 #[error("No stored session token")]
83 NoSessionToken,
84
85 #[error("No stored migration data")]
86 NoMigrationData,
87
88 #[error("No stored current device id")]
89 NoCurrentDeviceId,
90
91 #[error("Device target is unknown (Device ID: {0})")]
92 UnknownTargetDevice(String),
93
94 #[error("Api client error {0}")]
95 ApiClientError(&'static str),
96
97 #[error("Illegal state: {0}")]
98 IllegalState(&'static str),
99
100 #[error("Unknown command: {0}")]
101 UnknownCommand(String),
102
103 #[error("Send Tab diagnosis error: {0}")]
104 SendTabDiagnosisError(&'static str),
105
106 #[error("Cannot xor arrays with different lengths: {0} and {1}")]
107 XorLengthMismatch(usize, usize),
108
109 #[error("Origin mismatch: {0}")]
110 OriginMismatch(String),
111
112 #[error("Remote key and local key mismatch")]
113 MismatchedKeys,
114
115 #[error("The response from the server, or the content in that reponse, was unexpected")]
119 UnexpectedServerResponse,
120
121 #[error("The sync scoped key was missing in the server response")]
125 SyncScopedKeyMissingInServerResponse,
126
127 #[error("Client: {0} is not allowed to request scope: {1}")]
128 ScopeNotAllowed(String, String),
129
130 #[error("Unsupported command: {0}")]
131 UnsupportedCommand(&'static str),
132
133 #[error("Missing URL parameter: {0}")]
134 MissingUrlParameter(&'static str),
135
136 #[error("Null pointer passed to FFI")]
137 NullPointer,
138
139 #[error("Invalid buffer length: {0}")]
140 InvalidBufferLength(i32),
141
142 #[error("Too many calls to auth introspection endpoint")]
143 AuthCircuitBreakerError,
144
145 #[error("Remote server error: '{code}' '{errno}' '{error}' '{message}' '{info}'")]
146 RemoteError {
147 code: u64,
148 errno: u64,
149 error: String,
150 message: String,
151 info: String,
152 },
153
154 #[error("Crypto/NSS error: {0}")]
156 CryptoError(#[from] rc_crypto::Error),
157
158 #[error("http-ece encryption error: {0}")]
159 EceError(#[from] rc_crypto::ece::Error),
160
161 #[error("Hex decode error: {0}")]
162 HexDecodeError(#[from] hex::FromHexError),
163
164 #[error("Base64 decode error: {0}")]
165 Base64Decode(#[from] base64::DecodeError),
166
167 #[error("JSON error: {0}")]
168 JsonError(#[from] serde_json::Error),
169
170 #[error("JWCrypto error: {0}")]
171 JwCryptoError(#[from] jwcrypto::JwCryptoError),
172
173 #[error("UTF8 decode error: {0}")]
174 UTF8DecodeError(#[from] string::FromUtf8Error),
175
176 #[error("Network error: {0}")]
177 RequestError(#[from] viaduct::ViaductError),
178
179 #[error("Malformed URL: {sanitized_url} ({when})")]
180 MalformedUrl {
181 sanitized_url: String,
184 when: String,
185 },
186
187 #[error("Unexpected HTTP status: {0}")]
188 UnexpectedStatus(#[from] viaduct::UnexpectedStatus),
189
190 #[error("Sync15 error: {0}")]
191 SyncError(#[from] sync15::Error),
192
193 #[error("HAWK error: {0}")]
194 HawkError(#[from] hawk::Error),
195
196 #[error("Integer conversion error: {0}")]
197 IntegerConversionError(#[from] std::num::TryFromIntError),
198
199 #[error("Command not found by fxa")]
200 CommandNotFound,
201
202 #[error("Invalid Push Event")]
203 InvalidPushEvent,
204
205 #[error("Invalid state transition: {0}")]
206 InvalidStateTransition(String),
207
208 #[error("Internal error in the state machine: {0}")]
209 StateMachineLogicError(String),
210}
211
212impl GetErrorHandling for Error {
215 type ExternalError = FxaError;
216
217 fn get_error_handling(&self) -> ErrorHandling<Self::ExternalError> {
218 match self {
219 Error::RemoteError { code: 401, .. }
220 | Error::NoRefreshToken
221 | Error::NoSessionToken
222 | Error::NoScopedKey(_) => {
223 ErrorHandling::convert(FxaError::Authentication).log_warning()
224 }
225 Error::RemoteError { code: 403, .. } => {
226 ErrorHandling::convert(FxaError::Forbidden).log_warning()
227 }
228 Error::RequestError(_) => ErrorHandling::convert(FxaError::Network).log_warning(),
229 Error::SyncScopedKeyMissingInServerResponse => {
230 ErrorHandling::convert(FxaError::SyncScopedKeyMissingInServerResponse)
231 .report_error("fxa-client-scoped-key-missing")
232 }
233 Error::UnknownOAuthState => {
234 ErrorHandling::convert(FxaError::NoExistingAuthFlow).log_warning()
235 }
236 Error::BackoffError(_) => ErrorHandling::convert(FxaError::Other(self.to_string()))
237 .report_error("fxa-client-backoff"),
238 Error::InvalidStateTransition(_) | Error::StateMachineLogicError(_) => {
239 ErrorHandling::convert(FxaError::Other(self.to_string()))
240 .report_error("fxa-state-machine-error")
241 }
242 Error::OriginMismatch(_) => ErrorHandling::convert(FxaError::OriginMismatch),
243 Error::MalformedUrl { .. } => {
246 ErrorHandling::convert(FxaError::Other(self.to_string())).log_warning()
247 }
248 _ => ErrorHandling::convert(FxaError::Other(self.to_string()))
249 .report_error("fxa-client-other-error"),
250 }
251 }
252}