/* This Source Code Form is subject to the terms of the Mozilla Public *License,v.2.0.IfacopyoftheMPLwasnotdistributedwiththis
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use mozprofile::prefreader::PrefReaderError; use mozprofile::profile::Profile; use std::collections::HashMap; use std::ffi::{OsStr, OsString}; use std::io; use std::path::{Path, PathBuf}; use std::process; use std::process::{Child, Command, Stdio}; use std::thread; use std::time; use thiserror::Error;
usecrate::firefox_args::Arg;
pubtrait Runner { type Process;
fn arg<S>(&mutself, arg: S) -> &mutSelf where
S: AsRef<OsStr>;
pubtrait RunnerProcess { /// Attempts to collect the exit status of the process if it has already exited. /// /// This function will not block the calling thread and will only advisorily check to see if /// the child process has exited or not. If the process has exited then on Unix the process ID /// is reaped. This function is guaranteed to repeatedly return a successful exit status so /// long as the child has already exited. /// /// If the process has exited, then `Ok(Some(status))` is returned. If the exit status is not /// available at this time then `Ok(None)` is returned. If an error occurs, then that error is /// returned. fn try_wait(&mutself) -> io::Result<Option<process::ExitStatus>>;
/// Waits for the process to exit completely, killing it if it does not stop within `timeout`, /// and returns the status that it exited with. /// /// Firefox' integrated background monitor observes long running threads during shutdown and /// kills these after 63 seconds. If the process fails to exit within the duration of /// `timeout`, it is forcefully killed. /// /// This function will continue to have the same return value after it has been called at least /// once. fn wait(&mutself, timeout: time::Duration) -> io::Result<process::ExitStatus>;
/// Determine if the process is still running. fn running(&mutself) -> bool;
/// Forces the process to exit and returns the exit status. This is /// equivalent to sending a SIGKILL on Unix platforms. fn kill(&mutself) -> io::Result<process::ExitStatus>;
}
#[derive(Debug)] pubstruct FirefoxProcess {
process: Child, // The profile field is not directly used, but it is kept to avoid its // Drop removing the (temporary) profile directory. #[allow(dead_code)]
profile: Option<Profile>,
}
impl FirefoxRunner { /// Initialize Firefox process runner. /// /// On macOS, `path` can optionally point to an application bundle, /// i.e. _/Applications/Firefox.app_, as well as to an executable program /// such as _/Applications/Firefox.app/Content/MacOS/firefox_. pubfn new(path: &Path, profile: Option<Profile>) -> FirefoxRunner {
FirefoxRunner {
path: path.to_path_buf(),
envs: HashMap::new(),
profile,
args: vec![],
stdout: None,
stderr: None,
}
}
}
impl Runner for FirefoxRunner { type Process = FirefoxProcess;
/// Searches the system path for `firefox`. pubfn firefox_default_path() -> Option<PathBuf> { if running_as_snap() { return Some(PathBuf::from("/snap/firefox/current/firefox.launcher"));
}
find_binary("firefox")
}
pubfn arg_prefix_char(c: char) -> bool {
c == '-'
}
#[cfg(test)] mod tests { usecrate::firefox_default_path; use std::env; use std::ops::Drop; use std::path::PathBuf;
#[cfg(target_os = "macos")] pubmod platform { usecrate::path::{find_binary, is_app_bundle, is_binary}; use plist::Value; use std::path::PathBuf;
/// Searches for the binary file inside the path passed as parameter. /// If the binary is not found, the path remains unaltered. /// Else, it gets updated by the new binary path. pubfn resolve_binary_path(path: &mut PathBuf) -> &PathBuf { if path.as_path().is_dir() { letmut info_plist = path.clone();
info_plist.push("Contents");
info_plist.push("Info.plist"); iflet Ok(plist) = Value::from_file(&info_plist) { iflet Some(dict) = plist.as_dictionary() { iflet Some(Value::String(s)) = dict.get("CFBundleExecutable") {
path.push("Contents");
path.push("MacOS");
path.push(s);
}
}
}
}
path
}
/// Searches the system path for `firefox`, then looks for /// `Applications/Firefox.app/Contents/MacOS/firefox` as well /// as `Applications/Firefox Nightly.app/Contents/MacOS/firefox` /// and `Applications/Firefox Developer Edition.app/Contents/MacOS/firefox` /// under both `/` (system root) and the user home directory. pubfn firefox_default_path() -> Option<PathBuf> { iflet Some(path) = find_binary("firefox") { return Some(path);
}
let home = dirs::home_dir(); for &(prefix_home, trial_path) in [
(false, "/Applications/Firefox.app"),
(true, "Applications/Firefox.app"),
(false, "/Applications/Firefox Developer Edition.app"),
(true, "Applications/Firefox Developer Edition.app"),
(false, "/Applications/Firefox Nightly.app"),
(true, "Applications/Firefox Nightly.app"),
]
.iter()
{ let path = match (home.as_ref(), prefix_home) {
(Some(home_dir), true) => home_dir.join(trial_path),
(None, true) => continue,
(_, false) => PathBuf::from(trial_path),
};
if is_binary(&path) || is_app_bundle(&path) { return Some(path);
}
}
#[cfg(target_os = "windows")] pubmod platform { usecrate::path::{find_binary, is_binary}; use std::io::Error; use std::path::PathBuf; use winreg::enums::*; use winreg::RegKey;
/// Searches the Windows registry, then the system path for `firefox.exe`. /// /// It _does not_ currently check the `HKEY_CURRENT_USER` tree. pubfn firefox_default_path() -> Option<PathBuf> { iflet Ok(Some(path)) = firefox_registry_path() { if is_binary(&path) { return Some(path);
}
};
find_binary("firefox.exe")
}
fn firefox_registry_path() -> Result<Option<PathBuf>, Error> { let hklm = RegKey::predef(HKEY_LOCAL_MACHINE); for subtree_key in ["SOFTWARE", "SOFTWARE\\WOW6432Node"].iter() { let subtree = hklm.open_subkey_with_flags(subtree_key, KEY_READ)?; let mozilla_org = match subtree.open_subkey_with_flags("mozilla.org\\Mozilla", KEY_READ)
{
Ok(val) => val,
Err(_) => continue,
}; let current_version: String = mozilla_org.get_value("CurrentVersion")?; let mozilla = subtree.open_subkey_with_flags("Mozilla", KEY_READ)?; for key_res in mozilla.enum_keys() { let key = key_res?; let section_data = mozilla.open_subkey_with_flags(&key, KEY_READ)?; let version: Result<String, _> = section_data.get_value("GeckoVer"); iflet Ok(ver) = version { if ver == current_version { letmut bin_key = key.to_owned();
bin_key.push_str("\\bin"); iflet Ok(bin_subtree) = mozilla.open_subkey_with_flags(bin_key, KEY_READ) { let path_to_exe: Result<String, _> = bin_subtree.get_value("PathToExe"); iflet Ok(path_to_exe) = path_to_exe { let path = PathBuf::from(path_to_exe); if is_binary(&path) { return Ok(Some(path));
}
}
}
}
}
}
}
Ok(None)
}
pubfn arg_prefix_char(c: char) -> bool {
c == '/' || c == '-'
}
}
#[cfg(not(any(unix, target_os = "windows")))] pubmod platform { use std::path::PathBuf;
/// Returns an unaltered path for all operating systems other than macOS. pubfn resolve_binary_path(path: &mut PathBuf) -> &PathBuf {
path
}
/// Returns `None` for all other operating systems than Linux, macOS, and /// Windows. pubfn firefox_default_path() -> Option<PathBuf> {
None
}
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.