tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

env.rs (4533B)


      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 
      5 use crate::xpcom_utils::get_app_locales;
      6 use cstr::cstr;
      7 use fluent_fallback::env::LocalesProvider;
      8 use l10nregistry::{
      9    env::ErrorReporter,
     10    errors::{L10nRegistryError, L10nRegistrySetupError},
     11 };
     12 use log::warn;
     13 use nserror::{nsresult, NS_ERROR_NOT_AVAILABLE};
     14 use nsstring::{nsCStr, nsCString, nsString};
     15 use std::fmt::{self, Write};
     16 use unic_langid::LanguageIdentifier;
     17 use xpcom::interfaces;
     18 
     19 #[derive(Clone)]
     20 pub struct GeckoEnvironment {
     21    custom_locales: Option<Vec<LanguageIdentifier>>,
     22 }
     23 
     24 impl GeckoEnvironment {
     25    pub fn new(custom_locales: Option<Vec<LanguageIdentifier>>) -> Self {
     26        Self { custom_locales }
     27    }
     28 
     29    pub fn report_l10nregistry_setup_error(error: &L10nRegistrySetupError) {
     30        warn!("L10nRegistry setup error: {}", error);
     31        let result = log_simple_console_error(
     32            &error.to_string(),
     33            false,
     34            true,
     35            None,
     36            (0, 0),
     37            interfaces::nsIScriptError::errorFlag as u32,
     38        );
     39        if let Err(err) = result {
     40            warn!("Error while reporting an error: {}", err);
     41        }
     42    }
     43 }
     44 
     45 impl ErrorReporter for GeckoEnvironment {
     46    fn report_errors(&self, errors: Vec<L10nRegistryError>) {
     47        for error in errors {
     48            warn!("L10nRegistry error: {}", error);
     49            let result = match error {
     50                L10nRegistryError::FluentError {
     51                    resource_id,
     52                    loc,
     53                    error,
     54                } => log_simple_console_error(
     55                    &error.to_string(),
     56                    false,
     57                    true,
     58                    Some(nsCString::from(&resource_id.value)),
     59                    loc.map_or((0, 0), |(l, c)| (l as u32, c as u32)),
     60                    interfaces::nsIScriptError::errorFlag as u32,
     61                ),
     62                L10nRegistryError::MissingResource { .. } => log_simple_console_error(
     63                    &error.to_string(),
     64                    false,
     65                    true,
     66                    None,
     67                    (0, 0),
     68                    interfaces::nsIScriptError::warningFlag as u32,
     69                ),
     70            };
     71            if let Err(err) = result {
     72                warn!("Error while reporting an error: {}", err);
     73            }
     74        }
     75    }
     76 }
     77 
     78 impl LocalesProvider for GeckoEnvironment {
     79    type Iter = std::vec::IntoIter<unic_langid::LanguageIdentifier>;
     80    fn locales(&self) -> Self::Iter {
     81        if let Some(custom_locales) = &self.custom_locales {
     82            custom_locales.clone().into_iter()
     83        } else {
     84            let result = get_app_locales()
     85                .expect("Failed to retrieve app locales")
     86                .into_iter()
     87                .map(|s| LanguageIdentifier::from_bytes(&s).expect("Failed to parse a locale"))
     88                .collect::<Vec<_>>();
     89            result.into_iter()
     90        }
     91    }
     92 }
     93 
     94 fn log_simple_console_error(
     95    error: &impl fmt::Display,
     96    from_private_window: bool,
     97    from_chrome_context: bool,
     98    path: Option<nsCString>,
     99    pos: (u32, u32),
    100    error_flags: u32,
    101 ) -> Result<(), nsresult> {
    102    // Format whatever error argument into a wide string with `Display`.
    103    let mut error_str = nsString::new();
    104    write!(&mut error_str, "{}", error).expect("nsString has an infallible Write impl");
    105 
    106    // Get the relevant services, and create the script error object.
    107    let console_service =
    108        xpcom::get_service::<interfaces::nsIConsoleService>(cstr!("@mozilla.org/consoleservice;1"))
    109            .ok_or(NS_ERROR_NOT_AVAILABLE)?;
    110    let script_error =
    111        xpcom::create_instance::<interfaces::nsIScriptError>(cstr!("@mozilla.org/scripterror;1"))
    112            .ok_or(NS_ERROR_NOT_AVAILABLE)?;
    113    let category = nsCStr::from("l10n");
    114    unsafe {
    115        script_error
    116            .Init(
    117                &*error_str,
    118                &*path.unwrap_or_else(nsCString::new), /* aSourceName */
    119                pos.0,                                 /* aLineNumber */
    120                pos.1,                                 /* aColNumber */
    121                error_flags,
    122                &*category,
    123                from_private_window,
    124                from_chrome_context,
    125            )
    126            .to_result()?;
    127 
    128        console_service.LogMessage(&**script_error).to_result()?;
    129    }
    130    Ok(())
    131 }