Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  lib.rs   Sprache: unbekannt

 
/* 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 https://mozilla.org/MPL/2.0/. */

//! This provides a XPCOM service to send app services logs to the desktop

#[macro_use]
extern crate cstr;

#[macro_use]
extern crate xpcom;

use golden_gate::log::LogSink;
use nserror::{nsresult, NS_OK};
use nsstring::nsAString;
use once_cell::sync::Lazy;
use std::os::raw::c_char;
use std::{
    collections::HashMap,
    sync::{
        atomic::{AtomicBool, Ordering},
        RwLock,
    },
};
use xpcom::{
    interfaces::{mozIAppServicesLogger, mozIServicesLogSink, nsIObserverService, nsISupports},
    RefPtr,
};

/// A flag that's set after we register our observer to clear the map of loggers
/// on shutdown.
static SHUTDOWN_OBSERVED: AtomicBool = AtomicBool::new(false);

#[xpcom(implement(mozIAppServicesLogger), nonatomic)]
pub struct AppServicesLogger {}

pub static LOGGERS_BY_TARGET: Lazy<RwLock<HashMap<String, LogSink>>> = Lazy::new(|| {
    let h: HashMap<String, LogSink> = HashMap::new();
    let m = RwLock::new(h);
    m
});

impl AppServicesLogger {
    xpcom_method!(register => Register(target: *const nsAString, logger: *const mozIServicesLogSink));
    fn register(&self, target: &nsAString, logger: &mozIServicesLogSink) -> Result<(), nsresult> {
        let log_sink_logger = LogSink::with_logger(Some(logger))?;

        ensure_observing_shutdown();

        LOGGERS_BY_TARGET
            .write()
            .unwrap()
            .insert(target.to_string(), log_sink_logger);
        Ok(())
    }

    pub fn is_app_services_logger_registered(target: String) -> bool {
        match LOGGERS_BY_TARGET.read() {
            Ok(loggers_by_target) => loggers_by_target.contains_key(&target),
            Err(_e) => false,
        }
    }
}

// Import the `NS_IsMainThread` symbol from Gecko...
extern "C" {
    fn NS_IsMainThread() -> bool;
}

/// Registers an observer to clear the loggers map on `xpcom-shutdown`. This
/// function must be called from the main thread, because the observer service
//// is main thread-only.
fn ensure_observing_shutdown() {
    assert!(unsafe { NS_IsMainThread() });
    // If we've already registered our observer, bail. Relaxed ordering is safe
    // here and below, because we've asserted we're only called from the main
    // thread, and only check the flag here.
    if SHUTDOWN_OBSERVED.load(Ordering::Relaxed) {
        return;
    }
    if let Ok(service) = xpcom::components::Observer::service::<nsIObserverService>() {
        let observer = ShutdownObserver::allocate(InitShutdownObserver {});
        let rv = unsafe {
            service.AddObserver(observer.coerce(), cstr!("xpcom-shutdown").as_ptr(), false)
        };
        // If we fail to register the observer now, or fail to get the observer
        // service, the flag will remain `false`, and we'll try again on the
        // next call to `ensure_observing_shutdown`.
        SHUTDOWN_OBSERVED.store(rv.succeeded(), Ordering::Relaxed);
    }
}

#[xpcom(implement(nsIObserver), nonatomic)]
struct ShutdownObserver {}

impl ShutdownObserver {
    xpcom_method!(observe => Observe(_subject: *const nsISupports, topic: *const c_char, _data: *const u16));
    /// Remove our shutdown observer and clear the map.
    fn observe(
        &self,
        _subject: &nsISupports,
        topic: *const c_char,
        _data: *const u16,
    ) -> Result<(), nsresult> {
        LOGGERS_BY_TARGET.write().unwrap().clear();
        if let Ok(service) = xpcom::components::Observer::service::<nsIObserverService>() {
            // Ignore errors, since we're already shutting down.
            let _ = unsafe { service.RemoveObserver(self.coerce(), topic) };
        }
        Ok(())
    }
}

/// The constructor for an `AppServicesLogger` service. This uses C linkage so that it
/// can be called from C++. See `AppServicesLoggerComponents.h` for the C++
/// constructor that's passed to the component manager.
///
/// # Safety
///
/// This function is unsafe because it dereferences `result`.
#[no_mangle]
pub unsafe extern "C" fn NS_NewAppServicesLogger(
    result: *mut *const mozIAppServicesLogger,
) -> nsresult {
    let logger = AppServicesLogger::allocate(InitAppServicesLogger {});
    RefPtr::new(logger.coerce::<mozIAppServicesLogger>()).forget(&mut *result);
    NS_OK
}

[ Dauer der Verarbeitung: 0.26 Sekunden  (vorverarbeitet)  ]

                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge