Source code

Revision control

Copy as Markdown

Other Tools

/* 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 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)),
},
}
}
}