diff options
Diffstat (limited to 'toolkit/components/bitsdownload/src/bits_interface/error.rs')
-rw-r--r-- | toolkit/components/bitsdownload/src/bits_interface/error.rs | 686 |
1 files changed, 686 insertions, 0 deletions
diff --git a/toolkit/components/bitsdownload/src/bits_interface/error.rs b/toolkit/components/bitsdownload/src/bits_interface/error.rs new file mode 100644 index 0000000000..c046ae5e70 --- /dev/null +++ b/toolkit/components/bitsdownload/src/bits_interface/error.rs @@ -0,0 +1,686 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +use super::action::Action; +use bits_client::{ + bits_protocol::{ + CancelJobFailure, CompleteJobFailure, HResultMessage, MonitorJobFailure, ResumeJobFailure, + SetJobPriorityFailure, SetNoProgressTimeoutFailure, SetUpdateIntervalFailure, + StartJobFailure, SuspendJobFailure, + }, + PipeError, +}; +use comedy::error::HResult as ComedyError; +use nserror::{nsresult, NS_ERROR_FAILURE}; +use nsstring::nsCString; +use std::convert::From; +use xpcom::interfaces::nsIBits; + +#[derive(Debug, PartialEq, Clone, Copy)] +pub enum ErrorType { + NullArgument, + InvalidArgument, + NotInitialized, + NoUtf8Conversion, + InvalidGuid, + PipeNotConnected, + PipeTimeout, + PipeBadWriteCount, + PipeApiError, + FailedToCreateBitsJob, + FailedToAddFileToJob, + FailedToApplyBitsJobSettings, + FailedToResumeBitsJob, + OtherBitsError, + OtherBitsClientError, + BitsJobNotFound, + FailedToGetBitsJob, + FailedToSuspendBitsJob, + FailedToCompleteBitsJob, + PartiallyCompletedBitsJob, + FailedToCancelBitsJob, + MissingResultData, + MissingCallback, + CallbackOnWrongThread, + MissingBitsService, + BitsServiceOnWrongThread, + MissingBitsRequest, + BitsRequestOnWrongThread, + MissingObserver, + ObserverOnWrongThread, + MissingContext, + ContextOnWrongThread, + FailedToStartThread, + FailedToConstructTaskRunnable, + FailedToDispatchRunnable, + TransferAlreadyComplete, + OperationAlreadyInProgress, + MissingBitsClient, + FailedToGetJobStatus, + BitsStateError, + BitsStateTransientError, + BitsStateCancelled, + BitsStateUnexpected, + FailedToConnectToBcm, +} + +impl ErrorType { + pub fn bits_code(&self) -> i32 { + match self { + ErrorType::NullArgument => nsIBits::ERROR_TYPE_NULL_ARGUMENT, + ErrorType::InvalidArgument => nsIBits::ERROR_TYPE_INVALID_ARGUMENT, + ErrorType::NotInitialized => nsIBits::ERROR_TYPE_NOT_INITIALIZED, + ErrorType::NoUtf8Conversion => nsIBits::ERROR_TYPE_NO_UTF8_CONVERSION, + ErrorType::InvalidGuid => nsIBits::ERROR_TYPE_INVALID_GUID, + ErrorType::PipeNotConnected => nsIBits::ERROR_TYPE_PIPE_NOT_CONNECTED, + ErrorType::PipeTimeout => nsIBits::ERROR_TYPE_PIPE_TIMEOUT, + ErrorType::PipeBadWriteCount => nsIBits::ERROR_TYPE_PIPE_BAD_WRITE_COUNT, + ErrorType::PipeApiError => nsIBits::ERROR_TYPE_PIPE_API_ERROR, + ErrorType::FailedToCreateBitsJob => nsIBits::ERROR_TYPE_FAILED_TO_CREATE_BITS_JOB, + ErrorType::FailedToAddFileToJob => nsIBits::ERROR_TYPE_FAILED_TO_ADD_FILE_TO_JOB, + ErrorType::FailedToApplyBitsJobSettings => { + nsIBits::ERROR_TYPE_FAILED_TO_APPLY_BITS_JOB_SETTINGS + } + ErrorType::FailedToResumeBitsJob => nsIBits::ERROR_TYPE_FAILED_TO_RESUME_BITS_JOB, + ErrorType::OtherBitsError => nsIBits::ERROR_TYPE_OTHER_BITS_ERROR, + ErrorType::OtherBitsClientError => nsIBits::ERROR_TYPE_OTHER_BITS_CLIENT_ERROR, + ErrorType::BitsJobNotFound => nsIBits::ERROR_TYPE_BITS_JOB_NOT_FOUND, + ErrorType::FailedToGetBitsJob => nsIBits::ERROR_TYPE_FAILED_TO_GET_BITS_JOB, + ErrorType::FailedToSuspendBitsJob => nsIBits::ERROR_TYPE_FAILED_TO_SUSPEND_BITS_JOB, + ErrorType::FailedToCompleteBitsJob => nsIBits::ERROR_TYPE_FAILED_TO_COMPLETE_BITS_JOB, + ErrorType::PartiallyCompletedBitsJob => { + nsIBits::ERROR_TYPE_PARTIALLY_COMPLETED_BITS_JOB + } + ErrorType::FailedToCancelBitsJob => nsIBits::ERROR_TYPE_FAILED_TO_CANCEL_BITS_JOB, + ErrorType::MissingResultData => nsIBits::ERROR_TYPE_MISSING_RESULT_DATA, + ErrorType::MissingCallback => nsIBits::ERROR_TYPE_MISSING_CALLBACK, + ErrorType::CallbackOnWrongThread => nsIBits::ERROR_TYPE_CALLBACK_ON_WRONG_THREAD, + ErrorType::MissingBitsService => nsIBits::ERROR_TYPE_MISSING_BITS_SERVICE, + ErrorType::BitsServiceOnWrongThread => nsIBits::ERROR_TYPE_BITS_SERVICE_ON_WRONG_THREAD, + ErrorType::MissingBitsRequest => nsIBits::ERROR_TYPE_MISSING_BITS_REQUEST, + ErrorType::BitsRequestOnWrongThread => nsIBits::ERROR_TYPE_BITS_REQUEST_ON_WRONG_THREAD, + ErrorType::MissingObserver => nsIBits::ERROR_TYPE_MISSING_OBSERVER, + ErrorType::ObserverOnWrongThread => nsIBits::ERROR_TYPE_OBSERVER_ON_WRONG_THREAD, + ErrorType::MissingContext => nsIBits::ERROR_TYPE_MISSING_CONTEXT, + ErrorType::ContextOnWrongThread => nsIBits::ERROR_TYPE_CONTEXT_ON_WRONG_THREAD, + ErrorType::FailedToStartThread => nsIBits::ERROR_TYPE_FAILED_TO_START_THREAD, + ErrorType::FailedToConstructTaskRunnable => { + nsIBits::ERROR_TYPE_FAILED_TO_CONSTRUCT_TASK_RUNNABLE + } + ErrorType::FailedToDispatchRunnable => nsIBits::ERROR_TYPE_FAILED_TO_DISPATCH_RUNNABLE, + ErrorType::TransferAlreadyComplete => nsIBits::ERROR_TYPE_TRANSFER_ALREADY_COMPLETE, + ErrorType::OperationAlreadyInProgress => { + nsIBits::ERROR_TYPE_OPERATION_ALREADY_IN_PROGRESS + } + ErrorType::MissingBitsClient => nsIBits::ERROR_TYPE_MISSING_BITS_CLIENT, + ErrorType::FailedToGetJobStatus => nsIBits::ERROR_TYPE_FAILED_TO_GET_JOB_STATUS, + ErrorType::BitsStateError => nsIBits::ERROR_TYPE_BITS_STATE_ERROR, + ErrorType::BitsStateTransientError => nsIBits::ERROR_TYPE_BITS_STATE_TRANSIENT_ERROR, + ErrorType::BitsStateCancelled => nsIBits::ERROR_TYPE_BITS_STATE_CANCELLED, + ErrorType::BitsStateUnexpected => nsIBits::ERROR_TYPE_BITS_STATE_UNEXPECTED, + ErrorType::FailedToConnectToBcm => nsIBits::ERROR_TYPE_FAILED_TO_CONNECT_TO_BCM, + } + } +} + +impl From<&PipeError> for ErrorType { + fn from(error: &PipeError) -> Self { + match error { + PipeError::NotConnected => ErrorType::PipeNotConnected, + PipeError::Timeout => ErrorType::PipeTimeout, + PipeError::WriteCount(_, _) => ErrorType::PipeBadWriteCount, + PipeError::Api(_) => ErrorType::PipeApiError, + } + } +} + +#[derive(Debug, PartialEq, Clone, Copy)] +pub enum ErrorStage { + Pretask, + CommandThread, + AgentCommunication, + BitsClient, + MainThread, +} + +impl ErrorStage { + pub fn bits_code(&self) -> i32 { + let val = match self { + ErrorStage::Pretask => nsIBits::ERROR_STAGE_PRETASK, + ErrorStage::CommandThread => nsIBits::ERROR_STAGE_COMMAND_THREAD, + ErrorStage::AgentCommunication => nsIBits::ERROR_STAGE_AGENT_COMMUNICATION, + ErrorStage::BitsClient => nsIBits::ERROR_STAGE_BITS_CLIENT, + ErrorStage::MainThread => nsIBits::ERROR_STAGE_MAIN_THREAD, + }; + val as i32 + } +} + +#[derive(Debug, Clone)] +pub enum ErrorCode { + None, + Hresult(i32), + Nsresult(nsresult), + Message(nsCString), +} + +impl From<ComedyError> for ErrorCode { + fn from(error: ComedyError) -> Self { + ErrorCode::Hresult(error.code()) + } +} + +impl From<HResultMessage> for ErrorCode { + fn from(result: HResultMessage) -> Self { + ErrorCode::Hresult(result.hr) + } +} + +#[derive(Debug, Clone)] +pub struct BitsTaskError { + pub error_type: ErrorType, + pub error_action: Action, + pub error_stage: ErrorStage, + pub error_code: ErrorCode, +} + +impl BitsTaskError { + pub fn new( + error_type: ErrorType, + error_action: Action, + error_stage: ErrorStage, + ) -> BitsTaskError { + BitsTaskError { + error_type, + error_action, + error_stage, + error_code: ErrorCode::None, + } + } + + pub fn missing_result(error_action: Action) -> BitsTaskError { + BitsTaskError { + error_type: ErrorType::MissingResultData, + error_action, + error_stage: ErrorStage::MainThread, + error_code: ErrorCode::None, + } + } + + pub fn from_nsresult( + error_type: ErrorType, + error_action: Action, + error_stage: ErrorStage, + error_code: nsresult, + ) -> BitsTaskError { + BitsTaskError { + error_type, + error_action, + error_stage, + error_code: ErrorCode::Nsresult(error_code), + } + } + + pub fn from_hresult( + error_type: ErrorType, + error_action: Action, + error_stage: ErrorStage, + error_code: i32, + ) -> BitsTaskError { + BitsTaskError { + error_type, + error_action, + error_stage, + error_code: ErrorCode::Hresult(error_code), + } + } + + pub fn from_comedy( + error_type: ErrorType, + error_action: Action, + error_stage: ErrorStage, + comedy_error: ComedyError, + ) -> BitsTaskError { + BitsTaskError { + error_type, + error_action, + error_stage, + error_code: comedy_error.into(), + } + } + + pub fn from_pipe(error_action: Action, pipe_error: PipeError) -> BitsTaskError { + let error_type = (&pipe_error).into(); + match pipe_error { + PipeError::Api(comedy_error) => BitsTaskError { + error_type, + error_action, + error_stage: ErrorStage::AgentCommunication, + error_code: comedy_error.into(), + }, + _ => BitsTaskError { + error_type, + error_action, + error_stage: ErrorStage::AgentCommunication, + error_code: ErrorCode::None, + }, + } + } +} + +impl From<BitsTaskError> for nsresult { + fn from(error: BitsTaskError) -> Self { + if let ErrorCode::Nsresult(rv) = error.error_code { + rv + } else { + NS_ERROR_FAILURE + } + } +} + +impl From<StartJobFailure> for BitsTaskError { + fn from(error: StartJobFailure) -> Self { + let error_stage = ErrorStage::BitsClient; + let error_action = Action::StartDownload; + match error { + StartJobFailure::ArgumentValidation(message) => BitsTaskError { + error_type: ErrorType::InvalidArgument, + error_action, + error_stage, + error_code: ErrorCode::Message(nsCString::from(message)), + }, + StartJobFailure::Create(error_code) => BitsTaskError { + error_type: ErrorType::FailedToCreateBitsJob, + error_action, + error_stage, + error_code: error_code.into(), + }, + StartJobFailure::AddFile(error_code) => BitsTaskError { + error_type: ErrorType::FailedToAddFileToJob, + error_action, + error_stage, + error_code: error_code.into(), + }, + StartJobFailure::ApplySettings(error_code) => BitsTaskError { + error_type: ErrorType::FailedToApplyBitsJobSettings, + error_action, + error_stage, + error_code: error_code.into(), + }, + StartJobFailure::Resume(error_code) => BitsTaskError { + error_type: ErrorType::FailedToResumeBitsJob, + error_action, + error_stage, + error_code: error_code.into(), + }, + StartJobFailure::ConnectBcm(error_code) => BitsTaskError { + error_type: ErrorType::FailedToConnectToBcm, + error_action, + error_stage, + error_code: error_code.into(), + }, + StartJobFailure::OtherBITS(error_code) => BitsTaskError { + error_type: ErrorType::OtherBitsError, + error_action, + error_stage, + error_code: error_code.into(), + }, + StartJobFailure::Other(message) => BitsTaskError { + error_type: ErrorType::OtherBitsClientError, + error_action, + error_stage, + error_code: ErrorCode::Message(nsCString::from(message)), + }, + } + } +} + +impl From<MonitorJobFailure> for BitsTaskError { + fn from(error: MonitorJobFailure) -> Self { + let error_stage = ErrorStage::BitsClient; + let error_action = Action::MonitorDownload; + match error { + MonitorJobFailure::ArgumentValidation(message) => BitsTaskError { + error_type: ErrorType::InvalidArgument, + error_action, + error_stage, + error_code: ErrorCode::Message(nsCString::from(message)), + }, + MonitorJobFailure::NotFound => BitsTaskError { + error_type: ErrorType::BitsJobNotFound, + error_action, + error_stage, + error_code: ErrorCode::None, + }, + MonitorJobFailure::GetJob(error_code) => BitsTaskError { + error_type: ErrorType::FailedToGetBitsJob, + error_action, + error_stage, + error_code: error_code.into(), + }, + MonitorJobFailure::ConnectBcm(error_code) => BitsTaskError { + error_type: ErrorType::FailedToConnectToBcm, + error_action, + error_stage, + error_code: error_code.into(), + }, + MonitorJobFailure::OtherBITS(error_code) => BitsTaskError { + error_type: ErrorType::OtherBitsError, + error_action, + error_stage, + error_code: error_code.into(), + }, + MonitorJobFailure::Other(message) => BitsTaskError { + error_type: ErrorType::OtherBitsClientError, + error_action, + error_stage, + error_code: ErrorCode::Message(nsCString::from(message)), + }, + } + } +} + +impl From<SuspendJobFailure> for BitsTaskError { + fn from(error: SuspendJobFailure) -> Self { + let error_stage = ErrorStage::BitsClient; + let error_action = Action::Suspend; + match error { + SuspendJobFailure::NotFound => BitsTaskError { + error_type: ErrorType::BitsJobNotFound, + error_action, + error_stage, + error_code: ErrorCode::None, + }, + SuspendJobFailure::GetJob(error_code) => BitsTaskError { + error_type: ErrorType::FailedToGetBitsJob, + error_action, + error_stage, + error_code: error_code.into(), + }, + SuspendJobFailure::SuspendJob(error_code) => BitsTaskError { + error_type: ErrorType::FailedToSuspendBitsJob, + error_action, + error_stage, + error_code: error_code.into(), + }, + SuspendJobFailure::ConnectBcm(error_code) => BitsTaskError { + error_type: ErrorType::FailedToConnectToBcm, + error_action, + error_stage, + error_code: error_code.into(), + }, + SuspendJobFailure::OtherBITS(error_code) => BitsTaskError { + error_type: ErrorType::OtherBitsError, + error_action, + error_stage, + error_code: error_code.into(), + }, + SuspendJobFailure::Other(message) => BitsTaskError { + error_type: ErrorType::OtherBitsClientError, + error_action, + error_stage, + error_code: ErrorCode::Message(nsCString::from(message)), + }, + } + } +} + +impl From<ResumeJobFailure> for BitsTaskError { + fn from(error: ResumeJobFailure) -> Self { + let error_stage = ErrorStage::BitsClient; + let error_action = Action::Resume; + match error { + ResumeJobFailure::NotFound => BitsTaskError { + error_type: ErrorType::BitsJobNotFound, + error_action, + error_stage, + error_code: ErrorCode::None, + }, + ResumeJobFailure::GetJob(error_code) => BitsTaskError { + error_type: ErrorType::FailedToGetBitsJob, + error_action, + error_stage, + error_code: error_code.into(), + }, + ResumeJobFailure::ResumeJob(error_code) => BitsTaskError { + error_type: ErrorType::FailedToResumeBitsJob, + error_action, + error_stage, + error_code: error_code.into(), + }, + ResumeJobFailure::ConnectBcm(error_code) => BitsTaskError { + error_type: ErrorType::FailedToConnectToBcm, + error_action, + error_stage, + error_code: error_code.into(), + }, + ResumeJobFailure::OtherBITS(error_code) => BitsTaskError { + error_type: ErrorType::OtherBitsError, + error_action, + error_stage, + error_code: error_code.into(), + }, + ResumeJobFailure::Other(message) => BitsTaskError { + error_type: ErrorType::OtherBitsClientError, + error_action, + error_stage, + error_code: ErrorCode::Message(nsCString::from(message)), + }, + } + } +} + +impl From<SetJobPriorityFailure> for BitsTaskError { + fn from(error: SetJobPriorityFailure) -> Self { + let error_stage = ErrorStage::BitsClient; + let error_action = Action::SetPriority; + match error { + SetJobPriorityFailure::NotFound => BitsTaskError { + error_type: ErrorType::BitsJobNotFound, + error_action, + error_stage, + error_code: ErrorCode::None, + }, + SetJobPriorityFailure::GetJob(error_code) => BitsTaskError { + error_type: ErrorType::FailedToGetBitsJob, + error_action, + error_stage, + error_code: error_code.into(), + }, + SetJobPriorityFailure::ApplySettings(error_code) => BitsTaskError { + error_type: ErrorType::FailedToApplyBitsJobSettings, + error_action, + error_stage, + error_code: error_code.into(), + }, + SetJobPriorityFailure::ConnectBcm(error_code) => BitsTaskError { + error_type: ErrorType::FailedToConnectToBcm, + error_action, + error_stage, + error_code: error_code.into(), + }, + SetJobPriorityFailure::OtherBITS(error_code) => BitsTaskError { + error_type: ErrorType::OtherBitsError, + error_action, + error_stage, + error_code: error_code.into(), + }, + SetJobPriorityFailure::Other(message) => BitsTaskError { + error_type: ErrorType::OtherBitsClientError, + error_action, + error_stage, + error_code: ErrorCode::Message(nsCString::from(message)), + }, + } + } +} + +impl From<SetNoProgressTimeoutFailure> for BitsTaskError { + fn from(error: SetNoProgressTimeoutFailure) -> Self { + use self::SetNoProgressTimeoutFailure::*; + + let error_stage = ErrorStage::BitsClient; + let error_action = Action::SetNoProgressTimeout; + match error { + NotFound => BitsTaskError { + error_type: ErrorType::BitsJobNotFound, + error_action, + error_stage, + error_code: ErrorCode::None, + }, + GetJob(error_code) => BitsTaskError { + error_type: ErrorType::FailedToGetBitsJob, + error_action, + error_stage, + error_code: error_code.into(), + }, + ApplySettings(error_code) => BitsTaskError { + error_type: ErrorType::FailedToApplyBitsJobSettings, + error_action, + error_stage, + error_code: error_code.into(), + }, + ConnectBcm(error_code) => BitsTaskError { + error_type: ErrorType::FailedToConnectToBcm, + error_action, + error_stage, + error_code: error_code.into(), + }, + OtherBITS(error_code) => BitsTaskError { + error_type: ErrorType::OtherBitsError, + error_action, + error_stage, + error_code: error_code.into(), + }, + Other(message) => BitsTaskError { + error_type: ErrorType::OtherBitsClientError, + error_action, + error_stage, + error_code: ErrorCode::Message(nsCString::from(message)), + }, + } + } +} + +impl From<SetUpdateIntervalFailure> for BitsTaskError { + fn from(error: SetUpdateIntervalFailure) -> Self { + let error_stage = ErrorStage::BitsClient; + let error_action = Action::SetMonitorInterval; + match error { + SetUpdateIntervalFailure::ArgumentValidation(message) => BitsTaskError { + error_type: ErrorType::InvalidArgument, + error_action, + error_stage, + error_code: ErrorCode::Message(nsCString::from(message)), + }, + SetUpdateIntervalFailure::NotFound => BitsTaskError { + error_type: ErrorType::BitsJobNotFound, + error_action, + error_stage, + error_code: ErrorCode::None, + }, + SetUpdateIntervalFailure::Other(message) => BitsTaskError { + error_type: ErrorType::OtherBitsClientError, + error_action, + error_stage, + error_code: ErrorCode::Message(nsCString::from(message)), + }, + } + } +} + +impl From<CompleteJobFailure> for BitsTaskError { + fn from(error: CompleteJobFailure) -> Self { + let error_stage = ErrorStage::BitsClient; + let error_action = Action::Complete; + match error { + CompleteJobFailure::NotFound => BitsTaskError { + error_type: ErrorType::BitsJobNotFound, + error_action, + error_stage, + error_code: ErrorCode::None, + }, + CompleteJobFailure::GetJob(error_code) => BitsTaskError { + error_type: ErrorType::FailedToGetBitsJob, + error_action, + error_stage, + error_code: error_code.into(), + }, + CompleteJobFailure::CompleteJob(error_code) => BitsTaskError { + error_type: ErrorType::FailedToCompleteBitsJob, + error_action, + error_stage, + error_code: error_code.into(), + }, + CompleteJobFailure::PartialComplete => BitsTaskError { + error_type: ErrorType::PartiallyCompletedBitsJob, + error_action, + error_stage, + error_code: ErrorCode::None, + }, + CompleteJobFailure::ConnectBcm(error_code) => BitsTaskError { + error_type: ErrorType::FailedToConnectToBcm, + error_action, + error_stage, + error_code: error_code.into(), + }, + CompleteJobFailure::OtherBITS(error_code) => BitsTaskError { + error_type: ErrorType::OtherBitsError, + error_action, + error_stage, + error_code: error_code.into(), + }, + CompleteJobFailure::Other(message) => BitsTaskError { + error_type: ErrorType::OtherBitsClientError, + error_action, + error_stage, + error_code: ErrorCode::Message(nsCString::from(message)), + }, + } + } +} + +impl From<CancelJobFailure> for BitsTaskError { + fn from(error: CancelJobFailure) -> Self { + let error_stage = ErrorStage::BitsClient; + let error_action = Action::Cancel; + match error { + CancelJobFailure::NotFound => BitsTaskError { + error_type: ErrorType::BitsJobNotFound, + error_action, + error_stage, + error_code: ErrorCode::None, + }, + CancelJobFailure::GetJob(error_code) => BitsTaskError { + error_type: ErrorType::FailedToGetBitsJob, + error_action, + error_stage, + error_code: error_code.into(), + }, + CancelJobFailure::CancelJob(error_code) => BitsTaskError { + error_type: ErrorType::FailedToCancelBitsJob, + error_action, + error_stage, + error_code: error_code.into(), + }, + CancelJobFailure::ConnectBcm(error_code) => BitsTaskError { + error_type: ErrorType::FailedToConnectToBcm, + error_action, + error_stage, + error_code: error_code.into(), + }, + CancelJobFailure::OtherBITS(error_code) => BitsTaskError { + error_type: ErrorType::OtherBitsError, + error_action, + error_stage, + error_code: error_code.into(), + }, + CancelJobFailure::Other(message) => BitsTaskError { + error_type: ErrorType::OtherBitsClientError, + error_action, + error_stage, + error_code: ErrorCode::Message(nsCString::from(message)), + }, + } + } +} |