Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/browser/components/urlbar/tests/unit/   (Firefox Browser Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 16 kB image not shown  

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


//! Argument string parsing and matching functions for Firefox.
//!
//! Which arguments Firefox accepts and in what style depends on the platform.
//! On Windows only, arguments can be prefixed with `/` (slash), such as
//! `/screenshot`.  Elsewhere, including Windows, arguments may be prefixed
//! with both single (`-screenshot`) and double (`--screenshot`) dashes.
//!
//! An argument's name is determined by a space or an assignment operator (`=`)
//! so that for the string `-foo=bar`, `foo` is considered the argument's
//! basename.

use crate::runner::platform;
use std::ffi::{OsStr, OsString};
use std::fmt;

/// Parse an argument string into a name and value
///
/// Given an argument like `"--arg=value"` this will split it into
/// `(Some("arg"), Some("value")). For a case like `"--arg"` it will
/// return `(Some("arg"), None)` and where the input doesn't look like
/// an argument e.g. `"value"` it will return `(None, Some("value"))`
fn parse_arg_name_value<T>(arg: T) -> (Option<String>, Option<String>)
where
    T: AsRef<OsStr>,
{
    let arg_os_str: &OsStr = arg.as_ref();
    let arg_str = arg_os_str.to_string_lossy();

    let mut name_start = 0;
    let mut name_end = 0;

    // Look for an argument name at the start of the
    // string
    for (i, c) in arg_str.chars().enumerate() {
        if i == 0 {
            if !platform::arg_prefix_char(c) {
                break;
            }
        } else if i == 1 {
            if name_end_char(c) {
                break;
            } else if c != '-' {
                name_start = i;
                name_end = name_start + 1;
            } else {
                name_start = i + 1;
                name_end = name_start;
            }
        } else {
            name_end += 1;
            if name_end_char(c) {
                name_end -= 1;
                break;
            }
        }
    }

    let name = if name_start > 0 && name_end > name_start {
        Some(arg_str[name_start..name_end].into())
    } else {
        None
    };

    // If there are characters in the string after the argument, read
    // them as the value, excluding the seperator (e.g. "=") if
    // present.
    let mut value_start = name_end;
    let value_end = arg_str.len();
    let value = if value_start < value_end {
        if let Some(c) = arg_str[value_start..value_end].chars().next() {
            if name_end_char(c) {
                value_start += 1;
            }
        }
        Some(arg_str[value_start..value_end].into())
    } else {
        None
    };
    (name, value)
}

fn name_end_char(c: char) -> bool {
    c == ' ' || c == '='
}

/// Represents a Firefox command-line argument.
#[derive(Debug, PartialEq)]
pub enum Arg {
    /// `-foreground` ensures application window gets focus, which is not the
    /// default on macOS. As such Firefox only supports it on MacOS.
    Foreground,

    /// --marionette enables Marionette in the application which is used
    /// by WebDriver HTTP.
    Marionette,

    /// `-no-remote` prevents remote commands to this instance of Firefox, and
    /// ensure we always start a new instance.
    NoRemote,

    /// `-P NAME` starts Firefox with a profile with a given name.
    NamedProfile,

    /// `-profile PATH` starts Firefox with the profile at the specified path.
    Profile,

    /// `-ProfileManager` starts Firefox with the profile chooser dialogue.
    ProfileManager,

    /// All other arguments.
    Other(String),

    /// --remote-allow-hosts contains comma-separated values of the Host header
    /// to allow for incoming WebSocket requests of the Remote Agent.
    RemoteAllowHosts,

    /// --remote-allow-origins contains comma-separated values of the Origin header
    /// to allow for incoming WebSocket requests of the Remote Agent.
    RemoteAllowOrigins,

    /// --remote-debugging-port enables the Remote Agent in the application
    /// which is used for the WebDriver BiDi and CDP remote debugging protocols.
    RemoteDebuggingPort,

    /// Not an argument.
    None,
}

impl Arg {
    pub fn new(name: &str) -> Arg {
        match name {
            "foreground" => Arg::Foreground,
            "marionette" => Arg::Marionette,
            "no-remote" => Arg::NoRemote,
            "profile" => Arg::Profile,
            "P" => Arg::NamedProfile,
            "ProfileManager" => Arg::ProfileManager,
            "remote-allow-hosts" => Arg::RemoteAllowHosts,
            "remote-allow-origins" => Arg::RemoteAllowOrigins,
            "remote-debugging-port" => Arg::RemoteDebuggingPort,
            _ => Arg::Other(name.into()),
        }
    }
}

impl<'a> From<&'a OsString> for Arg {
    fn from(arg_str: &OsString) -> Arg {
        if let (Some(name), _) = parse_arg_name_value(arg_str) {
            Arg::new(&name)
        } else {
            Arg::None
        }
    }
}

impl fmt::Display for Arg {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str(&match self {
            Arg::Foreground => "--foreground".to_string(),
            Arg::Marionette => "--marionette".to_string(),
            Arg::NamedProfile => "-P".to_string(),
            Arg::None => "".to_string(),
            Arg::NoRemote => "--no-remote".to_string(),
            Arg::Other(x) => format!("--{}", x),
            Arg::Profile => "--profile".to_string(),
            Arg::ProfileManager => "--ProfileManager".to_string(),
            Arg::RemoteAllowHosts => "--remote-allow-hosts".to_string(),
            Arg::RemoteAllowOrigins => "--remote-allow-origins".to_string(),
            Arg::RemoteDebuggingPort => "--remote-debugging-port".to_string(),
        })
    }
}

