xpcom_utils.rs (3824B)
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 cstr::cstr; 6 use nsstring::{nsACString, nsCString}; 7 use std::marker::PhantomData; 8 use thin_vec::ThinVec; 9 use xpcom::{ 10 get_service, getter_addrefs, 11 interfaces::{ 12 mozILocaleService, nsICategoryEntry, nsICategoryManager, nsISimpleEnumerator, nsIXULRuntime, 13 }, 14 RefPtr, XpCom, 15 }; 16 17 pub struct IterSimpleEnumerator<T> { 18 enumerator: RefPtr<nsISimpleEnumerator>, 19 phantom: PhantomData<T>, 20 } 21 22 impl<T: XpCom> IterSimpleEnumerator<T> { 23 /// Convert a `nsISimpleEnumerator` into a rust `Iterator` type. 24 pub fn new(enumerator: RefPtr<nsISimpleEnumerator>) -> Self { 25 IterSimpleEnumerator { 26 enumerator, 27 phantom: PhantomData, 28 } 29 } 30 } 31 32 impl<T: XpCom + 'static> Iterator for IterSimpleEnumerator<T> { 33 type Item = RefPtr<T>; 34 35 fn next(&mut self) -> Option<Self::Item> { 36 let mut more = false; 37 unsafe { 38 self.enumerator 39 .HasMoreElements(&mut more) 40 .to_result() 41 .ok()? 42 } 43 if !more { 44 return None; 45 } 46 47 let element = getter_addrefs(|p| unsafe { self.enumerator.GetNext(p) }).ok()?; 48 element.query_interface::<T>() 49 } 50 } 51 52 fn process_type() -> u32 { 53 if let Ok(appinfo) = xpcom::components::XULRuntime::service::<nsIXULRuntime>() { 54 let mut process_type = nsIXULRuntime::PROCESS_TYPE_DEFAULT; 55 if unsafe { appinfo.GetProcessType(&mut process_type).succeeded() } { 56 return process_type; 57 } 58 } 59 nsIXULRuntime::PROCESS_TYPE_DEFAULT 60 } 61 62 pub fn is_parent_process() -> bool { 63 process_type() == nsIXULRuntime::PROCESS_TYPE_DEFAULT 64 } 65 66 pub fn get_packaged_locales() -> Option<ThinVec<nsCString>> { 67 let locale_service = 68 get_service::<mozILocaleService>(cstr!("@mozilla.org/intl/localeservice;1"))?; 69 let mut locales = ThinVec::new(); 70 unsafe { 71 locale_service 72 .GetPackagedLocales(&mut locales) 73 .to_result() 74 .ok()?; 75 } 76 Some(locales) 77 } 78 79 pub fn get_app_locales() -> Option<ThinVec<nsCString>> { 80 let locale_service = 81 get_service::<mozILocaleService>(cstr!("@mozilla.org/intl/localeservice;1"))?; 82 let mut locales = ThinVec::new(); 83 unsafe { 84 locale_service 85 .GetAppLocalesAsBCP47(&mut locales) 86 .to_result() 87 .ok()?; 88 } 89 Some(locales) 90 } 91 92 pub fn set_available_locales(locales: &ThinVec<nsCString>) { 93 let locale_service = 94 get_service::<mozILocaleService>(cstr!("@mozilla.org/intl/localeservice;1")) 95 .expect("Failed to get a service."); 96 unsafe { 97 locale_service 98 .SetAvailableLocales(locales) 99 .to_result() 100 .expect("Failed to set locales."); 101 } 102 } 103 104 pub struct CategoryEntry { 105 pub entry: nsCString, 106 pub value: nsCString, 107 } 108 109 pub fn get_category_entries(category: &nsACString) -> Option<Vec<CategoryEntry>> { 110 let category_manager = 111 get_service::<nsICategoryManager>(cstr!("@mozilla.org/categorymanager;1"))?; 112 113 let enumerator = 114 getter_addrefs(|p| unsafe { category_manager.EnumerateCategory(category, p) }).ok()?; 115 116 Some( 117 IterSimpleEnumerator::<nsICategoryEntry>::new(enumerator) 118 .map(|ientry| { 119 let mut entry = nsCString::new(); 120 let mut value = nsCString::new(); 121 unsafe { 122 let _ = ientry.GetEntry(&mut *entry); 123 let _ = ientry.GetValue(&mut *value); 124 } 125 CategoryEntry { entry, value } 126 }) 127 .collect(), 128 ) 129 }