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 }