/// Parse an iterator over arguments into an vector of (name, value)
/// tuples
///
/// Each entry in the input argument will produce a single item in the
/// output. Because we don't know anything about the specific
/// arguments, something that doesn't parse as a named argument may
/// either be the value of a previous named argument, or may be a
/// positional argument.
pub fn parse_args<'a>(
    args: impl Iterator<Item = &'a OsString>,
) -> Vec<(Option<Arg>, Option<String>)> {
    args.map(parse_arg_name_value)
        .map(|(name, value)| {
            if let Some(arg_name) = name {
                (Some(Arg::new(&arg_name)), value)
            } else {
                (None, value)
            }
        })
        .collect()
}

/// Given an iterator over all arguments, get the value of an argument
///
/// This assumes that the argument takes a single value and that is
/// either provided as a single argument entry
/// (e.g. `["--name=value"]`) or as the following argument
/// (e.g. `["--name", "value"])
pub fn get_arg_value<'a>(
    mut parsed_args: impl Iterator<Item = &'a (Option<Arg>, Option<String>)>,
    arg: Arg,
) -> Option<String> {
    let mut found_value = None;
    for (arg_name, arg_value) in &mut parsed_args {
        if let (Some(name), value) = (arg_name, arg_value) {
            if *name == arg {
                found_value = value.clone();
                break;
            }
        }
    }
    if found_value.is_none() {
        // If there wasn't a value, check if the following argument is a value
        if let Some((None, value)) = parsed_args.next() {
            found_value = value.clone();
        }
    }
    found_value
}

#[cfg(test)]
mod tests {
    use super::{get_arg_value, parse_arg_name_value, parse_args, Arg};
    use std::ffi::OsString;

    fn parse(arg: &str, name: Option<&str>) {
        let (result, _) = parse_arg_name_value(arg);
        assert_eq!(result, name.map(|x| x.to_string()));
    }

    #[test]
    fn test_parse_arg_name_value() {
        parse("-p", Some("p"));
        parse("--p", Some("p"));
        parse("--profile foo", Some("profile"));
        parse("--profile", Some("profile"));
        parse("--", None);
        parse("", None);
        parse("-=", None);
        parse("--=", None);
        parse("-- foo", None);
        parse("foo", None);
        parse("/ foo", None);
        parse("/- foo", None);
        parse("/=foo", None);
        parse("foo", None);
        parse("-profile", Some("profile"));
        parse("-profile=foo", Some("profile"));
        parse("-profile = foo", Some("profile"));
        parse("-profile abc", Some("profile"));
        parse("-profile /foo", Some("profile"));
    }

    #[cfg(target_os = "windows")]
    #[test]
    fn test_parse_arg_name_value_windows() {
        parse("/profile", Some("profile"));
    }

    #[cfg(not(target_os = "windows"))]
    #[test]
    fn test_parse_arg_name_value_non_windows() {
        parse("/profile", None);
    }

