bug 1529278: mozrunner: support macOS application bundle paths; r=ato
authorNupur Baghel <nupurbaghel@gmail.com>
Fri, 15 Mar 2019 15:04:46 +0000
changeset 525105 505cad15904ebf5bb19c235394f92979aa1c888c
parent 525104 c6ec16f6a398a139ccb9dfc19138d6367f009c29
child 525106 b06e155361ff2b3b3f4f52964c6a620786270a77
push id2032
push userffxbld-merge
push dateMon, 13 May 2019 09:36:57 +0000
treeherdermozilla-release@455c1065dcbe [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersato
bugs1529278
milestone67.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
bug 1529278: mozrunner: support macOS application bundle paths; r=ato
Cargo.lock
testing/geckodriver/CHANGES.md
testing/mozbase/rust/mozrunner/Cargo.toml
testing/mozbase/rust/mozrunner/src/lib.rs
testing/mozbase/rust/mozrunner/src/runner.rs
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -170,16 +170,25 @@ dependencies = [
  "cranelift-wasm 0.29.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "env_logger 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "target-lexicon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "base64"
+version = "0.9.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "safemem 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "base64"
 version = "0.10.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "bench-collections-gtest"
@@ -1707,16 +1716,17 @@ dependencies = [
 
 [[package]]
 name = "mozrunner"
 version = "0.9.0"
 dependencies = [
  "dirs 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "mozprofile 0.5.0",
+ "plist 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "winreg 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "mozurl"
 version = "0.0.1"
 dependencies = [
  "nserror 0.1.0",
@@ -2009,16 +2019,28 @@ source = "registry+https://github.com/ru
 dependencies = [
  "binary-space-partition 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "euclid 0.19.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
+name = "plist"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "humantime 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
+ "xml-rs 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
 name = "podio"
 version = "0.1.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "precomputed-hash"
 version = "0.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2264,16 +2286,21 @@ dependencies = [
 ]
 
 [[package]]
 name = "ryu"
 version = "0.2.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
+name = "safemem"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
 name = "same-file"
 version = "1.0.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "winapi 0.3.6 (git+https://github.com/froydnj/winapi-rs?branch=aarch64)",
 ]
 
 [[package]]
@@ -3309,16 +3336,17 @@ dependencies = [
 "checksum arrayref 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "0fd1479b7c29641adbd35ff3b5c293922d696a92f25c8c975da3e0acbc87258f"
 "checksum arrayvec 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2f0ef4a9820019a0c91d918918c93dc71d469f581a49b47ddc1d285d4270bbe2"
 "checksum ascii-canvas 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b385d69402821a1c254533a011a312531cbcc0e3e24f19bbb4747a5a2daf37e2"
 "checksum atomic_refcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fb2dcb6e6d35f20276943cc04bb98e538b348d525a04ac79c10021561d202f21"
 "checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652"
 "checksum backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "89a47830402e9981c5c41223151efcced65a0510c13097c769cede7efb34782a"
 "checksum backtrace-sys 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)" = "c66d56ac8dabd07f6aacdaf633f4b8262f5b3601a810a0dcddffd5c22c69daa0"
 "checksum base64 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "621fc7ecb8008f86d7fb9b95356cd692ce9514b80a86d85b397f32a22da7b9e2"
+"checksum base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "489d6c0ed21b11d038c31b6ceccca973e65d73ba3bd8ecb9a2babf5546164643"
 "checksum binary-space-partition 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "88ceb0d16c4fd0e42876e298d7d3ce3780dd9ebdcbe4199816a32c77e08597ff"
 "checksum bincode 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bda13183df33055cbb84b847becce220d392df502ebe7a4a78d7021771ed94d0"
 "checksum bindgen 0.43.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6d52d263eacd15d26cbcf215d254b410bd58212aaa2d3c453a04b2d3b3adcf41"
 "checksum binjs_meta 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "430239e4551e42b80fa5d92322ac80ea38c9dda56e5d5582e057e2288352b71a"
 "checksum bit-set 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6f1efcc46c18245a69c38fcc5cc650f16d3a59d034f3106e9ed63748f695730a"
 "checksum bit-vec 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4440d5cb623bb7390ae27fec0bb6c61111969860f8e3ae198bfa0663645e67cf"
 "checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12"
 "checksum bitreader 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "80b13e2ab064ff3aa0bdbf1eff533f9822dc37899821f5f98c67f263eab51707"
@@ -3481,16 +3509,17 @@ dependencies = [
 "checksum petgraph 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)" = "9c3659d1ee90221741f65dd128d9998311b0e40c5d3c23a62445938214abce4f"
 "checksum phf 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "cb325642290f28ee14d8c6201159949a872f220c62af6e110a56ea914fbe42fc"
 "checksum phf_codegen 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "d62594c0bb54c464f633175d502038177e90309daf2e0158be42ed5f023ce88f"
 "checksum phf_generator 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "6b07ffcc532ccc85e3afc45865469bf5d9e4ef5bfcf9622e3cfe80c2d275ec03"
 "checksum phf_shared 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "07e24b0ca9643bdecd0632f2b3da6b1b89bbb0030e0b992afc1113b23a7bc2f2"
 "checksum pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "3a8b4c6b8165cd1a1cd4b9b120978131389f64bdaf456435caa41e630edba903"
 "checksum plain 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6"
 "checksum plane-split 0.13.7 (registry+https://github.com/rust-lang/crates.io-index)" = "9760bb0546502fcfae6d2d1d638fac6b9272027a3efae34060218152d0ce8387"
+"checksum plist 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "95bef0807b4fe77618f8d24f0c4ec37a4ad1dad9348c3b27d8b624c824d8cf48"
 "checksum podio 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e5422a1ee1bc57cc47ae717b0137314258138f38fd5f3cea083f43a9725383a0"
 "checksum precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c"
 "checksum proc-macro2 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "77997c53ae6edd6d187fec07ec41b207063b5ee6f33680e9fa86d405cdd313d4"
 "checksum proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)" = "77619697826f31a02ae974457af0b29b723e5619e113e9397b8b82c6bd253f09"
 "checksum procedural-masquerade 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9f566249236c6ca4340f7ca78968271f0ed2b0f234007a61b66f9ecd0af09260"
 "checksum quick-error 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eda5fe9b71976e62bc81b781206aaa076401769b2143379d3eb2118388babac4"
 "checksum quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9949cfe66888ffe1d53e6ec9d9f3b70714083854be20fd5e271b232a017401e8"
 "checksum quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "53fa22a1994bd0f9372d7a816207d8a2677ad0325b073f5c5332760f0fb62b5c"
@@ -3507,16 +3536,17 @@ dependencies = [
 "checksum regex-syntax 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8f1ac0f60d675cc6cf13a20ec076568254472551051ad5dd050364d70671bf6b"
 "checksum rkv 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "becd7f5278be3b97250a8035455116f9fc63f5fc68cc8293213051d7d751c373"
 "checksum ron 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "da06feaa07f69125ab9ddc769b11de29090122170b402547f64b86fe16ebc399"
 "checksum runloop 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5d79b4b604167921892e84afbbaad9d5ad74e091bf6c511d9dbfb0593f09fabd"
 "checksum rust-ini 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8a654c5bda722c699be6b0fe4c0d90de218928da5b724c3e467fc48865c37263"
 "checksum rustc-demangle 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "76d7ba1feafada44f2d38eed812bd2489a03c0f5abb975799251518b68848649"
 "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
 "checksum ryu 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "fd0568787116e13c652377b6846f5931454a363a8fdf8ae50463ee40935b278b"
+"checksum safemem 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8dca453248a96cb0749e36ccdfe2b0b4e54a61bfef89fb97ec621eb8e0a93dd9"
 "checksum same-file 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "cfb6eded0b06a0b512c8ddbcf04089138c9b4362c2f696f3c3d76039d68f3637"
 "checksum scoped-tls 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f417c22df063e9450888a7561788e9bd46d3bb3c1466435b4eccb903807f147d"
 "checksum scoped_threadpool 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "1d51f5df5af43ab3f1360b429fa5e0152ac5ce8c0bd6485cae490332e96846a8"
 "checksum scopeguard 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c79eb2c3ac4bc2507cda80e7f3ac5b88bd8eae4c0914d5663e6a8933994be918"
 "checksum scroll 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2f84d114ef17fd144153d608fba7c446b0145d038985e7a8cc5d08bb0ce20383"
 "checksum scroll_derive 0.9.5 (registry+https://github.com/rust-lang/crates.io-index)" = "8f1aa96c45e7f5a91cb7fabe7b279f02fea7126239fc40b732316e8b6a2d0fcb"
 "checksum semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a3186ec9e65071a2095434b1f5bb24838d4e8e130f584c790f6033c79943537"
 "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
--- a/testing/geckodriver/CHANGES.md
+++ b/testing/geckodriver/CHANGES.md
@@ -18,16 +18,25 @@ Unreleased
 
     1. `/Applications/Firefox.app/Contents/MacOS/firefox-bin`
     2. `$HOME/Applications/Firefox.app/Contents/MacOS/firefox-bin`
     3. `/Applications/Firefox Nightly.app/Contents/MacOS/firefox-bin`
     4. `$HOME/Applications/Firefox Nightly.app/Contents/MacOS/firefox-bin`
 
   Thanks to [Kriti Singh] for this patch.
 
+- Support for application bundle paths on macOS
+
+  It is now possible to pass an application bundle path, such as
+  `/Applications/Firefox.app` as argument to the `binary` field in
+  [`moz:firefoxOptions`].  This will be automatically resolved to
+  the absolute path of the binary when Firefox is started.
+
+  Thanks to [Nupur Baghel] for this patch.
+
 ### Removed
 
 - Dropped support for legacy Selenium web element references
 
   The legacy way of serialising web elements, using `{"ELEMENT": <UUID>}`,
   has been removed in this release.  This may break older Selenium
   clients and clients which are otherwise not compatible with the
   WebDriver standard.
@@ -1207,10 +1216,11 @@ 0.1.0 (2015-04-09)
 
 [Bastien Orivel]: https://github.com/Eijebong
 [Jason Juang]: https://github.com/juangj
 [Jeremy Lempereur]: https://github.com/o0Ignition0o
 [Joshua Bruning]: https://github.com/joshbruning
 [Kalpesh Krishna]: https://github.com/martiansideofthemoon
 [Kriti Singh]: https://github.com/kritisingh1
 [Mike Pennisi]: https://github.com/jugglinmike
+[Nupur Baghel]: https://github.com/nupurbaghel
 [Sven Jost]: https://github/mythsunwind
 [Vlad Filippov]: https://github.com/vladikoff
--- a/testing/mozbase/rust/mozrunner/Cargo.toml
+++ b/testing/mozbase/rust/mozrunner/Cargo.toml
@@ -4,16 +4,17 @@ version = "0.9.0"
 authors = ["Mozilla"]
 description = "Reliable Firefox process management."
 repository = "https://hg.mozilla.org/mozilla-central/file/tip/testing/mozbase/rust/mozrunner"
 license = "MPL-2.0"
 
 [dependencies]
 log = "0.4"
 mozprofile = { path = "../mozprofile" }
+plist = "0.4"
 
 [target.'cfg(target_os = "windows")'.dependencies]
 winreg = "0.5"
 
 [target.'cfg(target_os = "macos")'.dependencies]
 dirs = "1.0"
 
 [[bin]]
--- a/testing/mozbase/rust/mozrunner/src/lib.rs
+++ b/testing/mozbase/rust/mozrunner/src/lib.rs
@@ -1,13 +1,15 @@
 #[macro_use]
 extern crate log;
 extern crate mozprofile;
 #[cfg(target_os = "windows")]
 extern crate winreg;
 #[cfg(target_os = "macos")]
 extern crate dirs;
+#[cfg(target_os = "macos")]
+extern crate plist;
 
 pub mod firefox_args;
 pub mod path;
 pub mod runner;
 
 pub use crate::runner::platform::firefox_default_path;
--- a/testing/mozbase/rust/mozrunner/src/runner.rs
+++ b/testing/mozbase/rust/mozrunner/src/runner.rs
@@ -163,31 +163,36 @@ impl RunnerProcess for FirefoxProcess {
         debug!("Killing process {}", self.process.id());
         self.process.kill()?;
         self.process.wait()
     }
 }
 
 #[derive(Debug)]
 pub struct FirefoxRunner {
-    binary: PathBuf,
+    path: PathBuf,
     profile: Profile,
     args: Vec<OsString>,
     envs: HashMap<OsString, OsString>,
     stdout: Option<Stdio>,
     stderr: Option<Stdio>,
 }
 
 impl FirefoxRunner {
-    pub fn new(binary: &Path, profile: Profile) -> FirefoxRunner {
+    /// Initialise 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-bin_.
+    pub fn new(path: &Path, profile: Profile) -> FirefoxRunner {
         let mut envs: HashMap<OsString, OsString> = HashMap::new();
         envs.insert("MOZ_NO_REMOTE".into(), "1".into());
 
         FirefoxRunner {
-            binary: binary.to_path_buf(),
+            path: path.to_path_buf(),
             envs: envs,
             profile: profile,
             args: vec![],
             stdout: None,
             stderr: None,
         }
     }
 }
@@ -252,17 +257,18 @@ impl Runner for FirefoxRunner {
     }
 
     fn start(mut self) -> Result<FirefoxProcess, RunnerError> {
         self.profile.user_prefs()?.write()?;
 
         let stdout = self.stdout.unwrap_or_else(|| Stdio::inherit());
         let stderr = self.stderr.unwrap_or_else(|| Stdio::inherit());
 
-        let mut cmd = Command::new(&self.binary);
+        let binary_path = platform::resolve_binary_path(&mut self.path);
+        let mut cmd = Command::new(binary_path);
         cmd.args(&self.args[..])
             .envs(&self.envs)
             .stdout(stdout)
             .stderr(stderr);
 
         let mut seen_foreground = false;
         let mut seen_no_remote = false;
         let mut seen_profile = false;
@@ -293,31 +299,62 @@ impl Runner for FirefoxRunner {
     }
 }
 
 #[cfg(target_os = "linux")]
 pub mod platform {
     use path::find_binary;
     use std::path::PathBuf;
 
+    pub fn resolve_binary_path(path: &mut PathBuf) -> &PathBuf {
+        path
+    }
+
     /// Searches the system path for `firefox`.
     pub fn firefox_default_path() -> Option<PathBuf> {
         find_binary("firefox")
     }
 
     pub fn arg_prefix_char(c: char) -> bool {
         c == '-'
     }
 }
 
 #[cfg(target_os = "macos")]
 pub mod platform {
     use crate::path::{find_binary, is_binary};
     use dirs;
     use std::path::PathBuf;
+    use plist::Value;
+
+    /// 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.
+    pub fn resolve_binary_path(path: &mut PathBuf) -> &PathBuf {
+        if path.as_path().is_dir() {
+            let mut info_plist = path.clone();
+            info_plist.push("Contents");
+            info_plist.push("Info.plist");
+            if let Ok(plist) = Value::from_file(&info_plist) {
+                if let Some(dict) = plist.as_dictionary() {
+                    if let Some(binary_file) = dict.get("CFBundleExecutable") {
+                        match binary_file {
+                            Value::String(s) => {
+                                path.push("Contents");
+                                path.push("MacOS");
+                                path.push(s);
+                            },
+                            _ => {}
+                        }
+                    }
+                }
+            }
+        }
+        path
+    }
 
     /// Searches the system path for `firefox-bin`, then looks for
     /// `Applications/Firefox.app/Contents/MacOS/firefox-bin` as well
     /// as `Applications/Firefox Nightly.app/Contents/MacOS/firefox-bin`
     /// under both `/` (system root) and the user home directory.
     pub fn firefox_default_path() -> Option<PathBuf> {
         if let Some(path) = find_binary("firefox-bin") {
             return Some(path);
@@ -352,16 +389,20 @@ pub mod platform {
 #[cfg(target_os = "windows")]
 pub mod platform {
     use path::{find_binary, is_binary};
     use std::io::Error;
     use std::path::PathBuf;
     use winreg::RegKey;
     use winreg::enums::*;
 
+    pub fn resolve_binary_path(path: &mut PathBuf) -> &PathBuf {
+        path
+    }
+
     /// Searches the Windows registry, then the system path for `firefox.exe`.
     ///
     /// It _does not_ currently check the `HKEY_CURRENT_USER` tree.
     pub fn firefox_default_path() -> Option<PathBuf> {
         if let Ok(Some(path)) = firefox_registry_path() {
             if is_binary(&path) {
                 return Some(path);
             }
@@ -407,16 +448,21 @@ pub mod platform {
         c == '/' || c == '-'
     }
 }
 
 #[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows")))]
 pub mod platform {
     use std::path::PathBuf;
 
+    /// Returns an unaltered path for all operating systems other than macOS.
+    pub fn resolve_binary_path(path: &mut PathBuf) -> &PathBuf {
+        path
+    }
+
     /// Returns `None` for all other operating systems than Linux, macOS, and
     /// Windows.
     pub fn firefox_default_path() -> Option<PathBuf> {
         None
     }
 
     pub fn arg_prefix_char(c: char) -> bool {
         c == '-'