tabs/
error.rs

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5use error_support::{ErrorHandling, GetErrorHandling};
6
7/// Result enum for the public interface
8pub type ApiResult<T> = std::result::Result<T, TabsApiError>;
9/// Result enum for internal functions
10pub type Result<T> = std::result::Result<T, Error>;
11
12// Errors we return via the public interface.
13#[derive(Debug, thiserror::Error)]
14pub enum TabsApiError {
15    #[error("SyncError: {reason}")]
16    SyncError { reason: String },
17
18    #[error("SqlError: {reason}")]
19    SqlError { reason: String },
20
21    #[error("Unexpected tabs error: {reason}")]
22    UnexpectedTabsError { reason: String },
23}
24
25// Error we use internally
26#[derive(Debug, thiserror::Error)]
27pub enum Error {
28    // For historical reasons we have a mis-matched name between the error
29    // and what the error actually represents.
30    #[error("Sync feature is disabled: {0}")]
31    SyncAdapterError(String),
32
33    #[error("Error parsing JSON data: {0}")]
34    JsonError(#[from] serde_json::Error),
35
36    #[error("Missing SyncUnlockInfo Local ID")]
37    MissingLocalIdError,
38
39    #[error("Error parsing URL: {0}")]
40    UrlParseError(#[from] url::ParseError),
41
42    #[error("Error executing SQL: {0}")]
43    SqlError(#[from] rusqlite::Error),
44
45    #[error("Error opening database: {0}")]
46    OpenDatabaseError(#[from] sql_support::open_database::Error),
47
48    #[error("Unexpected connection state")]
49    UnexpectedConnectionState,
50}
51
52// Define how our internal errors are handled and converted to external errors
53// See `support/error/README.md` for how this works, especially the warning about PII.
54impl GetErrorHandling for Error {
55    type ExternalError = TabsApiError;
56
57    fn get_error_handling(&self) -> ErrorHandling<Self::ExternalError> {
58        match self {
59            Self::SyncAdapterError(e) => ErrorHandling::convert(TabsApiError::SyncError {
60                reason: e.to_string(),
61            })
62            .report_error("tabs-sync-error"),
63            Self::JsonError(e) => ErrorHandling::convert(TabsApiError::UnexpectedTabsError {
64                reason: e.to_string(),
65            })
66            .report_error("tabs-json-error"),
67            Self::MissingLocalIdError => {
68                ErrorHandling::convert(TabsApiError::UnexpectedTabsError {
69                    reason: "MissingLocalId".to_string(),
70                })
71                .report_error("tabs-missing-local-id-error")
72            }
73            Self::UrlParseError(e) => ErrorHandling::convert(TabsApiError::UnexpectedTabsError {
74                reason: e.to_string(),
75            })
76            .report_error("tabs-url-parse-error"),
77            Self::SqlError(e) => ErrorHandling::convert(TabsApiError::SqlError {
78                reason: e.to_string(),
79            })
80            .report_error("tabs-sql-error"),
81            Self::OpenDatabaseError(e) => ErrorHandling::convert(TabsApiError::SqlError {
82                reason: e.to_string(),
83            })
84            .report_error("tabs-open-database-error"),
85            Self::UnexpectedConnectionState => {
86                ErrorHandling::convert(TabsApiError::UnexpectedTabsError {
87                    reason: "Unexpected connection state".to_string(),
88                })
89                .report_error("tabs-unexpected-connection-state")
90            }
91        }
92    }
93}
94
95impl From<anyhow::Error> for TabsApiError {
96    fn from(value: anyhow::Error) -> Self {
97        TabsApiError::UnexpectedTabsError {
98            reason: value.to_string(),
99        }
100    }
101}