    #[test]
    fn test_arg_from_osstring() {
        assert_eq!(Arg::from(&OsString::from("--foreground")), Arg::Foreground);
        assert_eq!(Arg::from(&OsString::from("-foreground")), Arg::Foreground);

        assert_eq!(Arg::from(&OsString::from("--marionette")), Arg::Marionette);
        assert_eq!(Arg::from(&OsString::from("-marionette")), Arg::Marionette);

        assert_eq!(Arg::from(&OsString::from("--no-remote")), Arg::NoRemote);
        assert_eq!(Arg::from(&OsString::from("-no-remote")), Arg::NoRemote);

        assert_eq!(Arg::from(&OsString::from("-- profile")), Arg::None);
        assert_eq!(Arg::from(&OsString::from("profile")), Arg::None);
        assert_eq!(Arg::from(&OsString::from("profile -P")), Arg::None);
        assert_eq!(
            Arg::from(&OsString::from("-profiled")),
            Arg::Other("profiled".into())
        );
        assert_eq!(
            Arg::from(&OsString::from("-PROFILEMANAGER")),
            Arg::Other("PROFILEMANAGER".into())
        );

        assert_eq!(Arg::from(&OsString::from("--profile")), Arg::Profile);
        assert_eq!(Arg::from(&OsString::from("-profile foo")), Arg::Profile);

        assert_eq!(
            Arg::from(&OsString::from("--ProfileManager")),
            Arg::ProfileManager
        );
        assert_eq!(
            Arg::from(&OsString::from("-ProfileManager")),
            Arg::ProfileManager
        );

        // TODO: -Ptest is valid
        //assert_eq!(Arg::from(&OsString::from("-Ptest")), Arg::NamedProfile);
        assert_eq!(Arg::from(&OsString::from("-P")), Arg::NamedProfile);
        assert_eq!(Arg::from(&OsString::from("-P test")), Arg::NamedProfile);

        assert_eq!(
            Arg::from(&OsString::from("--remote-debugging-port")),
            Arg::RemoteDebuggingPort
        );
        assert_eq!(
            Arg::from(&OsString::from("-remote-debugging-port")),
            Arg::RemoteDebuggingPort
        );
        assert_eq!(
            Arg::from(&OsString::from("--remote-debugging-port 9222")),
            Arg::RemoteDebuggingPort
        );

        assert_eq!(
            Arg::from(&OsString::from("--remote-allow-hosts")),
            Arg::RemoteAllowHosts
        );
        assert_eq!(
            Arg::from(&OsString::from("-remote-allow-hosts")),
            Arg::RemoteAllowHosts
        );
        assert_eq!(
            Arg::from(&OsString::from("--remote-allow-hosts 9222")),
            Arg::RemoteAllowHosts
        );

        assert_eq!(
            Arg::from(&OsString::from("--remote-allow-origins")),
            Arg::RemoteAllowOrigins
        );
        assert_eq!(
            Arg::from(&OsString::from("-remote-allow-origins")),
            Arg::RemoteAllowOrigins
        );
        assert_eq!(
            Arg::from(&OsString::from("--remote-allow-origins http://foo")),
            Arg::RemoteAllowOrigins
        );
    }

    #[test]
    fn test_get_arg_value() {
        let args = vec!["-P""ProfileName""--profile=/path/""--no-remote"]
            .iter()
            .map(|x| OsString::from(x))
            .collect::<Vec<OsString>>();
        let parsed_args = parse_args(args.iter());
        assert_eq!(
            get_arg_value(parsed_args.iter(), Arg::NamedProfile),
            Some("ProfileName".into())
        );
        assert_eq!(
            get_arg_value(parsed_args.iter(), Arg::Profile),
            Some("/path/".into())
        );
        assert_eq!(get_arg_value(parsed_args.iter(), Arg::NoRemote), None);

        let args = vec!["--profile=""-P test"]
            .iter()
            .map(|x| OsString::from(x))
            .collect::<Vec<OsString>>();
        let parsed_args = parse_args(args.iter());
        assert_eq!(
            get_arg_value(parsed_args.iter(), Arg::NamedProfile),
            Some("test".into())
        );
        assert_eq!(
            get_arg_value(parsed_args.iter(), Arg::Profile),
            Some("".into())
        );
    }
}

Messung V0.5 in Prozent
C=85 H=92 G=88

¤ Dauer der Verarbeitung: 0.26 Sekunden  (vorverarbeitet am  2026-06-19) ¤

*© 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.