From 3bf0bda2b321ef14c97899129c0507e530ee1642 Mon Sep 17 00:00:00 2001 From: Andreas Tolfsen Date: Mon, 12 Mar 2018 23:07:48 +0000 Subject: [PATCH] import of 0.20.0 --- .hgignore | 1 - CHANGES.md | 56 +++- CONTRIBUTING.md | 52 ++-- Cargo.lock | 654 +++++++++++++++++++------------------------- Cargo.toml | 19 +- README.md | 127 +++++++-- doc/Releasing.md | 104 ++++--- doc/TraceLogs.md | 4 +- doc/index.rst | 20 +- mach_commands.py | 81 ++++-- moz.build | 7 + src/capabilities.rs | 53 ++-- src/logging.rs | 362 ++++++++++++++++-------- src/main.rs | 28 +- src/marionette.rs | 171 +++++++----- src/prefs.rs | 23 +- 16 files changed, 1014 insertions(+), 748 deletions(-) delete mode 100644 .hgignore diff --git a/.hgignore b/.hgignore deleted file mode 100644 index 2f7896d1..00000000 --- a/.hgignore +++ /dev/null @@ -1 +0,0 @@ -target/ diff --git a/CHANGES.md b/CHANGES.md index 63282ce4..9f9dedc9 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -3,6 +3,52 @@ Change log All notable changes to this program is documented in this file. +0.20.0 (2018-03-08) +------------------- + +### Added + +- New `--jsdebugger` flag to open the [Browser Toolbox] when Firefox + launches. This is useful for debugging Marionette internals. + +- Introduced the temporary, boolean capability + `moz:useNonSpecCompliantPointerOrigin` to disable the WebDriver + conforming behavior of calculating the Pointer Origin. + +### Changed + +- HTTP status code for the [`StaleElementReference`] error changed + from 400 (Bad Request) to 404 (Not Found). + +- Backtraces from geckodriver no longer substitute for missing + Marionette stacktraces. + +- [webdriver crate] upgraded to 0.35.0. + +### Fixed + +- The Firefox process is now given ample time to shut down, allowing + enough time for the Firefox shutdown hang monitor to kick in. + + Firefox has an integrated background monitor that observes + long-running threads during shutdown. These threads will be + killed after 63 seconds in the event of a hang. To allow Firefox + to shut down these threads on its own, geckodriver has to wait + that time and some additional seconds. + +- Grapheme clusters are now accepted as input for keyboard input + to actions. + + Input to the `value` field of the `keyDown` and `keyUp` action + primitives used to only accept single characters, which means + geckodriver would error when a valid grapheme cluster was sent in, + for example with the tamil nadu character U+0BA8 U+0BBF. + + Thanks to Greg Fraley for fixing this bug. + +- Improved error messages for malformed capability values. + + 0.19.1 (2017-10-30) ------------------- @@ -28,7 +74,7 @@ All notable changes to this program is documented in this file. 0.19.0 (2017-09-16) ------------------- -Note that with geckodriver v0.19.0 the following versions are recommended: +Note that with geckodriver 0.19.0 the following versions are recommended: - Firefox 55.0 (and greater) - Selenium 3.5 (and greater) @@ -763,9 +809,11 @@ and greater. [README]: https://github.com/mozilla/geckodriver/blob/master/README.md +[Browser Toolbox]: https://developer.mozilla.org/en-US/docs/Tools/Browser_Toolbox [`CloseWindowResponse`]: https://docs.rs/webdriver/newest/webdriver/response/struct.CloseWindowResponse.html [`CookieResponse`]: https://docs.rs/webdriver/newest/webdriver/response/struct.CookieResponse.html +[`DeleteSession`]: https://docs.rs/webdriver/newest/webdriver/command/enum.WebDriverCommand.html#variant.DeleteSession [`ElementClickIntercepted`]: https://docs.rs/webdriver/newest/webdriver/error/enum.ErrorStatus.html#variant.ElementClickIntercepted [`ElementNotInteractable`]: https://docs.rs/webdriver/newest/webdriver/error/enum.ErrorStatus.html#variant.ElementNotInteractable [`FullscreenWindow`]: https://docs.rs/webdriver/newest/webdriver/command/enum.WebDriverCommand.html#variant.FullscreenWindow @@ -781,6 +829,7 @@ and greater. [`SessionNotCreated`]: https://docs.rs/webdriver/newest/webdriver/error/enum.ErrorStatus.html#variant.SessionNotCreated [`SetTimeouts`]: https://docs.rs/webdriver/newest/webdriver/command/enum.WebDriverCommand.html#variant.SetTimeouts [`SetWindowRect`]: https://docs.rs/webdriver/newest/webdriver/command/enum.WebDriverCommand.html#variant.SetWindowRect +[`StaleElementReference`]: https://docs.rs/webdriver/newest/webdriver/error/enum.ErrorStatus.html#variant.StaleElementReference [`UnableToCaptureScreen`]: https://docs.rs/webdriver/newest/webdriver/error/enum.ErrorStatus.html#variant.UnableToCaptureScreen [`UnknownCommand`]: https://docs.rs/webdriver/newest/webdriver/error/enum.ErrorStatus.html#variant.UnknownCommand [`UnknownError`]: https://docs.rs/webdriver/newest/webdriver/error/enum.ErrorStatus.html#variant.UnknownError @@ -790,15 +839,16 @@ and greater. [webdriver crate]: https://crates.io/crates/webdriver [Actions]: https://w3c.github.io/webdriver/webdriver-spec.html#actions +[Delete Session]: https://w3c.github.io/webdriver/webdriver-spec.html#delete-session [Element Click]: https://w3c.github.io/webdriver/webdriver-spec.html#element-click [Get Timeouts]: https://w3c.github.io/webdriver/webdriver-spec.html#get-timeouts -[Set Timeouts]: https://w3c.github.io/webdriver/webdriver-spec.html#set-timeouts [Get Window Rect]: https://w3c.github.io/webdriver/webdriver-spec.html#get-window-rect -[Set Window Rect]: https://w3c.github.io/webdriver/webdriver-spec.html#set-window-rect [insecure certificate]: https://w3c.github.io/webdriver/webdriver-spec.html#dfn-insecure-certificate [Minimize Window]: https://w3c.github.io/webdriver/webdriver-spec.html#minimize-window [New Session]: https://w3c.github.io/webdriver/webdriver-spec.html#new-session [Send Alert Text]: https://w3c.github.io/webdriver/webdriver-spec.html#send-alert-text +[Set Timeouts]: https://w3c.github.io/webdriver/webdriver-spec.html#set-timeouts +[Set Window Rect]: https://w3c.github.io/webdriver/webdriver-spec.html#set-window-rect [Status]: https://w3c.github.io/webdriver/webdriver-spec.html#status [Take Element Screenshot]: https://w3c.github.io/webdriver/webdriver-spec.html#take-element-screenshot [WebDriver errors]: https://w3c.github.io/webdriver/webdriver-spec.html#handling-errors diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 648bbc9a..d1e76bca 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -14,7 +14,7 @@ parts it can be useful to know about: to communicate with, instrument, and control Gecko. It is built in to Firefox and written in [XPCOM] flavoured JavaScript. - * [_libwebdriver_] is a Rust crate providing interfaces, traits + * [_webdriver_] is a Rust crate providing interfaces, traits and types, errors, type- and bounds checks, and JSON marshaling for correctly parsing and emitting the [WebDriver protocol]. @@ -22,9 +22,9 @@ By participating in this project, you agree to abide by the Mozilla [Community Participation Guidelines]. Here are some guidelines for contributing high-quality and actionable bugs and code. -[_geckodriver_]: ./README.md -[_Marionette_]: ../marionette/README.md -[_libwebdriver_]: ../webdriver/README.md +[_geckodriver_]: https://firefox-source-docs.mozilla.org/testing/geckodriver/geckodriver/ +[_Marionette_]: https://firefox-source-docs.mozilla.org/testing/marionette/marionette/ +[_webdriver_]: https://crates.io/crates/webdriver [WebDriver protocol]: https://w3c.github.io/webdriver/webdriver-spec.html#protocol [XPCOM]: https://developer.mozilla.org/en-US/docs/Mozilla/Tech/XPCOM/Guide [Community Participation Guidelines]: https://www.mozilla.org/en-US/about/governance/policies/participation/ @@ -60,12 +60,11 @@ the affected system, reproduction steps, and logs. geckodriver development follows a rolling release model as we don’t release patches for older versions. It is therefore useful to use the tip-of-tree geckodriver binary, or failing this, the latest -release when verifying the problem. Similarly, as noted in the -[README], geckodriver is only compatible with the current release -channel versions of Firefox, and it consequently does not help -to report bugs that affect outdated and unsupported Firefoxen. -Please always try to verify the issue in the latest Firefox Nightly -before you file your bug. +release when verifying the problem. geckodriver is only compatible +with the current release channel versions of Firefox, and it +consequently does not help to report bugs that affect outdated and +unsupported Firefoxen. Please always try to verify the issue in +the latest Firefox Nightly before you file your bug. Once we are satisfied the issue raised is of sufficiently actionable character, we will continue with triaging it and file a bug where it @@ -73,9 +72,8 @@ is appropriate. Bugs specific to geckodriver will be filed in the [`Testing :: geckodriver`] component in Bugzilla. [mailing list]: #communication -[trace-level log]: doc/TraceLogs.md +[trace-level log]: https://firefox-source-docs.mozilla.org/testing/geckodriver/geckodriver/TraceLogs.html [GitHub issue tracker]: https://github.com/mozilla/geckodriver/issues -[README]: ./README.md [`Testing :: geckodriver`]: https://bugzilla.mozilla.org/buglist.cgi?component=geckodriver @@ -89,7 +87,7 @@ where to start. Please don’t hesitate to [ask questions]! The canonical source code repository of geckodriver is now [mozilla-central]. We continue to use the [GitHub issue tracker] as a triage ground before actual, actionable bugs and tasks are filed -in the [`Testing :: geckodriver`] component in Bugzilla. We also +in the [`Testing :: geckodriver`] component on Bugzilla. We also have a curated set of [good first bugs] you may consider attempting first. The purpose of this guide _is not_ to make sure you have a basic @@ -126,20 +124,19 @@ When you have, you are ready to start off your first build: % ./mach build testing/geckodriver -The geckodriver executable will appear in `${objdir}/dist/bin/geckodriver` -alongside firefox-bin. To run it you can use mach: +To run the executable from the objdir: % ./mach geckodriver -- --version 0:00.27 /home/ato/src/gecko/obj-x86_64-pc-linux-gnu/dist/bin/geckodriver --version --binary /home/ato/src/gecko/obj-x86_64-pc-linux-gnu/dist/bin/firefox geckodriver 0.19.0 (f3e939a81ee1169f9501ad96eb43bbf4bf4a1bde 2017-10-11) [Rust]: https://www.rust-lang.org/ -[webdriver crate]: ../webdriver/README.md +[webdriver crate]: https://crates.io/crates/webdriver [commands]: https://docs.rs/webdriver/newest/webdriver/command/index.html [responses]: https://docs.rs/webdriver/newest/webdriver/response/index.html [errors]: https://docs.rs/webdriver/newest/webdriver/error/enum.ErrorStatus.html [Marionette protocol]: https://developer.mozilla.org/en-US/docs/Mozilla/QA/Marionette/Protocol -[Marionette]: ../marionette/README.md +[Marionette]: https://firefox-source-docs.mozilla.org/testing/marionette/marionette/index.html [Firefox CI]: https://treeherder.mozilla.org/ [mozconfig]: https://developer.mozilla.org/en-US/docs/Mozilla/Developer_guide/Build_Instructions/Configuring_Build_Options @@ -154,18 +151,17 @@ a set of conformance tests with other browser vendors through the compatibility between _different_ WebDriver implementations for different browsers. -In addition to the WPT tests, geckodriver and libwebdriver has -unit tests. At the moment there is no way to run Rust unit tests -through mach, although this is being worked on. For the moment -you need to kick off a separate build using [cargo]: +In addition to the WPT tests, geckodriver and webdriver have unit tests. +You can use a mach command to run them: - % cd testing/geckodriver - Compiling geckodriver v0.19.0 (file:///home/ato/src/gecko/testing/geckodriver) - … - test result: ok. 7 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out + % ./mach test testing/geckodriver -Because the unit tests _are not_ currently run in the [Firefox CI], -hopefully you will find that they all pass. (-: +The webdriver crate tests are unfortunately not yet runnable through mach. +Work to make this possible is tracked in [[https://bugzil.la/1424369]]. +For the moment you must run them manually through `cargo`: + + % cd testing/webdriver + % cargo test To run the more extensive WPT tests you can use mach, but first make sure you have a build of Firefox: @@ -229,4 +225,4 @@ channel on irc.mozilla.org. Don’t ask if you can ask a question, just ask, and please wait for an answer as we might not be in your timezone. [subscribe]: https://lists.mozilla.org/listinfo/tools-marionette -[archive]: http://groups.google.com/group/mozilla.tools.marionette +[archive]: https://groups.google.com/group/mozilla.tools.marionette diff --git a/Cargo.lock b/Cargo.lock index 735946c8..21778c94 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,64 +1,38 @@ [[package]] -name = "advapi32-sys" -version = "0.1.2" +name = "adler32" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] name = "aho-corasick" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "backtrace" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "backtrace-sys 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "dbghelp-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-demangle 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "backtrace-sys" -version = "0.1.10" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "gcc 0.3.42 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "base64" -version = "0.5.2" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "safemem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "bitflags" -version = "0.7.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "bitflags" -version = "0.8.2" +name = "build_const" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "byteorder" -version = "1.0.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -66,22 +40,27 @@ name = "bzip2" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bzip2-sys 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)", + "bzip2-sys 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "bzip2-sys" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "gcc 0.3.42 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "cc" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "cfg-if" -version = "0.1.0" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -89,120 +68,101 @@ name = "chrono" version = "0.2.25" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "num 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)", + "num 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "clap" -version = "2.24.2" +version = "2.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", - "strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "term_size 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-segmentation 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "term_size 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "textwrap 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "vec_map 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "cookie" -version = "0.9.1" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "time 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "crossbeam" -version = "0.2.10" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "dbghelp-sys" -version = "0.2.0" +name = "crc" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "build_const 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "flate2" -version = "0.2.19" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)", - "miniz-sys 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", + "miniz_oxide_c_api 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "fuchsia-zircon" -version = "0.2.1" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "fuchsia-zircon-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "fuchsia-zircon-sys" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "gcc" -version = "0.3.42" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "geckodriver" -version = "0.19.1" +version = "0.20.0" dependencies = [ "chrono 0.2.25 (registry+https://github.com/rust-lang/crates.io-index)", - "clap 2.24.2 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.10.10 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "clap 2.31.1 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.10.13 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "mozprofile 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "mozrunner 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "mozversion 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", - "slog 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "slog-atomic 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "slog-stdlog 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "slog-stream 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "mozrunner 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "mozversion 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", "uuid 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", - "webdriver 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)", - "zip 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)", + "webdriver 0.35.0 (registry+https://github.com/rust-lang/crates.io-index)", + "zip 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "httparse" -version = "1.2.2" +version = "1.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "hyper" -version = "0.10.10" +version = "0.10.13" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "base64 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "httparse 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "base64 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "httparse 1.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "mime 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "mime 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", "traitobject 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "typeable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -210,30 +170,11 @@ name = "idna" version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "matches 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-bidi 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-normalization 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "isatty" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "kernel32-sys" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "kernel32-sys" version = "0.2.2" @@ -243,15 +184,6 @@ dependencies = [ "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "ktmw32-sys" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "language-tags" version = "0.2.2" @@ -259,52 +191,69 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "lazy_static" -version = "0.1.16" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "lazy_static" -version = "0.2.2" +name = "libc" +version = "0.2.39" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "libc" -version = "0.2.24" +name = "log" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "log" -version = "0.3.6" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "matches" -version = "0.1.4" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "memchr" -version = "1.0.1" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "mime" -version = "0.2.4" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "miniz-sys" -version = "0.1.9" +name = "miniz_oxide" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "gcc 0.3.42 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)", + "adler32 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "miniz_oxide_c_api" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cc 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "crc 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", + "miniz_oxide 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -312,26 +261,26 @@ name = "mozprofile" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "tempdir 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "mozrunner" -version = "0.5.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "mozprofile 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winreg 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "winreg 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "mozversion" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "regex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rust-ini 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "rust-ini 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -341,120 +290,127 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "num" -version = "0.1.37" +version = "0.1.42" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "num-integer 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)", - "num-iter 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", + "num-integer 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)", + "num-iter 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "num-integer" -version = "0.1.33" +version = "0.1.36" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "num-iter" -version = "0.1.33" +version = "0.1.35" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "num-integer 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", + "num-integer 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "num-traits" -version = "0.1.37" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "num_cpus" -version = "1.2.1" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "percent-encoding" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "podio" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "rand" -version = "0.3.17" +version = "0.3.22" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "fuchsia-zircon 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)", + "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "redox_syscall" -version = "0.1.16" +version = "0.1.37" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "regex" -version = "0.2.1" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "aho-corasick 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-syntax 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "thread_local 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "aho-corasick 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "regex-syntax" -version = "0.4.0" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "ucd-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] -name = "rust-ini" -version = "0.10.0" +name = "remove_dir_all" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "rustc-demangle" -version = "0.1.4" +name = "rust-ini" +version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "rustc-serialize" -version = "0.3.22" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "rustc_version" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "semver 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "semver" -version = "0.1.20" +name = "safemem" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -470,113 +426,56 @@ name = "semver-parser" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "slog" -version = "1.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "slog-atomic" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "crossbeam 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", - "slog 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "slog-extra" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "slog 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "thread_local 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "slog-stdlog" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "crossbeam 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "slog 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "slog-term 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "slog-stream" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "slog 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "slog-extra 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "thread_local 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "slog-term" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "chrono 0.2.25 (registry+https://github.com/rust-lang/crates.io-index)", - "isatty 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "slog 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "slog-stream 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "thread_local 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "strsim" -version = "0.6.0" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "tempdir" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "remove_dir_all 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "term_size" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "thread-id" -version = "3.0.0" +name = "textwrap" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)", + "term_size 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "thread_local" -version = "0.3.3" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "thread-id 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "time" -version = "0.1.36" +version = "0.1.39" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -589,20 +488,25 @@ name = "typeable" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "ucd-util" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "unicase" -version = "1.4.0" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "version_check 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "unicode-bidi" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "matches 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -612,7 +516,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "unicode-segmentation" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -622,7 +526,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "unreachable" -version = "0.1.1" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -630,12 +534,12 @@ dependencies = [ [[package]] name = "url" -version = "1.5.1" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "idna 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "matches 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "percent-encoding 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -648,13 +552,13 @@ name = "uuid" version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "vec_map" -version = "0.8.0" +name = "version_check" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -664,17 +568,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "webdriver" -version = "0.32.0" +version = "0.35.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "cookie 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.10.10 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "cookie 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.10.13 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-segmentation 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -682,121 +586,129 @@ name = "winapi" version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "winapi" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "winapi-build" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "winreg" -version = "0.3.5" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "advapi32-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "kernel32-sys 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "ktmw32-sys 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "zip" -version = "0.1.19" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bzip2 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "flate2 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)", + "flate2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "msdos_time 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "podio 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)", + "podio 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", ] [metadata] -"checksum advapi32-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "307c92332867e586720c0222ee9d890bbe8431711efed8a1b06bc5b40fc66bd7" -"checksum aho-corasick 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0638fd549427caa90c499814196d1b9e3725eb4d15d7339d6de073a680ed0ca2" -"checksum backtrace 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "72f9b4182546f4b04ebc4ab7f84948953a118bd6021a1b6a6c909e3e94f6be76" -"checksum backtrace-sys 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "d192fd129132fbc97497c1f2ec2c2c5174e376b95f535199ef4fe0a293d33842" -"checksum base64 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "30e93c03064e7590d0466209155251b90c22e37fab1daf2771582598b5827557" -"checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d" -"checksum bitflags 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1370e9fc2a6ae53aea8b7a5110edbd08836ed87c88736dfabccade1c2b44bff4" -"checksum byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c40977b0ee6b9885c9013cd41d9feffdd22deb3bb4dc3a71d901cc7a77de18c8" +"checksum adler32 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6cbd0b9af8587c72beadc9f72d35b9fbb070982c9e6203e46e93f10df25f8f45" +"checksum aho-corasick 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d6531d44de723825aa81398a6415283229725a00fa30713812ab9323faa82fc4" +"checksum base64 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "96434f987501f0ed4eb336a411e0631ecd1afa11574fe148587adc4ff96143c9" +"checksum bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b3c30d3802dfb7281680d6285f2ccdaa8c2d8fee41f93805dba5c4cf50dc23cf" +"checksum build_const 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e90dc84f5e62d2ebe7676b83c22d33b6db8bd27340fb6ffbff0a364efa0cb9c9" +"checksum byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "652805b7e73fada9d85e9a6682a4abd490cb52d96aeecc12e33a0de34dfd0d23" "checksum bzip2 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c3eafc42c44e0d827de6b1c131175098fe7fb53b8ce8a47e65cb3ea94688be24" -"checksum bzip2-sys 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "98ce3fff84d4e90011f464bbdf48e3428f04270439f703868fd489d2aaedfc30" -"checksum cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "de1e760d7b6535af4241fca8bd8adf68e2e7edacc6b29f5d399050c5e48cf88c" +"checksum bzip2-sys 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2c5162604199bbb17690ede847eaa6120a3f33d5ab4dcc8e7c25b16d849ae79b" +"checksum cc 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "fedf677519ac9e865c4ff43ef8f930773b37ed6e6ea61b6b83b400a7b5787f49" +"checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de" "checksum chrono 0.2.25 (registry+https://github.com/rust-lang/crates.io-index)" = "9213f7cd7c27e95c2b57c49f0e69b1ea65b27138da84a170133fd21b07659c00" -"checksum clap 2.24.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6b8f69e518f967224e628896b54e41ff6acfb4dcfefc5076325c36525dac900f" -"checksum cookie 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a54aa6d675d62b2f95b56b331b5222a520149a54f23a2d21974dfcc69caf0a9d" -"checksum crossbeam 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "0c5ea215664ca264da8a9d9c3be80d2eaf30923c259d03e870388eb927508f97" -"checksum dbghelp-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "97590ba53bcb8ac28279161ca943a924d1fd4a8fb3fa63302591647c4fc5b850" -"checksum flate2 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)" = "36df0166e856739905cd3d7e0b210fe818592211a008862599845e012d8d304c" -"checksum fuchsia-zircon 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f6c0581a4e363262e52b87f59ee2afe3415361c6ec35e665924eb08afe8ff159" -"checksum fuchsia-zircon-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "43f3795b4bae048dc6123a6b972cadde2e676f9ded08aef6bb77f5f157684a82" -"checksum gcc 0.3.42 (registry+https://github.com/rust-lang/crates.io-index)" = "291055c78f59ca3d84c99026c9501c469413d386bb46be1e1cf1d285cd1db3b0" -"checksum httparse 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "77f756bed9ee3a83ce98774f4155b42a31b787029013f3a7d83eca714e500e21" -"checksum hyper 0.10.10 (registry+https://github.com/rust-lang/crates.io-index)" = "36e108e0b1fa2d17491cbaac4bc460dc0956029d10ccf83c913dd0e5db3e7f07" +"checksum clap 2.31.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5dc18f6f4005132120d9711636b32c46a233fad94df6217fa1d81c5e97a9f200" +"checksum cookie 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "746858cae4eae40fff37e1998320068df317bc247dc91a67c6cfa053afdc2abb" +"checksum crc 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bd5d02c0aac6bd68393ed69e00bbc2457f3e89075c6349db7189618dc4ddc1d7" +"checksum flate2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9fac2277e84e5e858483756647a9d0aa8d9a2b7cba517fd84325a0aaa69a0909" +"checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" +"checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" +"checksum httparse 1.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "c2f407128745b78abc95c0ffbe4e5d37427fdc0d45470710cfef8c44522a2e37" +"checksum hyper 0.10.13 (registry+https://github.com/rust-lang/crates.io-index)" = "368cb56b2740ebf4230520e2b90ebb0461e69034d85d1945febd9b3971426db2" "checksum idna 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "014b298351066f1512874135335d62a789ffe78a9974f94b43ed5621951eaf7d" -"checksum isatty 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "fa500db770a99afe2a0f2229be2a3d09c7ed9d7e4e8440bf71253141994e240f" -"checksum kernel32-sys 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "e014dab1082fd9d80ea1fa6fcb261b47ed3eb511612a14198bb507701add083e" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" -"checksum ktmw32-sys 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7f9313a869ff779ae08dd990b75a92dc06aa16d771f41305f7286649cd39a0ee" "checksum language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a" -"checksum lazy_static 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "cf186d1a8aa5f5bee5fd662bc9c1b949e0259e1bcc379d1f006847b0080c7417" -"checksum lazy_static 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6abe0ee2e758cd6bc8a2cd56726359007748fbf4128da998b65d0b70f881e19b" -"checksum libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)" = "38f5c2b18a287cf78b4097db62e20f43cace381dc76ae5c0a3073067f78b7ddc" -"checksum log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ab83497bf8bf4ed2a74259c1c802351fcd67a65baa86394b6ba73c36f4838054" -"checksum matches 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "efd7622e3022e1a6eaa602c4cea8912254e5582c9c692e9167714182244801b1" -"checksum memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1dbccc0e46f1ea47b9f17e6d67c5a96bd27030519c519c9c91327e31275a47b4" -"checksum mime 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "9d69889cdc6336ed56b174514ce876c4c3dc564cc23dd872e7bca589bb2a36c8" -"checksum miniz-sys 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "28eaee17666671fa872e567547e8428e83308ebe5808cdf6a0e28397dbe2c726" +"checksum lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c8f31047daa365f19be14b47c29df4f7c3b581832407daabe6ae77397619237d" +"checksum libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)" = "f54263ad99207254cf58b5f701ecb432c717445ea2ee8af387334bdd1a03fdff" +"checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" +"checksum log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "89f010e843f2b1a31dbd316b3b8d443758bc634bed37aabade59c686d644e0a2" +"checksum matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "100aabe6b8ff4e4a7e32c1c13523379802df0772b82466207ac25b013f193376" +"checksum memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "796fba70e76612589ed2ce7f45282f5af869e0fdd7cc6199fa1aa1f1d591ba9d" +"checksum mime 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ba626b8a6de5da682e1caa06bdb42a335aee5a84db8e5046a3e8ab17ba0a3ae0" +"checksum miniz_oxide 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "aaa2d3ad070f428fffbd7d3ca2ea20bb0d8cffe9024405c44e1840bc1418b398" +"checksum miniz_oxide_c_api 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "92d98fdbd6145645828069b37ea92ca3de225e000d80702da25c20d3584b38a5" "checksum mozprofile 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1a17b8bbde1dc0fbf1c8b073192d7c6f89baa932173ece7c1447de5e9cc7cd7e" -"checksum mozrunner 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ff037ca681fa465d01c863f8b16d4a008997b35468059c06f1a4b828369600b" -"checksum mozversion 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9fb3a40135553611560d3eb4a49479beaf0c91c5a93f723338c5b0edddf08f26" +"checksum mozrunner 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0a221fca79c09a57df26353e91507fc385d61575527eec7569060e2811f46d86" +"checksum mozversion 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "597412c9031cfa14e823ace4aa80d0cc19596f2a65d5de960fdeb00ebe285861" "checksum msdos_time 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "65ba9d75bcea84e07812618fedf284a64776c2f2ea0cad6bca7f69739695a958" -"checksum num 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "98b15ba84e910ea7a1973bccd3df7b31ae282bf9d8bd2897779950c9b8303d40" -"checksum num-integer 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)" = "21e4df1098d1d797d27ef0c69c178c3fab64941559b290fcae198e0825c9c8b5" -"checksum num-iter 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)" = "f7d1891bd7b936f12349b7d1403761c8a0b85a18b148e9da4429d5d102c1a41e" -"checksum num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "e1cbfa3781f3fe73dc05321bed52a06d2d491eaa764c52335cf4399f046ece99" -"checksum num_cpus 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a225d1e2717567599c24f88e49f00856c6e825a12125181ee42c4257e3688d39" -"checksum percent-encoding 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "de154f638187706bde41d9b4738748933d64e6b37bdbffc0b47a97d16a6ae356" -"checksum podio 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e5422a1ee1bc57cc47ae717b0137314258138f38fd5f3cea083f43a9725383a0" -"checksum rand 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)" = "61efcbcd9fa8d8fbb07c84e34a8af18a1ff177b449689ad38a6e9457ecc7b2ae" -"checksum redox_syscall 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "8dd35cc9a8bdec562c757e3d43c1526b5c6d2653e23e2315065bc25556550753" -"checksum regex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4278c17d0f6d62dfef0ab00028feb45bd7d2102843f80763474eeb1be8a10c01" -"checksum regex-syntax 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9191b1f57603095f105d317e375d19b1c9c5c3185ea9633a99a6dcbed04457" -"checksum rust-ini 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "06d4e8b0b50e7e7f827d609fa9746e1cf6371a1fa15404a1a0a86152a801079f" -"checksum rustc-demangle 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3058a43ada2c2d0b92b3ae38007a2d0fa5e9db971be260e0171408a4ff471c95" -"checksum rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)" = "237546c689f20bb44980270c73c3b9edd0891c1be49cc1274406134a66d3957b" -"checksum rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "c5f5376ea5e30ce23c03eb77cbe4962b988deead10910c372b226388b594c084" -"checksum semver 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)" = "d4f410fedcf71af0345d7607d246e7ad15faaadd49d240ee3b24e5dc21a820ac" +"checksum num 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "4703ad64153382334aa8db57c637364c322d3372e097840c72000dabdcf6156e" +"checksum num-integer 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)" = "f8d26da319fb45674985c78f1d1caf99aa4941f785d384a2ae36d0740bc3e2fe" +"checksum num-iter 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)" = "4b226df12c5a59b63569dd57fafb926d91b385dfce33d8074a412411b689d593" +"checksum num-traits 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3c2bd9b9d21e48e956b763c9f37134dc62d9e95da6edb3f672cacb6caf3cd3" +"checksum num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c51a3322e4bca9d212ad9a158a02abc6934d005490c054a2778df73a70aa0a30" +"checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" +"checksum podio 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "780fb4b6698bbf9cf2444ea5d22411cef2953f0824b98f33cf454ec5615645bd" +"checksum rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)" = "15a732abf9d20f0ad8eeb6f909bf6868722d9a06e1e50802b6a70351f40b4eb1" +"checksum rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "eba5f8cb59cc50ed56be8880a5c7b496bfd9bd26394e176bc67884094145c2c5" +"checksum redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "0d92eecebad22b767915e4d529f89f28ee96dbbf5a4810d2b844373f136417fd" +"checksum regex 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "0a33e44e4f5dbeb5619910f68b874d85b01e15f86fa7bb0fbc41bbd148883a48" +"checksum regex-syntax 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d8337992c33b62cf49462a1ce4d0eedbb021f48de017e40ec307cca445df0ca9" +"checksum remove_dir_all 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b5d2f806b0fcdabd98acd380dc8daef485e22bcb7cddc811d1337967f2528cf5" +"checksum rust-ini 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8a654c5bda722c699be6b0fe4c0d90de218928da5b724c3e467fc48865c37263" +"checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" +"checksum safemem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e27a8b19b835f7aea908818e871f5cc3a5a186550c30773be987e155e8163d8f" "checksum semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a3186ec9e65071a2095434b1f5bb24838d4e8e130f584c790f6033c79943537" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" -"checksum slog 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bab9d589681f7d6b9ca4ed5cc861779a392bca7beaae2f69f2341617415a78dc" -"checksum slog-atomic 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d6f5a4e4908d6818fe553b6126ba5377801556ab885c65ebf960b722a6778864" -"checksum slog-extra 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "511581f4dd1dc90e4eca99b60be8a692d9c975e8757558aa774f16007d27492a" -"checksum slog-stdlog 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "56cc08f40c45e0ab41dcfde0a19a22c5b7176d3827fc7d078450ebfdc080a37c" -"checksum slog-stream 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3fac4af71007ddb7338f771e059a46051f18d1454d8ac556f234a0573e719daa" -"checksum slog-term 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cb53c0bae0745898fd5a7b75b1c389507333470ac4c645ae431890c0f828b6ca" -"checksum strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b4d15c810519a91cf877e7e36e63fe068815c678181439f2f29e2562147c3694" -"checksum tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "87974a6f5c1dfb344d733055601650059a3363de2a6104819293baff662132d6" -"checksum term_size 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2b6b55df3198cc93372e85dd2ed817f0e38ce8cc0f22eb32391bfad9c4bf209" -"checksum thread-id 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4437c97558c70d129e40629a5b385b3fb1ffac301e63941335e4d354081ec14a" -"checksum thread_local 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c85048c6260d17cf486ceae3282d9fb6b90be220bf5b28c400f5485ffc29f0c7" -"checksum time 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)" = "211b63c112206356ef1ff9b19355f43740fc3f85960c598a93d3a3d3ba7beade" +"checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550" +"checksum tempdir 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "f73eebdb68c14bcb24aef74ea96079830e7fa7b31a6106e42ea7ee887c1e134e" +"checksum term_size 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9e5b9a66db815dcfd2da92db471106457082577c3c278d4138ab3e3b4e189327" +"checksum textwrap 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c0b59b6b4b44d867f1370ef1bd91bfb262bf07bf0ae65c202ea2fbc16153b693" +"checksum thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "279ef31c19ededf577bfd12dfae728040a21f635b06a24cd670ff510edd38963" +"checksum time 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "a15375f1df02096fb3317256ce2cee6a1f42fc84ea5ad5fc8c421cfe40c73098" "checksum traitobject 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "efd1f82c56340fdf16f2a953d7bda4f8fdffba13d93b00844c25572110b26079" "checksum typeable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1410f6f91f21d1612654e7cc69193b0334f909dcf2c790c4826254fbb86f8887" -"checksum unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "13a5906ca2b98c799f4b1ab4557b76367ebd6ae5ef14930ec841c74aed5f3764" -"checksum unicode-bidi 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a6a2c4e3710edd365cd7e78383153ed739fa31af19f9172f72d3575060f5a43a" +"checksum ucd-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fd2be2d6639d0f8fe6cdda291ad456e23629558d466e2789d2c3e9892bda285d" +"checksum unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7f4765f83163b74f957c797ad9253caf97f103fb064d3999aea9568d09fc8a33" +"checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" "checksum unicode-normalization 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "51ccda9ef9efa3f7ef5d91e8f9b83bbe6955f9bf86aec89d5cce2c874625920f" -"checksum unicode-segmentation 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "18127285758f0e2c6cf325bb3f3d138a12fee27de4f23e146cd6a179f26c2cf3" +"checksum unicode-segmentation 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a8083c594e02b8ae1654ae26f0ade5158b119bd88ad0e8227a5d8fcd72407946" "checksum unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "bf3a113775714a22dcb774d8ea3655c53a32debae63a063acc00a91cc586245f" -"checksum unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1f2ae5ddb18e1c92664717616dd9549dde73f539f01bd7b77c2edb2446bdff91" -"checksum url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eeb819346883532a271eb626deb43c4a1bb4c4dd47c519bd78137c3e72a4fe27" +"checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" +"checksum url 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f808aadd8cfec6ef90e4a14eb46f24511824d1ac596b9682703c87056c8678b7" "checksum utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122" "checksum uuid 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)" = "78c590b5bd79ed10aad8fb75f078a59d8db445af6c743e55c4a53227fc01c13f" -"checksum vec_map 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "887b5b631c2ad01628bbbaa7dd4c869f80d3186688f8d0b6f58774fbe324988c" +"checksum version_check 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6b772017e347561807c1aa192438c5fd74242a670a6cffacc40f2defd1dc069d" "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" -"checksum webdriver 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b982fb5fe268cc124931035ca0c4b65d39e6d9c9fed319186b7d17493bf98984" +"checksum webdriver 0.35.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ed276b0ce328478121cac7d113901f3d8e3c9f854d3c9ba493b2f6ee211f619e" "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" +"checksum winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "04e3bd221fcbe8a271359c04f21a76db7d0c6028862d1bb5512d85e1e2eb5bb3" "checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" -"checksum winreg 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e63857fb213f619b4c4fff86b158285c76766aac7e7474967e92fb6dbbfeefe9" -"checksum zip 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)" = "c0deac03fc7d43abcf19f2c2db6bd9289f9ea3d31f350e26eb0ed8b4117983c1" +"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +"checksum winreg 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9338067aba07889a38beaad4dbb77fa2e62e87c423b770824b3bdf412874bd2c" +"checksum zip 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "10931e278527cea65682696481e6d840371d581079df529ebfee186e0eaad719" diff --git a/Cargo.toml b/Cargo.toml index 600d8323..8c4d1347 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "geckodriver" -version = "0.19.1" -authors = ["Mozilla "] +version = "0.20.0" description = "Proxy for using WebDriver clients to interact with Gecko-based browsers." keywords = ["webdriver", "w3c", "httpd", "mozilla", "firefox"] repository = "https://hg.mozilla.org/mozilla-central/file/tip/testing/geckodriver" @@ -13,20 +12,16 @@ publish = false chrono = "^0.2" clap = { version = "^2.19", default-features = false, features = ["suggestions", "wrap_help"] } hyper = "0.10" -lazy_static = "0.1" -log = "0.3" +lazy_static = "1.0" +log = { version = "0.4", features = ["std"] } mozprofile = "0.3.0" -mozrunner = "0.5.0" -mozversion = "0.1.2" +mozrunner = "0.6.0" +mozversion = "0.1.3" regex = "0.2" rustc-serialize = "0.3" -slog = "1" -slog-atomic = "0.4" -slog-stdlog = "1" -slog-stream = "1" uuid = "0.1.18" -webdriver = "0.32.0" -zip = "0.1" +webdriver = "0.35.0" +zip = "0.3" [[bin]] name = "geckodriver" diff --git a/README.md b/README.md index 4c41876b..6dac0b59 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ the [Testing :: GeckoDriver] component. [WebDriver protocol]: http://w3c.github.io/webdriver/webdriver-spec.html#protocol [Firefox remote protocol]: https://developer.mozilla.org/en-US/docs/Mozilla/QA/Marionette -[change log]: https://github.com/mozilla/geckodriver/blob/master/CHANGES.md +[change log]: https://searchfox.org/mozilla-central/source/testing/geckodriver/CHANGES.md [Releases]: https://github.com/mozilla/geckodriver/releases [supported platforms]: #supported-firefoxen [mozilla-central]: https://hg.mozilla.org/mozilla-central/ @@ -33,11 +33,11 @@ the [Testing :: GeckoDriver] component. Supported clients ================= -[Selenium] users must update to [version -3.5](https://github.com/SeleniumHQ/selenium/releases/tag/selenium-3.5.0) -or later to use geckodriver. Other clients that follow the [W3C WebDriver +[Selenium] users must update to [version 3.5] or later to +use geckodriver. Other clients that follow the [W3C WebDriver specification] are also supported. +[version 3.5]: https://github.com/SeleniumHQ/selenium/releases/tag/selenium-3.5.0 [W3C WebDriver specification]: https://w3c.github.io/webdriver/webdriver-spec.html @@ -90,6 +90,7 @@ geckodriver supports a number of [capabilities]: Boolean initially set to false, indicating the session will not implicitly trust untrusted or self-signed TLS certificates on navigation. + @@ -104,6 +105,7 @@ geckodriver supports a number of [capabilities]: waiting for the complete ready state; or "none", which will return immediately after starting navigation. + @@ -199,10 +201,13 @@ geckodriver supports a number of [capabilities]: Firefox capabilities ==================== -geckodriver also supports a capability named `moz:firefoxOptions` -which takes Firefox-specific options. -This must be a dictionary -and may contain any of the following fields: +geckodriver has a few capabilities that are specific to Firefox. + +moz:firefoxOptions +------------------ + +A dictionary used to define options which control how Firefox gets started +and run. It may contain any of the following fields: @@ -276,6 +281,46 @@ and may contain any of the following fields:
+moz:useNonSpecCompliantPointerOrigin +------------------------------------ + +A boolean value to indicate how the pointer origin for an action command +will be calculated. + +With Firefox 59 the calculation will be based on the requirements by the +[WebDriver] specification. This means that the pointer origin is no longer +computed based on the top and left position of the referenced element, but +on the in-view center point. + +To temporarily disable the WebDriver conformant behavior use `false` as value +for this capability. + +Please note that this capability exists only temporarily, and that it will be +removed once all Selenium bindings can handle the new behavior. + +moz:webdriverClick +------------------ + +A boolean value to indicate which kind of interactability checks to run +when performing a click or sending keys to an elements. For Firefoxen prior to +version 58.0 some legacy code as imported from an older version of +[FirefoxDriver] was in use. + +With Firefox 58 the interactability checks as required by the [WebDriver] +specification are enabled by default. This means geckodriver will additionally +check if an element is obscured by another when clicking, and if an element is +focusable for sending keys. + +Because of this change in behaviour, we are aware that some extra errors could +be returned. In most cases the test in question might have to be updated +so it's conform with the new checks. But if the problem is located in +geckodriver, then please raise an issue in the [issue tracker]. + +To temporarily disable the WebDriver conformant checks use `false` as value +for this capability. + +Please note that this capability exists only temporarily, and that it will be +removed once the interactability checks have been stabilized. `log` object ------------ @@ -493,11 +538,18 @@ the Windows registry. #### `--connect-existing` -Connecting to an existing Firefox instance. The instance must have -Marionette enabled. +Connect geckodriver to an existing Firefox instance. This means +geckodriver will abstain from the default of starting a new Firefox +session. -To enable the Marionette remote protocol you can pass the `--marionette` -flag to Firefox. +The existing Firefox instance must have [Marionette] enabled. +To enable the remote protocol in Firefox, you can pass the +`-marionette` flag. Unless the `marionette.port` preference +has been user-set, Marionette will listen on port 2828. So when +using `--connect-existing` it is likely you will also have to use +[`--marionette-port`] to set the correct port. + +[`--marionette-port`]: #marionette-port #### --host HOST @@ -513,23 +565,40 @@ Set the Gecko and geckodriver log level. Possible values are `fatal`, #### --marionette-port PORT -Port to use for connecting to the Marionette remote protocol. By default -it will pick a free port assigned by the system. +Selects the port for geckodriver’s connection to the [Marionette] +remote protocol. + +In the default mode where geckodriver starts and manages the Firefox +process, it will pick a free port assigned by the system and set the +`marionette.port` preference in the profile. + +When [`--connect-existing`] is used and the Firefox process is not +under geckodriver’s control, it will simply connect to PORT. + +[`--connect-existing`]: #connect-existing #### -p PORT/--port PORT Port to use for the WebDriver server. Defaults to 4444. -A helpful trick is that it is possible to bind to 0 to get the system -to atomically assign a free port. +A helpful trick is that it is possible to bind to 0 to get the +system to atomically assign a free port. + + +#### --jsdebugger + +Attach [browser toolbox] debugger when Firefox starts. This is +useful for debugging [Marionette] internals. + +[browser toolbox]: https://developer.mozilla.org/en-US/docs/Tools/Browser_Toolbox #### -v[v] -Increases the logging verbosity by to debug level when passing a single -`-v`, or to trace level if `-vv` is passed. This is analogous to passing -`--log debug` and `--log trace`, respectively. +Increases the logging verbosity by to debug level when passing +a single `-v`, or to trace level if `-vv` is passed. This is +analogous to passing `--log debug` and `--log trace`, respectively. Building @@ -548,18 +617,20 @@ ensure you put this in your [mozconfig]: ac_add_options --enable-geckodriver -The _geckodriver_ binary will appear in `${objdir}/dist/bin/geckodriver` -alongside _firefox-bin_. +You build geckodriver with the `./mach build testing/geckodriver` +command, run tests with `./mach test testing/geckodriver`, and run +the built executable with `./mach geckodriver -- --other --flags`. [Rust]: https://www.rust-lang.org/ [Mozilla]: https://www.mozilla.org/en-US/ -[webdriver crate]: https://github.com/mozilla/webdriver-rust -[commands]: https://docs.rs/webdriver/0.25.0/webdriver/command/index.html -[responses]: https://docs.rs/webdriver/0.25.0/webdriver/response/index.html -[errors]: https://docs.rs/webdriver/0.25.0/webdriver/error/enum.ErrorStatus.html -[Marionette protocol]: https://developer.mozilla.org/en-US/docs/Mozilla/QA/Marionette/Protocol +[webdriver crate]: https://crates.io/crates/webdriver +[commands]: https://docs.rs/webdriver/newest/webdriver/command/index.html +[responses]: https://docs.rs/webdriver/newest/webdriver/response/index.html +[errors]: https://docs.rs/webdriver/newest/webdriver/error/enum.ErrorStatus.html +[Marionette protocol]: https://firefox-source-docs.mozilla.org/testing/marionette/marionette/Protocol.html [WebDriver]: https://w3c.github.io/webdriver/webdriver-spec.html -[Marionette]: http://searchfox.org/mozilla-central/source/testing/marionette/README +[FirefoxDriver]: https://github.com/SeleniumHQ/selenium/wiki/FirefoxDriver +[Marionette]: https://firefox-source-docs.mozilla.org/testing/marionette/marionette/ [Firefox CI]: https://treeherder.mozilla.org/ [mozconfig]: https://developer.mozilla.org/en-US/docs/Mozilla/Developer_guide/Build_Instructions/Configuring_Build_Options @@ -574,4 +645,4 @@ There is also an IRC channel to talk about using and developing geckodriver in #ateam on irc.mozilla.org. [subscribe]: https://lists.mozilla.org/listinfo/tools-marionette -[archive]: http://groups.google.com/group/mozilla.tools.marionette +[archive]: https://groups.google.com/group/mozilla.tools.marionette diff --git a/doc/Releasing.md b/doc/Releasing.md index 755469b8..f1f3a51a 100644 --- a/doc/Releasing.md +++ b/doc/Releasing.md @@ -19,24 +19,34 @@ In any case, the steps to release geckodriver are as follows: [Mozilla’s CI infrastructure]: https://treeherder.mozilla.org/ -Release new webdriver crate ---------------------------- +Release new in-tree dependency crates +------------------------------------- -geckodriver depends on the [webdriver] crate, also hosted in -mozilla-central, by pointing to its in-tree relative path: +geckodriver depends on a number of Rust crates that also live in +central by using relative paths: - [dependencies] - webdriver = { path = "../webdriver" } + [dependencies] + … + mozprofile = { path = "../mozbase/rust/mozprofile" } + mozrunner = { path = "../mozbase/rust/mozrunner" } + mozversion = { path = "../mozbase/rust/mozversion" } + … + webdriver = { path = "../webdriver" } -Because we need to export the geckodriver source code to the old GitHub -repository in order to release, we need to publish any changes that -have been made to webdriver in the interim. If no changes have been -made, you can skip these steps: +Because we need to export the geckodriver source code to the old +GitHub repository when we release, we first need to publish these +crates if they have had any changes in the interim since the last +release. If they have receieved no changes, you can skip them: - 1. Bump the version number in testing/webdriver/Cargo.toml - 2. `cargo publish` + - `testing/mozbase/rust/mozprofile` + - `testing/mozbase/rust/mozrunner` + - `testing/mozbase/rust/mozversion` + - `testing/webdriver` + +For each crate: -[webdriver]: ../webdriver + 1. Bump the version number in Cargo.toml + 2. `cargo publish` Update the change log @@ -63,8 +73,7 @@ mention of this. Lines are optimally formatted at roughly 72 columns to make the file readable in a text editor as well as rendered HTML. fmt(1) does a splendid job at text formatting. -[CHANGES.md]: ../CHANGES.md -[webdriver]: ../../webdriver +[CHANGES.md]: https://searchfox.org/mozilla-central/source/testing/geckodriver/CHANGES.md [rust-mozrunner]: https://github.com/jgraham/rust_mozrunner @@ -77,15 +86,15 @@ Make relevant changes to [Cargo.toml] to upgrade dependencies, then run % ./mach build testing/geckodriver to pull down and vendor the upgraded libraries. Remember to check -in the [Cargo.lock] file, since unlike we want geckodriver builds to -be reproducible. +in the [Cargo.lock] file since we want reproducible builds for +geckodriver, uninfluenced by dependency variations. -Updating dependencies should always be made as a separate commit to -not confuse reviewers because vendoring involves checking in a lot -of extra code reviewed downstream. +The updates to dependencies should always be made as a separate +commit to not confuse reviewers, because vendoring involves checking +in a lot of extra code already reviewed downstream. -[Cargo.toml]: ../Cargo.toml -[Cargo.lock]: ../Cargo.lock +[Cargo.toml]: https://searchfox.org/mozilla-central/source/testing/geckodriver/Cargo.toml +[Cargo.lock]: https://searchfox.org/mozilla-central/source/testing/geckodriver/Cargo.lock Bump the version number @@ -122,39 +131,46 @@ of [testing/geckodriver] to the latter branch: % git rm -rf . % git clean -fxd % cp -r $SRC/gecko/testing/geckodriver/* . - % git add . - % git commit -am "import of vX.Y.Z" -[README]: ../README.md -[testing/geckodriver]: ../ +[README.md]: https://searchfox.org/mozilla-central/source/testing/geckodriver/README.md +[testing/geckodriver]: https://searchfox.org/mozilla-central/source/testing/geckodriver -Manually change `webdriver` dependency --------------------------------------- +Manually change in-tree path dependencies +------------------------------------------ -After the source code has been imported we need to change the -dependency information for the [webdriver] crate. As explained -previously geckodriver depends on a relative path in in the -mozilla-central repository to build with the latest unreleased -source code. +After the source code has been imported we need to change the dependency +information for the `mozrunner`, `mozprofile`, `mozversion`, and +`webdriver` crates. As explained previously geckodriver depends +on a relative path in in the mozilla-central repository to build +with the latest unreleased source code. -This relative path does not exist in the GitHub repository and the -build will fail unless we change it to the latest [webdriver] crate -version from crates.io. That version will either be the crate you -published earlier, or the latest version available if no changes have -been made to it since the last geckodriver release. +This relative paths do not exist in the GitHub repository and the +build will fail unless we change it to the latest crate versions +from crates.io. That version will either be the crate you published +earlier, or the latest version available if no changes have been +made to it since the last geckodriver release. -Tag the release ---------------- +Commit local changes +-------------------- -Run the following command: +Now commit all the changes you have made locally to the _release_ branch: - % git tag -a 'vX.Y.Z' + % git add . + % git commit -am "import of vX.Y.Z" + +As indicated above, the changes you make to this branch will not +be upstreamed back into mozilla-central. It is merely used as a +staging ground for pushing builds to Travis. + + +Tag the release +--------------- -Write the following in the annotation: +Run the following command to tag the release: - Tagging release vX.Y.Z + % git tag 'vX.Y.Z' Make the release diff --git a/doc/TraceLogs.md b/doc/TraceLogs.md index ff443165..787a6cb6 100644 --- a/doc/TraceLogs.md +++ b/doc/TraceLogs.md @@ -77,8 +77,8 @@ described in the [README] can hold Firefox-specific configuration, such as which Firefox binary to use, additional preferences to set, and of course which log level to use. -[`moz:firefoxOptions`]: ../README.md#firefox-capabilities -[README]: ../README.md +[`moz:firefoxOptions`]: https://searchfox.org/mozilla-central/source/testing/geckodriver/README.md#firefox-capabilities +[README]: https://searchfox.org/mozilla-central/source/testing/geckodriver/README.md Each client has its own way of specifying capabilities, and some clients include “helpers” for providing browser-specific configuration. diff --git a/doc/index.rst b/doc/index.rst index 5d687d6f..42b0730b 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -1,6 +1,15 @@ -============ -Geckodriver -============ +=========== +geckodriver +=========== + +geckodriver is a proxy for using W3C WebDriver-compatible clients +to interact with Gecko-based browsers. + +This program provides the HTTP API described by the WebDriver +protocol to communicate with Gecko browsers, such as Firefox. +It translates calls into the Marionette remote protocol by acting +as a proxy between the local- and remote ends. + For users ========= @@ -9,8 +18,9 @@ For users TraceLogs.md -For geckodriver developers -========================== + +For developers +============== .. toctree:: :maxdepth: 1 diff --git a/mach_commands.py b/mach_commands.py index 7867ae1f..a52412ee 100644 --- a/mach_commands.py +++ b/mach_commands.py @@ -1,43 +1,50 @@ +# 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/. + +from __future__ import absolute_import, print_function, unicode_literals + import argparse import os -from mozbuild.base import ( - MachCommandBase -) - from mach.decorators import ( + Command, CommandArgument, CommandArgumentGroup, CommandProvider, - Command, + SubCommand, +) + +from mozbuild.base import ( + MachCommandBase, + MachCommandConditions as conditions, ) @CommandProvider -class RunGeckodriver(MachCommandBase): - """Run the compiled program.""" - - @Command('geckodriver', category='post-build', - description='Run the geckodriver WebDriver implementation') - @CommandArgument('--binary', type=str, - help='Firefox binary (defaults to the local build).') - @CommandArgument('params', nargs='...', - help='Command-line arguments to be passed through to the program.') - - @CommandArgumentGroup('debugging') - @CommandArgument('--debug', action='store_true', group='debugging', - help='Enable the debugger. Not specifying a --debugger option will result in the default debugger being used.') - @CommandArgument('--debugger', default=None, type=str, group='debugging', - help='Name of debugger to use.') - @CommandArgument('--debugger-args', default=None, metavar='params', type=str, - group='debugging', - help='Command-line arguments to pass to the debugger itself; split as the Bourne shell would.') +class GeckoDriover(MachCommandBase): + + @Command("geckodriver", + category="post-build", + description="Run the WebDriver implementation for Gecko.") + @CommandArgument("--binary", type=str, + help="Firefox binary (defaults to the local build).") + @CommandArgument("params", nargs="...", + help="Flags to be passed through to geckodriver.") + @CommandArgumentGroup("debugging") + @CommandArgument("--debug", action="store_true", group="debugging", + help="Enable the debugger. Not specifying a --debugger option will result in the default debugger being used.") + @CommandArgument("--debugger", default=None, type=str, group="debugging", + help="Name of debugger to use.") + @CommandArgument("--debugger-args", default=None, metavar="params", type=str, + group="debugging", + help="Flags to pass to the debugger itself; split as the Bourne shell would.") def run(self, binary, params, debug, debugger, debugger_args): try: - binpath = self.get_binary_path('geckodriver') + binpath = self.get_binary_path("geckodriver") except Exception as e: print("It looks like geckodriver isn't built. " - "Add ac_add_options --enable-geckodrver to your mozconfig ", + "Add ac_add_options --enable-geckodriver to your mozconfig ", "and run |mach build| to build it.") print(e) return 1 @@ -48,12 +55,12 @@ def run(self, binary, params, debug, debugger, debugger_args): args.extend(params) if binary is None: - binary = self.get_binary_path('app') + binary = self.get_binary_path("app") args.extend(["--binary", binary]) if debug or debugger or debugger_args: - if 'INSIDE_EMACS' in os.environ: + if "INSIDE_EMACS" in os.environ: self.log_manager.terminal_handler.setLevel(logging.WARNING) import mozdebug @@ -84,3 +91,23 @@ def run(self, binary, params, debug, debugger, debugger_args): return self.run_process(args=args, ensure_exit_code=False, pass_thru=True) + + +@CommandProvider +class GeckoDriverTest(MachCommandBase): + + @Command("geckodriver-test", + category="post-build", + description="Run geckodriver unit tests.") + @CommandArgument("-v", "--verbose", action="store_true", + help="Verbose output for what commands the build is running.") + def test(self, verbose=False, **kwargs): + from mozbuild.controller.building import BuildDriver + + self.log_manager.enable_all_structured_loggers() + + driver = self._spawn(BuildDriver) + return driver.build( + what=["testing/geckodriver/check"], + verbose=verbose, + mach_context=self._mach_context) diff --git a/moz.build b/moz.build index 0df42f1f..277b6ae5 100644 --- a/moz.build +++ b/moz.build @@ -4,7 +4,14 @@ RUST_PROGRAMS += ["geckodriver"] +# https://bugzil.la/1425365 +if CONFIG["OS_ARCH"] != "WINNT": + RustTest("geckodriver") + with Files("**"): BUG_COMPONENT = ("Testing", "Marionette") SPHINX_TREES["geckodriver"] = "doc" + +with Files('doc/**'): + SCHEDULES.exclusive = ['docs'] diff --git a/src/capabilities.rs b/src/capabilities.rs index 9f70c4cd..c5adfcec 100644 --- a/src/capabilities.rs +++ b/src/capabilities.rs @@ -1,4 +1,4 @@ -use logging::LogLevel; +use logging::Level; use marionette::LogOptions; use mozprofile::preferences::Pref; use mozprofile::profile::Profile; @@ -159,13 +159,6 @@ impl<'a> BrowserCapabilities for FirefoxCapabilities<'a> { return Ok(()) } match name { - "moz:webdriverClick" => { - if !value.is_boolean() { - return Err(WebDriverError::new( - ErrorStatus::InvalidArgument, - "moz:webdriverClick is not a boolean")); - } - } "moz:firefoxOptions" => { let data = try_opt!(value.as_object(), ErrorStatus::InvalidArgument, @@ -207,11 +200,10 @@ impl<'a> BrowserCapabilities for FirefoxCapabilities<'a> { let level = try_opt!(log_value.as_string(), ErrorStatus::InvalidArgument, "log level is not a string"); - if LogLevel::from_str(level).is_err() { + if Level::from_str(level).is_err() { return Err(WebDriverError::new( ErrorStatus::InvalidArgument, - format!("{} is not a valid log level", - level))) + format!("Not a valid log level: {}", level))) } } x => return Err(WebDriverError::new( @@ -237,6 +229,20 @@ impl<'a> BrowserCapabilities for FirefoxCapabilities<'a> { } } } + "moz:useNonSpecCompliantPointerOrigin" => { + if !value.is_boolean() { + return Err(WebDriverError::new( + ErrorStatus::InvalidArgument, + "moz:useNonSpecCompliantPointerOrigin is not a boolean")); + } + } + "moz:webdriverClick" => { + if !value.is_boolean() { + return Err(WebDriverError::new( + ErrorStatus::InvalidArgument, + "moz:webdriverClick is not a boolean")); + } + } _ => return Err(WebDriverError::new(ErrorStatus::InvalidArgument, format!("Unrecognised option {}", name))) } @@ -335,25 +341,26 @@ impl FirefoxOptions { fn load_log(options: &Capabilities) -> WebDriverResult { if let Some(json) = options.get("log") { - let log = try!(json.as_object() - .ok_or(WebDriverError::new(ErrorStatus::InvalidArgument, - "Log section is not an object"))); + let log = json.as_object().ok_or(WebDriverError::new( + ErrorStatus::InvalidArgument, + "Log section is not an object", + ))?; let level = match log.get("level") { Some(json) => { - let s = try!(json.as_string() - .ok_or(WebDriverError::new(ErrorStatus::InvalidArgument, - "Log level is not a string"))); - Some(try!(LogLevel::from_str(s) - .ok() - .ok_or(WebDriverError::new(ErrorStatus::InvalidArgument, - "Log level is unknown")))) + let s = json.as_string().ok_or(WebDriverError::new( + ErrorStatus::InvalidArgument, + "Log level is not a string", + ))?; + Some(Level::from_str(s).ok().ok_or(WebDriverError::new( + ErrorStatus::InvalidArgument, + "Log level is unknown", + ))?) } None => None, }; - Ok(LogOptions { level: level }) - + Ok(LogOptions { level }) } else { Ok(Default::default()) } diff --git a/src/logging.rs b/src/logging.rs index a1c99a7b..d9efd9ff 100644 --- a/src/logging.rs +++ b/src/logging.rs @@ -1,158 +1,304 @@ +//! Gecko-esque logger implementation for the [`log`] crate. +//! +//! The [`log`] crate provides a single logging API that abstracts over the +//! actual logging implementation. This module uses the logging API +//! to provide a log implementation that shares many aesthetical traits with +//! [Log.jsm] from Gecko. +//! +//! Using the [`error!`], [`warn!`], [`info!`], [`debug!`], and +//! [`trace!`] macros from `log` will output a timestamp field, followed by the +//! log level, and then the message. The fields are separated by a tab +//! character, making the output suitable for further text processing with +//! `awk(1)`. +//! +//! This module shares the same API as `log`, except it provides additional +//! entry functions [`init`] and [`init_with_level`] and additional log levels +//! `Level::Fatal` and `Level::Config`. Converting these into the +//! [`log::Level`] is lossy so that `Level::Fatal` becomes `log::Level::Error` +//! and `Level::Config` becomes `log::Level::Debug`. +//! +//! [`log`]: https://docs.rs/log/newest/log/ +//! [Log.jsm]: https://developer.mozilla.org/en/docs/Mozilla/JavaScript_code_modules/Log.jsm +//! [`error!`]: https://docs.rs/log/newest/log/macro.error.html +//! [`warn!`]: https://docs.rs/log/newest/log/macro.warn.html +//! [`info!`]: https://docs.rs/log/newest/log/macro.info.html +//! [`debug!`]: https://docs.rs/log/newest/log/macro.debug.html +//! [`trace!`]: https://docs.rs/log/newest/log/macro.trace.html +//! [`init`]: fn.init.html +//! [`init_with_level`]: fn.init_with_level.html + +use chrono; +use log; use std::fmt; use std::io; -use std::str::FromStr; -use std::sync::atomic::AtomicBool; -use std::sync::atomic::Ordering::SeqCst; - -use chrono::{DateTime, Local}; -use slog; -use slog::DrainExt; -use slog_atomic::{AtomicSwitch, AtomicSwitchCtrl}; -use slog_stream::{stream, Format, Streamer}; -use slog::Level as SlogLevel; -use slog::{LevelFilter, Logger}; -use slog::{OwnedKeyValueList, Record}; -use slog_stdlog; - -lazy_static! { - static ref ATOMIC_DRAIN: AtomicSwitchCtrl = AtomicSwitch::new( - slog::Discard.map_err(|_| io::Error::new(io::ErrorKind::Other, "should not happen")) - ).ctrl(); - static ref FIRST_RUN: AtomicBool = AtomicBool::new(true); +use std::io::Write; +use std::str; +use std::sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT}; + +static MAX_LOG_LEVEL: AtomicUsize = ATOMIC_USIZE_INIT; +const LOGGED_TARGETS: &'static [&'static str] = &[ + "geckodriver", + "mozprofile", + "mozrunner", + "mozversion", + "webdriver", +]; + +/// Logger levels from [Log.jsm]. +/// +/// [Log.jsm]: https://developer.mozilla.org/en/docs/Mozilla/JavaScript_code_modules/Log.jsm +#[repr(usize)] +#[derive(Clone, Copy, Eq, Debug, Hash, PartialEq)] +pub enum Level { + Fatal = 70, + Error = 60, + Warn = 50, + Info = 40, + Config = 30, + Debug = 20, + Trace = 10, } -static DEFAULT_LEVEL: &'static LogLevel = &LogLevel::Info; - -/// Logger levels from [Log.jsm] -/// (https://developer.mozilla.org/en/docs/Mozilla/JavaScript_code_modules/Log.jsm). -#[derive(Debug, Clone)] -pub enum LogLevel { - Fatal, - Error, - Warn, - Info, - Config, - Debug, - Trace, +impl From for Level { + fn from(n: usize) -> Level { + use self::Level::*; + match n { + 70 => Fatal, + 60 => Error, + 50 => Warn, + 40 => Info, + 30 => Config, + 20 => Debug, + 10 => Trace, + _ => Info, + } + } } -impl fmt::Display for LogLevel { +impl fmt::Display for Level { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + use self::Level::*; let s = match *self { - LogLevel::Fatal => "FATAL", - LogLevel::Error => "ERROR", - LogLevel::Warn => "WARN", - LogLevel::Info => "INFO", - LogLevel::Config => "CONFIG", - LogLevel::Debug => "DEBUG", - LogLevel::Trace => "TRACE", + Fatal => "FATAL", + Error => "ERROR", + Warn => "WARN", + Info => "INFO", + Config => "CONFIG", + Debug => "DEBUG", + Trace => "TRACE", }; write!(f, "{}", s) } } -impl FromStr for LogLevel { +impl str::FromStr for Level { type Err = (); - fn from_str(s: &str) -> Result { - match s { - "fatal" => Ok(LogLevel::Fatal), - "error" => Ok(LogLevel::Error), - "warn" => Ok(LogLevel::Warn), - "info" => Ok(LogLevel::Info), - "config" => Ok(LogLevel::Config), - "debug" => Ok(LogLevel::Debug), - "trace" => Ok(LogLevel::Trace), + fn from_str(s: &str) -> Result { + use self::Level::*; + match s.to_lowercase().as_ref() { + "fatal" => Ok(Fatal), + "error" => Ok(Error), + "warn" => Ok(Warn), + "info" => Ok(Info), + "config" => Ok(Config), + "debug" => Ok(Debug), + "trace" => Ok(Trace), _ => Err(()), } } } -trait ToSlogLevel { - fn to_slog(&self) -> SlogLevel; +impl Into for Level { + fn into(self) -> log::Level { + use self::Level::*; + match self { + Fatal | Error => log::Level::Error, + Warn => log::Level::Warn, + Info => log::Level::Info, + Config | Debug => log::Level::Debug, + Trace => log::Level::Trace, + } + } } -impl ToSlogLevel for LogLevel { - fn to_slog(&self) -> SlogLevel { - match *self { - LogLevel::Fatal => SlogLevel::Critical, - LogLevel::Error => SlogLevel::Error, - LogLevel::Warn => SlogLevel::Warning, - LogLevel::Info => SlogLevel::Info, - LogLevel::Config | LogLevel::Debug => SlogLevel::Debug, - LogLevel::Trace => SlogLevel::Trace, +impl From for Level { + fn from(log_level: log::Level) -> Level { + use log::Level::*; + match log_level { + Error => Level::Error, + Warn => Level::Warn, + Info => Level::Info, + Debug => Level::Debug, + Trace => Level::Trace, } } } -trait ToGeckoLevel { - fn to_gecko(&self) -> LogLevel; -} +struct Logger; + +impl log::Log for Logger { + fn enabled(&self, meta: &log::Metadata) -> bool { + LOGGED_TARGETS.iter().any(|&x| meta.target().starts_with(x)) + && meta.level() <= log::max_level() + } -impl ToGeckoLevel for SlogLevel { - fn to_gecko(&self) -> LogLevel { - match *self { - SlogLevel::Critical => LogLevel::Fatal, - SlogLevel::Error => LogLevel::Error, - SlogLevel::Warning => LogLevel::Warn, - SlogLevel::Info => LogLevel::Info, - SlogLevel::Debug => LogLevel::Debug, - SlogLevel::Trace => LogLevel::Trace, + fn log(&self, record: &log::Record) { + if self.enabled(record.metadata()) { + let ts = format_ts(chrono::Local::now()); + println!( + "{}\t{}\t{}\t{}", + ts, + record.target(), + record.level(), + record.args() + ); } } -} -/// Initialise logger if it has not been already. The provided `level` -/// filters out log records below this granularity. -pub fn init(level: &Option) { - let effective_level = level.as_ref().unwrap_or(DEFAULT_LEVEL); + fn flush(&self) { + io::stdout().flush().unwrap(); + } +} - let drain = filtered_gecko_log(&effective_level); - ATOMIC_DRAIN.set(drain); +/// Initialises the logging subsystem with the default log level. +pub fn init() -> Result<(), log::SetLoggerError> { + init_with_level(Level::Info) +} - let first_run = FIRST_RUN.load(SeqCst); - FIRST_RUN.store(false, SeqCst); - if first_run { - let log = Logger::root(ATOMIC_DRAIN.drain().fuse(), o!()); - slog_stdlog::set_logger(log.clone()).unwrap(); - } +/// Initialises the logging subsystem. +pub fn init_with_level(level: Level) -> Result<(), log::SetLoggerError> { + let logger = Logger {}; + set_max_level(level); + log::set_boxed_logger(Box::new(logger))?; + Ok(()) } -fn filtered_gecko_log(level: &LogLevel) -> LevelFilter> { - let io = stream(io::stderr(), GeckoFormat {}); - slog::level_filter(level.to_slog(), io) +/// Returns the current maximum log level. +pub fn max_level() -> Level { + MAX_LOG_LEVEL.load(Ordering::Relaxed).into() } -struct GeckoFormat; - -impl Format for GeckoFormat { - fn format(&self, io: &mut io::Write, record: &Record, _: &OwnedKeyValueList) -> io::Result<()> { - // TODO(ato): Quite sure this is the wrong way to filter records with slog, - // but I do not comprehend how slog works. - let module = record.module(); - if module.starts_with("geckodriver") || module.starts_with("webdriver") || - module.starts_with("mozrunner") { - let ts = format_ts(Local::now()); - let level = record.level().to_gecko(); - let _ = try!(write!(io, "{}\t{}\t{}\t{}\n", ts, module, level, record.msg())); - } - Ok(()) - } +/// Sets the global maximum log level. +pub fn set_max_level(level: Level) { + MAX_LOG_LEVEL.store(level as usize, Ordering::SeqCst); + + let slevel: log::Level = level.into(); + log::set_max_level(slevel.to_level_filter()) } /// Produces a 13-digit Unix Epoch timestamp similar to Gecko. -fn format_ts(ts: DateTime) -> String { +fn format_ts(ts: chrono::DateTime) -> String { format!("{}{:03}", ts.timestamp(), ts.timestamp_subsec_millis()) } #[cfg(test)] mod tests { - use chrono::Local; - use super::format_ts; + use super::{format_ts, init_with_level, max_level, set_max_level, Level}; + use chrono; + use log; + use std::str::FromStr; + use std::sync::Mutex; + + lazy_static! { + static ref LEVEL_MUTEX: Mutex<()> = Mutex::new(()); + } + + #[test] + fn test_level_repr() { + assert_eq!(Level::Fatal as usize, 70); + assert_eq!(Level::Error as usize, 60); + assert_eq!(Level::Warn as usize, 50); + assert_eq!(Level::Info as usize, 40); + assert_eq!(Level::Config as usize, 30); + assert_eq!(Level::Debug as usize, 20); + assert_eq!(Level::Trace as usize, 10); + } + + #[test] + fn test_level_eq() { + assert_eq!(Level::Fatal, Level::Fatal); + assert_eq!(Level::Error, Level::Error); + assert_eq!(Level::Warn, Level::Warn); + assert_eq!(Level::Info, Level::Info); + assert_eq!(Level::Config, Level::Config); + assert_eq!(Level::Debug, Level::Debug); + assert_eq!(Level::Trace, Level::Trace); + } + + #[test] + fn test_level_from_log() { + assert_eq!(Level::from(log::Level::Error), Level::Error); + assert_eq!(Level::from(log::Level::Warn), Level::Warn); + assert_eq!(Level::from(log::Level::Info), Level::Info); + assert_eq!(Level::from(log::Level::Debug), Level::Debug); + assert_eq!(Level::from(log::Level::Trace), Level::Trace); + } + + #[test] + fn test_level_into_log() { + assert_eq!(Into::::into(Level::Fatal), log::Level::Error); + assert_eq!(Into::::into(Level::Error), log::Level::Error); + assert_eq!(Into::::into(Level::Warn), log::Level::Warn); + assert_eq!(Into::::into(Level::Info), log::Level::Info); + assert_eq!(Into::::into(Level::Config), log::Level::Debug); + assert_eq!(Into::::into(Level::Debug), log::Level::Debug); + assert_eq!(Into::::into(Level::Trace), log::Level::Trace); + } + + #[test] + fn test_level_from_str() { + assert_eq!(Level::from_str("fatal"), Ok(Level::Fatal)); + assert_eq!(Level::from_str("error"), Ok(Level::Error)); + assert_eq!(Level::from_str("warn"), Ok(Level::Warn)); + assert_eq!(Level::from_str("info"), Ok(Level::Info)); + assert_eq!(Level::from_str("config"), Ok(Level::Config)); + assert_eq!(Level::from_str("debug"), Ok(Level::Debug)); + assert_eq!(Level::from_str("trace"), Ok(Level::Trace)); + + assert_eq!(Level::from_str("INFO"), Ok(Level::Info)); + + assert!(Level::from_str("foo").is_err()); + } + + #[test] + fn test_level_to_str() { + assert_eq!(Level::Fatal.to_string(), "FATAL"); + assert_eq!(Level::Error.to_string(), "ERROR"); + assert_eq!(Level::Warn.to_string(), "WARN"); + assert_eq!(Level::Info.to_string(), "INFO"); + assert_eq!(Level::Config.to_string(), "CONFIG"); + assert_eq!(Level::Debug.to_string(), "DEBUG"); + assert_eq!(Level::Trace.to_string(), "TRACE"); + } + + #[test] + fn test_max_level() { + let _guard = LEVEL_MUTEX.lock(); + set_max_level(Level::Info); + assert_eq!(max_level(), Level::Info); + } + + #[test] + fn test_set_max_level() { + let _guard = LEVEL_MUTEX.lock(); + set_max_level(Level::Error); + assert_eq!(max_level(), Level::Error); + set_max_level(Level::Fatal); + assert_eq!(max_level(), Level::Fatal); + } + + #[test] + fn test_init_with_level() { + let _guard = LEVEL_MUTEX.lock(); + init_with_level(Level::Debug).unwrap(); + assert_eq!(max_level(), Level::Debug); + assert!(init_with_level(Level::Warn).is_err()); + } #[test] fn test_format_ts() { - let ts = Local::now(); + let ts = chrono::Local::now(); let s = format_ts(ts); assert_eq!(s.len(), 13); } diff --git a/src/main.rs b/src/main.rs index 49025354..18df569c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -9,11 +9,6 @@ extern crate mozrunner; extern crate mozversion; extern crate regex; extern crate rustc_serialize; -#[macro_use] -extern crate slog; -extern crate slog_atomic; -extern crate slog_stdlog; -extern crate slog_stream; extern crate uuid; extern crate zip; extern crate webdriver; @@ -43,7 +38,6 @@ mod prefs; mod marionette; mod capabilities; -use logging::LogLevel; use marionette::{MarionetteHandler, MarionetteSettings, extension_routes}; include!(concat!(env!("OUT_DIR"), "/build-info.rs")); @@ -123,6 +117,10 @@ fn app<'a, 'b>() -> App<'a, 'b> { .long("connect-existing") .requires("marionette_port") .help("Connect to an existing Firefox instance")) + .arg(Arg::with_name("jsdebugger") + .long("jsdebugger") + .takes_value(false) + .help("Attach browser toolbox debugger for Firefox")) .arg(Arg::with_name("verbosity") .short("v") .multiple(true) @@ -176,23 +174,27 @@ fn run() -> ProgramResult { }; let log_level = if matches.is_present("log_level") { - LogLevel::from_str(matches.value_of("log_level").unwrap()).ok() + logging::Level::from_str(matches.value_of("log_level").unwrap()).ok() } else { match matches.occurrences_of("verbosity") { - 0 => Some(LogLevel::Info), - 1 => Some(LogLevel::Debug), - _ => Some(LogLevel::Trace), + 0 => Some(logging::Level::Info), + 1 => Some(logging::Level::Debug), + _ => Some(logging::Level::Trace), } }; - logging::init(&log_level); + if let Some(ref level) = log_level { + logging::init_with_level(level.clone()).unwrap(); + } else { + logging::init().unwrap(); + } info!("geckodriver {}", BuildInfo); let settings = MarionetteSettings { port: marionette_port, - binary: binary, + binary, connect_existing: matches.is_present("connect_existing"), - log_level: log_level, + jsdebugger: matches.is_present("jsdebugger"), }; let handler = MarionetteHandler::new(settings); let listening = webdriver::server::start(addr, handler, &extension_routes()[..]) diff --git a/src/marionette.rs b/src/marionette.rs index fecf063f..b0536c2c 100644 --- a/src/marionette.rs +++ b/src/marionette.rs @@ -1,9 +1,7 @@ use hyper::method::Method; -use logging; -use logging::LogLevel; use mozprofile::preferences::Pref; use mozprofile::profile::Profile; -use mozrunner::runner::{Runner, FirefoxRunner}; +use mozrunner::runner::{FirefoxRunner, FirefoxProcess, Runner, RunnerProcess}; use regex::Captures; use rustc_serialize::base64::FromBase64; use rustc_serialize::json; @@ -19,8 +17,8 @@ use std::path::PathBuf; use std::io::Result as IoResult; use std::net::{TcpListener, TcpStream}; use std::sync::Mutex; -use std::thread::sleep; -use std::time::Duration; +use std::thread; +use std::time; use uuid::Uuid; use webdriver::capabilities::CapabilitiesMatching; use webdriver::command::{WebDriverCommand, WebDriverMessage, Parameters, @@ -53,6 +51,7 @@ use webdriver::server::{WebDriverHandler, Session}; use webdriver::httpapi::{WebDriverExtensionRoute}; use capabilities::{FirefoxCapabilities, FirefoxOptions}; +use logging; use prefs; const DEFAULT_HOST: &'static str = "localhost"; @@ -369,7 +368,7 @@ impl ToMarionette for AddonUninstallParameters { #[derive(Default)] pub struct LogOptions { - pub level: Option, + pub level: Option, } #[derive(Default)] @@ -378,26 +377,23 @@ pub struct MarionetteSettings { pub binary: Option, pub connect_existing: bool, - /// Optionally increase Marionette's verbosity by providing a log - /// level. The Gecko default is LogLevel::Info for optimised - /// builds and LogLevel::Debug for debug builds. - pub log_level: Option, + /// Brings up the Browser Toolbox when starting Firefox, + /// letting you debug internals. + pub jsdebugger: bool, } pub struct MarionetteHandler { connection: Mutex>, settings: MarionetteSettings, - browser: Option, - current_log_level: Option, + browser: Option, } impl MarionetteHandler { pub fn new(settings: MarionetteSettings) -> MarionetteHandler { MarionetteHandler { connection: Mutex::new(None), - settings: settings, + settings, browser: None, - current_log_level: None, } } @@ -419,8 +415,9 @@ impl MarionetteHandler { (options, capabilities) }; - self.current_log_level = options.log.level.clone().or(self.settings.log_level.clone()); - logging::init(&self.current_log_level); + if let Some(l) = options.log.level { + logging::set_max_level(l); + } let port = self.settings.port.unwrap_or(try!(get_free_port())); if !self.settings.connect_existing { @@ -434,45 +431,51 @@ impl MarionetteHandler { Ok(capabilities) } - fn start_browser(&mut self, port: u16, mut options: FirefoxOptions) -> WebDriverResult<()> { - let binary = try!(options.binary + fn start_browser(&mut self, port: u16, options: FirefoxOptions) -> WebDriverResult<()> { + let binary = options.binary .ok_or(WebDriverError::new(ErrorStatus::SessionNotCreated, "Expected browser binary location, but unable to find \ binary in default location, no \ 'moz:firefoxOptions.binary' capability provided, and \ - no binary flag set on the command line"))); + no binary flag set on the command line"))?; - let custom_profile = options.profile.is_some(); + let is_custom_profile = options.profile.is_some(); - let mut runner = try!(FirefoxRunner::new(&binary, options.profile.take()) - .map_err(|e| WebDriverError::new(ErrorStatus::SessionNotCreated, - e.description().to_owned()))); - - // double-dashed flags are not accepted on Windows systems - runner.args().push("-marionette".to_owned()); - - // https://developer.mozilla.org/docs/Environment_variables_affecting_crash_reporting - runner.envs().insert("MOZ_CRASHREPORTER".to_string(), "1".to_string()); - runner.envs().insert("MOZ_CRASHREPORTER_NO_REPORT".to_string(), "1".to_string()); - runner.envs().insert("MOZ_CRASHREPORTER_SHUTDOWN".to_string(), "1".to_string()); - - if let Some(args) = options.args.take() { - runner.args().extend(args); + let mut profile = match options.profile { + Some(x) => x, + None => Profile::new(None)? }; - try!(self.set_prefs(port, &mut runner.profile, custom_profile, options.prefs) + self.set_prefs(port, &mut profile, is_custom_profile, options.prefs) .map_err(|e| { WebDriverError::new(ErrorStatus::SessionNotCreated, format!("Failed to set preferences: {}", e)) - })); + })?; + + let mut runner = FirefoxRunner::new(&binary, profile); - try!(runner.start() + // https://developer.mozilla.org/docs/Environment_variables_affecting_crash_reporting + runner + .env("MOZ_CRASHREPORTER", "1") + .env("MOZ_CRASHREPORTER_NO_REPORT", "1") + .env("MOZ_CRASHREPORTER_SHUTDOWN", "1"); + + // double-dashed flags are not accepted on Windows systems + runner.arg("-marionette"); + if self.settings.jsdebugger { + runner.arg("-jsdebugger"); + } + if let Some(args) = options.args.as_ref() { + runner.args(args); + } + + let browser_proc = runner.start() .map_err(|e| { WebDriverError::new(ErrorStatus::SessionNotCreated, format!("Failed to start browser {}: {}", binary.display(), e)) - })); - self.browser = Some(runner); + })?; + self.browser = Some(browser_proc); Ok(()) } @@ -492,9 +495,15 @@ impl MarionetteHandler { prefs.insert_slice(&extra_prefs[..]); - if let Some(ref level) = self.current_log_level { - prefs.insert("marionette.log.level", Pref::new(level.to_string())); - }; + if self.settings.jsdebugger { + prefs.insert("devtools.browsertoolbox.panel", Pref::new("jsdebugger".to_owned())); + prefs.insert("devtools.debugger.remote-enabled", Pref::new(true)); + prefs.insert("devtools.chrome.enabled", Pref::new(true)); + prefs.insert("devtools.debugger.prompt-connection", Pref::new(false)); + prefs.insert("marionette.debugging.clicktostart", Pref::new(true)); + } + + prefs.insert("marionette.log.level", Pref::new(logging::max_level().to_string())); prefs.insert("marionette.port", Pref::new(port as i64)); prefs.write().map_err(|_| WebDriverError::new(ErrorStatus::UnknownError, @@ -558,7 +567,7 @@ impl WebDriverHandler for MarionetteHandler { // Shutdown the browser if no session can // be established due to errors. if let NewSession(_) = msg.command { - err.delete_session=true; + err.delete_session = true; } err}) }, @@ -573,18 +582,29 @@ impl WebDriverHandler for MarionetteHandler { } } - fn delete_session(&mut self, _: &Option) { - if let Ok(connection) = self.connection.lock() { - if let Some(ref conn) = *connection { + fn delete_session(&mut self, session: &Option) { + if let Some(ref s) = *session { + let delete_session = WebDriverMessage { + session_id: Some(s.id.clone()), + command: WebDriverCommand::DeleteSession, + }; + let _ = self.handle_command(session, delete_session); + } + + if let Ok(ref mut connection) = self.connection.lock() { + if let Some(conn) = connection.as_mut() { conn.close(); } } + if let Some(ref mut runner) = self.browser { - debug!("Stopping browser process"); - if runner.stop().is_err() { - error!("Failed to kill browser process"); - }; + // TODO(https://bugzil.la/1443922): + // Use toolkit.asyncshutdown.crash_timout pref + if runner.wait(time::Duration::from_secs(70)).is_err() { + error!("Failed to stop browser process"); + } } + self.connection = Mutex::new(None); self.browser = None; } @@ -939,10 +959,10 @@ impl MarionetteSession { let expiry = try!( Nullable::from_json(x.find("expiry").unwrap_or(&Json::Null), |x| { - Ok(Date::new((try_opt!( + Ok(Date::new(try_opt!( x.as_u64(), ErrorStatus::UnknownError, - "Cookie expiry must be a positive integer")))) + "Cookie expiry must be a positive integer"))) })); let secure = try_opt!( x.find("secure").map_or(Some(false), |x| x.as_boolean()), @@ -1295,54 +1315,59 @@ impl MarionetteConnection { MarionetteConnection { port: port, stream: None, - session: MarionetteSession::new(session_id) + session: MarionetteSession::new(session_id), } } - pub fn connect(&mut self, browser: &mut Option) -> WebDriverResult<()> { - let timeout = 60 * 1000; // ms - let poll_interval = 100; // ms + pub fn connect(&mut self, browser: &mut Option) -> WebDriverResult<()> { + let timeout = 60 * 1000; // ms + let poll_interval = 100; // ms let poll_attempts = timeout / poll_interval; let mut poll_attempt = 0; loop { - // If the process is gone, immediately abort the connection attempts + // immediately abort connection attempts if process disappears if let &mut Some(ref mut runner) = browser { - let status = runner.status(); - if status.is_err() || status.as_ref().map(|x| *x).unwrap_or(None) != None { + let exit_status = match runner.try_wait() { + Ok(Some(status)) => Some( + status + .code() + .map(|c| c.to_string()) + .unwrap_or("signal".into()), + ), + Ok(None) => None, + Err(_) => Some("{unknown}".into()), + }; + if let Some(s) = exit_status { return Err(WebDriverError::new( ErrorStatus::UnknownError, - format!("Process unexpectedly closed with status: {}", status - .ok() - .and_then(|x| x) - .and_then(|x| x.code()) - .map(|x| x.to_string()) - .unwrap_or("{unknown}".into())))); + format!("Process unexpectedly closed with status {}", s), + )); } } match TcpStream::connect(&(DEFAULT_HOST, self.port)) { Ok(stream) => { self.stream = Some(stream); - break - }, + break; + } Err(e) => { trace!(" connection attempt {}/{}", poll_attempt, poll_attempts); if poll_attempt <= poll_attempts { poll_attempt += 1; - sleep(Duration::from_millis(poll_interval)); + thread::sleep(time::Duration::from_millis(poll_interval)); } else { return Err(WebDriverError::new( - ErrorStatus::UnknownError, e.description().to_owned())); + ErrorStatus::UnknownError, + e.description().to_owned(), + )); } } } - }; + } debug!("Connected to Marionette on {}:{}", DEFAULT_HOST, self.port); - - try!(self.handshake()); - Ok(()) + self.handshake() } fn handshake(&mut self) -> WebDriverResult<()> { diff --git a/src/prefs.rs b/src/prefs.rs index edfe6c3e..d2dd0c2d 100644 --- a/src/prefs.rs +++ b/src/prefs.rs @@ -1,7 +1,17 @@ use mozprofile::preferences::Pref; +// ALL CHANGES TO THIS FILE MUST HAVE REVIEW FROM A GECKODRIVER PEER! +// +// The Marionette Python client is used out-of-tree with release +// channel builds of Firefox. Removing a preference from this file +// will cause regressions, so please be careful and get review from +// a Testing :: Marionette peer before you make any changes to this file. + lazy_static! { - pub static ref DEFAULT: [(&'static str, Pref); 81] = [ + pub static ref DEFAULT: [(&'static str, Pref); 80] = [ + // Make sure Shield doesn't hit the network. + ("app.normandy.api_url", Pref::new("")), + // Disable automatic downloading of new releases ("app.update.auto", Pref::new(false)), @@ -30,14 +40,6 @@ lazy_static! { // Implicitly accept license ("browser.EULA.override", Pref::new(true)), - // use about:blank as new tab page - ("browser.newtabpage.enabled", Pref::new(false)), - - // Assume the about:newtab pages intro panels have been shown - // to not depend on which test runs first and happens to open - // about:newtab - ("browser.newtabpage.introShown", Pref::new(true)), - // Never start the browser in offline mode ("browser.offline", Pref::new(false)), @@ -118,7 +120,7 @@ lazy_static! { // Do not show datareporting policy notifications which can // interfere with tests - ("datareporting.healthreport.about.reportUrl", Pref::new("http://%(server)s/dummy/abouthealthreport/")), + ("datareporting.healthreport.about.reportUrl", Pref::new("http://%(server)s/dummy/abouthealthreport/")), // removed in Firefox 59 ("datareporting.healthreport.documentServerURI", Pref::new("http://%(server)s/dummy/healthreport/")), ("datareporting.healthreport.logging.consoleEnabled", Pref::new(false)), ("datareporting.healthreport.service.enabled", Pref::new(false)), @@ -153,6 +155,7 @@ lazy_static! { ("extensions.installDistroAddons", Pref::new(false)), // Make sure Shield doesn't hit the network. + // Removed in Firefox 60. ("extensions.shield-recipe-client.api_url", Pref::new("")), ("extensions.showMismatchUI", Pref::new(false)),