Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/toolkit/components/glean/src/init/   (Firefox Browser Version 153.0.1©)  Datei vom 27.6.2026 mit Größe 4 kB image not shown  

Quelle  user_activity.rs

  Sprache: Rust
 

// 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/.

use std::convert::TryInto;
use std::ffi::CStr;
use std::os::raw::c_char;
use std::sync::{
    atomic::{AtomicBool, Ordering},
    RwLock,
};
use std::time::{Duration, Instant};

use nserror::{nsresult, NS_ERROR_FAILURE, NS_OK};
use xpcom::{
    interfaces::{nsIObserverService, nsISupports},
    RefPtr,
};

// Partially cargo-culted from UploadPrefObserver.
#[xpcom(implement(nsIObserver), atomic)]
pub(cratestruct UserActivityObserver {
    last_edge: RwLock<Instant>,
    was_active: AtomicBool,
}

/// Listens to Firefox Desktop's `user-interaction-(in)active` topics,
/// debouncing them before calling into the Glean SDK Client Activity API.
/// See
/// [the docs](https://firefox-source-docs.mozilla.org/toolkit/components/glean/dev/builtin_pings.html)
/// for more info.
#[allow(non_snake_case)]
impl UserActivityObserver {
    pub(cratefn begin_observing() -> Result<(), nsresult> {
        // First and foremost, even if we can't get the ObserverService,
        // init always means client activity.
        glean::handle_client_active();

        // SAFETY: Everything here is self-contained.
        //
        // * We allocate the activity observer, created by the xpcom macro
        // * We create cstr from a static string.
        // * We control all input to `AddObserver`
        unsafe {
            let activity_obs = Self::allocate(InitUserActivityObserver {
                last_edge: RwLock::new(Instant::now()),
                was_active: AtomicBool::new(false),
            });
            let obs_service: RefPtr<nsIObserverService> =
                xpcom::components::Observer::service().map_err(|_| NS_ERROR_FAILURE)?;
            let rv = obs_service.AddObserver(
                activity_obs.coerce(),
                cstr!("user-interaction-active").as_ptr(),
                false,
            );
            if !rv.succeeded() {
                return Err(rv);
            }
            let rv = obs_service.AddObserver(
                activity_obs.coerce(),
                cstr!("user-interaction-inactive").as_ptr(),
                false,
            );
            if !rv.succeeded() {
                return Err(rv);
            }
        }
        Ok(())
    }

    unsafe fn Observe(
        &self,
        _subject: *const nsISupports,
        topic: *const c_char,
        _data: *const u16,
    ) -> nserror::nsresult {
        match CStr::from_ptr(topic).to_str() {
            Ok("user-interaction-active") => self.handle_active(),
            Ok("user-interaction-inactive") => self.handle_inactive(),
            _ => NS_OK,
        }
    }

    fn handle_active(&self) -> nserror::nsresult {
        let was_active = self.was_active.swap(true, Ordering::SeqCst);
        if !was_active {
            let inactivity = self
                .last_edge
                .read()
                .expect("Edge lock poisoned.")
                .elapsed();
            // We only care after a certain period of inactivity (default 20min).
            let limit = static_prefs::pref!("telemetry.fog.test.inactivity_limit");
            if limit >= 0 && inactivity >= Duration::from_secs(limit.try_into().unwrap_or(0)) {
                log::info!(
                    "User triggers core activity after {}s!",
                    inactivity.as_secs()
                );
                glean::handle_client_active();
            }
            let mut edge = self.last_edge.write().expect("Edge lock poisoned.");
            *edge = Instant::now();
        }
        NS_OK
    }

    fn handle_inactive(&self) -> nserror::nsresult {
        let was_active = self.was_active.swap(false, Ordering::SeqCst);
        // This is actually always so. Inactivity is only notified once.
        if was_active {
            let activity = self
                .last_edge
                .read()
                .expect("Edge lock poisoned.")
                .elapsed();
            // We only care after a certain period of activity (default 2min).
            let limit = static_prefs::pref!("telemetry.fog.test.activity_limit");
            if limit >= 0 && activity >= Duration::from_secs(limit.try_into().unwrap_or(0)) {
                log::info!(
                    "User triggers core inactivity after {}s!",
                    activity.as_secs()
                );
                glean::handle_client_inactive();
            }
            let mut edge = self.last_edge.write().expect("Edge lock poisoned.");
            *edge = Instant::now();
        }
        NS_OK
    }
}

Messung V0.5 in Prozent
C=90 H=98 G=94

¤ Dauer der Verarbeitung: 0.3 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.