Bug 1514247 - Upgrade u2f-hid-rs to 0.2.3 r=emilio,keeler
authorJ.C. Jones <jjones@mozilla.com>
Fri, 14 Dec 2018 19:40:03 +0000
changeset 450588 5dd52dc4e291a4e099f18dc718cb958f99b999eb
parent 450587 0331493c6965f5ee888729319903cebaf7b12062
child 450589 e7ae93be5f42ff04a5525aeda6d4309dec283768
push id35207
push useraciure@mozilla.com
push dateSat, 15 Dec 2018 02:27:37 +0000
treeherdermozilla-central@d8a944c012a7 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersemilio, keeler
bugs1514247
milestone66.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1514247 - Upgrade u2f-hid-rs to 0.2.3 r=emilio,keeler This patch moves u2f-hid-rs to 0.2.3 [1], which changes the dependency graph of u2f-hid-rs to not directly rely on the low-level core-foundation-sys library, as core-foundation has all the features u2f-hid-rs needs in 0.6.1+. This patch vendors core-foundation 0.6.3 and core-foundation-sys 0.6.2 as a consequence. [1] https://github.com/jcjones/u2f-hid-rs/releases/tag/v0.2.3 [2] https://github.com/jcjones/u2f-hid-rs/commit/d1d36d10442b0850f5ea9f5111a41b519fc5fee4 Differential Revision: https://phabricator.services.mozilla.com/D14569
Cargo.lock
dom/webauthn/u2f-hid-rs/.clippy.toml
dom/webauthn/u2f-hid-rs/.gitignore
dom/webauthn/u2f-hid-rs/.travis.yml
dom/webauthn/u2f-hid-rs/Cargo.toml
dom/webauthn/u2f-hid-rs/examples/main.rs
dom/webauthn/u2f-hid-rs/src/capi.rs
dom/webauthn/u2f-hid-rs/src/hidproto.rs
dom/webauthn/u2f-hid-rs/src/lib.rs
dom/webauthn/u2f-hid-rs/src/linux/device.rs
dom/webauthn/u2f-hid-rs/src/linux/hidraw.rs
dom/webauthn/u2f-hid-rs/src/linux/monitor.rs
dom/webauthn/u2f-hid-rs/src/macos/device.rs
dom/webauthn/u2f-hid-rs/src/macos/iokit.rs
dom/webauthn/u2f-hid-rs/src/macos/monitor.rs
dom/webauthn/u2f-hid-rs/src/macos/transaction.rs
dom/webauthn/u2f-hid-rs/src/manager.rs
dom/webauthn/u2f-hid-rs/src/statemachine.rs
dom/webauthn/u2f-hid-rs/src/u2fprotocol.rs
dom/webauthn/u2f-hid-rs/src/u2ftypes.rs
third_party/rust/core-foundation-sys/.cargo-checksum.json
third_party/rust/core-foundation-sys/Cargo.toml
third_party/rust/core-foundation-sys/src/attributed_string.rs
third_party/rust/core-foundation-sys/src/lib.rs
third_party/rust/core-foundation/.cargo-checksum.json
third_party/rust/core-foundation/Cargo.toml
third_party/rust/core-foundation/src/array.rs
third_party/rust/core-foundation/src/attributed_string.rs
third_party/rust/core-foundation/src/base.rs
third_party/rust/core-foundation/src/bundle.rs
third_party/rust/core-foundation/src/dictionary.rs
third_party/rust/core-foundation/src/lib.rs
third_party/rust/core-foundation/src/number.rs
third_party/rust/core-foundation/src/string.rs
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -400,45 +400,45 @@ name = "cookie"
 version = "0.11.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "core-foundation"
-version = "0.6.0"
+version = "0.6.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "core-foundation-sys 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "core-foundation-sys"
-version = "0.6.0"
+version = "0.6.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "core-graphics"
 version = "0.17.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "core-foundation 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "core-foundation 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "foreign-types 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "core-text"
 version = "13.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "core-foundation 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "core-foundation 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "core-graphics 0.17.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "foreign-types 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "cose"
 version = "0.1.4"
@@ -1053,17 +1053,17 @@ dependencies = [
  "netwerk_helper 0.0.1",
  "nserror 0.1.0",
  "nsstring 0.1.0",
  "prefs_parser 0.0.1",
  "profiler_helper 0.1.0",
  "rkv 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "rsdparsa_capi 0.1.0",
  "rustc_version 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "u2fhid 0.2.2",
+ "u2fhid 0.2.3",
  "webrender_bindings 0.1.0",
  "xpcom 0.1.0",
 ]
 
 [[package]]
 name = "gl_generator"
 version = "0.10.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2759,22 +2759,21 @@ source = "registry+https://github.com/ru
 
 [[package]]
 name = "typenum"
 version = "1.10.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "u2fhid"
-version = "0.2.2"
+version = "0.2.3"
 dependencies = [
  "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "boxfnonce 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "core-foundation 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "core-foundation-sys 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "core-foundation 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "devd-rs 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
  "libudev 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)",
  "runloop 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.3.6 (git+https://github.com/froydnj/winapi-rs?branch=aarch64)",
 ]
@@ -2925,17 +2924,17 @@ dependencies = [
 name = "webrender"
 version = "0.57.2"
 dependencies = [
  "app_units 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "bincode 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "core-foundation 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "core-foundation 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "core-graphics 0.17.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "core-text 13.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "dwrote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "freetype 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "gleam 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2954,33 +2953,33 @@ dependencies = [
 [[package]]
 name = "webrender_api"
 version = "0.57.2"
 dependencies = [
  "app_units 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "bincode 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "core-foundation 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "core-foundation 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "core-graphics 0.17.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "dwrote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "euclid 0.19.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_bytes 0.10.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 1.0.80 (git+https://github.com/servo/serde?branch=deserialize_from_enums9)",
  "time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "webrender_bindings"
 version = "0.1.0"
 dependencies = [
  "app_units 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "bincode 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "core-foundation 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "core-foundation 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "core-graphics 0.17.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "dwrote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "euclid 0.19.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "foreign-types 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "gleam 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "nsstring 0.1.0",
@@ -3141,18 +3140,18 @@ dependencies = [
 "checksum cexpr 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8fc0086be9ca82f7fc89fc873435531cb898b86e850005850de1f820e2db6e9b"
 "checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de"
 "checksum chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "45912881121cb26fad7c38c17ba7daa18764771836b34fab7d3fbd93ed633878"
 "checksum clang-sys 0.26.1 (registry+https://github.com/rust-lang/crates.io-index)" = "481e42017c1416b1c0856ece45658ecbb7c93d8a93455f7e5fa77f3b35455557"
 "checksum clap 2.31.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f0f16b89cbb9ee36d87483dc939fe9f1e13c05898d56d7b230a0d4dff033a536"
 "checksum cmake 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)" = "56d741ea7a69e577f6d06b36b7dff4738f680593dc27a701ffa8506b73ce28bb"
 "checksum constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8ff012e225ce166d4422e0e78419d901719760f62ae2b7969ca6b564d1b54a9e"
 "checksum cookie 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1465f8134efa296b4c19db34d909637cb2bf0f7aaf21299e23e18fa29ac557cf"
-"checksum core-foundation 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c7caa6cb9e76ddddbea09a03266d6b3bc98cd41e9fb9b017c473e7cca593ec25"
-"checksum core-foundation-sys 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b2a53cce0ddcf7e7e1f998738d757d5a3bf08bf799a180e50ebe50d298f52f5a"
+"checksum core-foundation 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4e2640d6d0bf22e82bed1b73c6aef8d5dd31e5abe6666c57e6d45e2649f4f887"
+"checksum core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e7ca8a5221364ef15ce201e8ed2f609fc312682a8f4e0e3d4aa5879764e0fa3b"
 "checksum core-graphics 0.17.1 (registry+https://github.com/rust-lang/crates.io-index)" = "62ceafe1622ffc9a332199096841d0ff9912ec8cf8f9cde01e254a7d5217cd10"
 "checksum core-text 13.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f3f46450d6f2397261af420b4ccce23807add2e45fa206410a03d66fb7f050ae"
 "checksum cose 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "72fa26cb151d3ae4b70f63d67d0fed57ce04220feafafbae7f503bef7aae590d"
 "checksum cose-c 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "49726015ab0ca765144fcca61e4a7a543a16b795a777fa53f554da2fffff9a94"
 "checksum cranelift-bforest 0.25.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b2d527b241af388ff017d72f2b0b323929a70cf97342c6ec1534e3b0f4dfaa0"
 "checksum cranelift-codegen 0.25.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e92fa0fa287cf00a6739c46aba114957e0a8eeeb4f0d1aa65d6ed0699c34ca6b"
 "checksum cranelift-codegen-meta 0.25.0 (registry+https://github.com/rust-lang/crates.io-index)" = "963262697a05d9aa63ca40f4670a7243e4525f4a098e10d654c3f5143fcef686"
 "checksum cranelift-entity 0.25.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc9a0329208e5e0d7d4d6e64cd50985d4c4cbfdbeeb594ae2157a094b98e8dcc"
new file mode 100644
--- /dev/null
+++ b/dom/webauthn/u2f-hid-rs/.clippy.toml
@@ -0,0 +1,1 @@
+type-complexity-threshold = 384
\ No newline at end of file
--- a/dom/webauthn/u2f-hid-rs/.gitignore
+++ b/dom/webauthn/u2f-hid-rs/.gitignore
@@ -1,10 +1,13 @@
 # Generated by Cargo
 # will have compiled files and executables
 /target/
 **/*.rs.bk
 
+# Fuzzing corpuses should be explicitly updated
+fuzz/corpus/
+
 # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
 # More information here http://doc.crates.io/guide.html#cargotoml-vs-cargolock
 Cargo.lock
 
 .DS_Store
--- a/dom/webauthn/u2f-hid-rs/.travis.yml
+++ b/dom/webauthn/u2f-hid-rs/.travis.yml
@@ -18,19 +18,23 @@ addons:
 
 before_install:
   - pkg-config --list-all
   - pkg-config --libs libudev
   - pkg-config --modversion libudev
 
 install:
   - rustup install nightly
-  - rustup component add --toolchain nightly rustfmt-preview
+  - rustup component add rustfmt-preview
+  - rustup component add clippy-preview
 
 script:
 - |
   if [ "$TRAVIS_RUST_VERSION" == "nightly" ] ; then
     export ASAN_OPTIONS="detect_odr_violation=1:leak_check_at_exit=0:detect_leaks=0"
     export RUSTFLAGS="-Z sanitizer=address"
   fi
-- cargo +nightly fmt --all -- --check
-- cargo build
+- |
+  if [ "$TRAVIS_RUST_VERSION" == "stable" ] ; then
+    cargo fmt --all -- --check
+    cargo clippy --all-targets -- -A renamed_and_removed_lints -A new-ret-no-self -D warnings
+  fi
 - cargo test
--- a/dom/webauthn/u2f-hid-rs/Cargo.toml
+++ b/dom/webauthn/u2f-hid-rs/Cargo.toml
@@ -1,22 +1,21 @@
 [package]
 name = "u2fhid"
-version = "0.2.2"
+version = "0.2.3"
 authors = ["Kyle Machulis <kyle@nonpolynomial.com>", "J.C. Jones <jc@mozilla.com>", "Tim Taubert <ttaubert@mozilla.com>"]
 
 [target.'cfg(target_os = "linux")'.dependencies]
 libudev = "^0.2"
 
 [target.'cfg(target_os = "freebsd")'.dependencies]
 devd-rs = "0.2.1"
 
 [target.'cfg(target_os = "macos")'.dependencies]
-core-foundation-sys = "0.6.0"
-core-foundation = "0.6.0"
+core-foundation = "0.6.2"
 
 [target.'cfg(target_os = "windows")'.dependencies.winapi]
 version = "0.3"
 features = [
     "handleapi",
     "hidclass",
     "hidpi",
     "hidusage",
--- a/dom/webauthn/u2f-hid-rs/examples/main.rs
+++ b/dom/webauthn/u2f-hid-rs/examples/main.rs
@@ -19,39 +19,41 @@ macro_rules! try_or {
             Ok(v) => v,
             Err(e) => {
                 return $or(e);
             }
         }
     };
 }
 
-fn u2f_get_key_handle_from_register_response(register_response: &Vec<u8>) -> io::Result<Vec<u8>> {
+fn u2f_get_key_handle_from_register_response(register_response: &[u8]) -> io::Result<Vec<u8>> {
     if register_response[0] != 0x05 {
         return Err(io::Error::new(
             io::ErrorKind::InvalidData,
             "Reserved byte not set correctly",
         ));
     }
 
     let key_handle_len = register_response[66] as usize;
-    let mut public_key = register_response.clone();
+    let mut public_key = register_response.to_owned();
     let mut key_handle = public_key.split_off(67);
     let _attestation = key_handle.split_off(key_handle_len);
 
     Ok(key_handle)
 }
 
 fn main() {
     env_logger::init();
 
     println!("Asking a security key to register now...");
-    let challenge_str = format!("{}{}",
+    let challenge_str = format!(
+        "{}{}",
         r#"{"challenge": "1vQ9mxionq0ngCnjD-wTsv1zUSrGRtFqG2xP09SbZ70","#,
-        r#" "version": "U2F_V2", "appId": "http://demo.yubico.com"}"#);
+        r#" "version": "U2F_V2", "appId": "http://demo.yubico.com"}"#
+    );
     let mut challenge = Sha256::default();
     challenge.input(challenge_str.as_bytes());
     let chall_bytes = challenge.result().to_vec();
 
     let mut application = Sha256::default();
     application.input(b"http://demo.yubico.com");
     let app_bytes = application.result().to_vec();
 
--- a/dom/webauthn/u2f-hid-rs/src/capi.rs
+++ b/dom/webauthn/u2f-hid-rs/src/capi.rs
@@ -99,17 +99,17 @@ pub unsafe extern "C" fn rust_u2f_result
     if res.is_null() {
         return ::Error::Unknown as u8;
     }
 
     if let U2FResult::Error(ref err) = *res {
         return *err as u8;
     }
 
-    return 0; /* No error, the request succeeded. */
+    0 /* No error, the request succeeded. */
 }
 
 #[no_mangle]
 pub unsafe extern "C" fn rust_u2f_resbuf_length(
     res: *const U2FResult,
     bid: u8,
     len: *mut size_t,
 ) -> bool {
@@ -224,17 +224,17 @@ pub unsafe extern "C" fn rust_u2f_mgr_si
     }
 
     // Check buffers.
     if challenge_ptr.is_null() {
         return 0;
     }
 
     // Need at least one app_id.
-    if (*app_ids).len() < 1 {
+    if (*app_ids).is_empty() {
         return 0;
     }
 
     let flags = ::SignFlags::from_bits_truncate(flags);
     let challenge = from_raw(challenge_ptr, challenge_len);
     let app_ids = (*app_ids).clone();
     let key_handles = (*khs).clone();
 
--- a/dom/webauthn/u2f-hid-rs/src/hidproto.rs
+++ b/dom/webauthn/u2f-hid-rs/src/hidproto.rs
@@ -1,28 +1,30 @@
 /* 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/. */
 
 // Shared code for platforms that use raw HID access (Linux, FreeBSD, etc.)
 
+#![cfg_attr(feature = "cargo-clippy", allow(cast_lossless, needless_lifetimes))]
+
 use std::mem;
 
 use consts::{FIDO_USAGE_PAGE, FIDO_USAGE_U2FHID};
 
 // The 4 MSBs (the tag) are set when it's a long item.
-const HID_MASK_LONG_ITEM_TAG: u8 = 0b11110000;
+const HID_MASK_LONG_ITEM_TAG: u8 = 0b1111_0000;
 // The 2 LSBs denote the size of a short item.
-const HID_MASK_SHORT_ITEM_SIZE: u8 = 0b00000011;
+const HID_MASK_SHORT_ITEM_SIZE: u8 = 0b0000_0011;
 // The 6 MSBs denote the tag (4) and type (2).
-const HID_MASK_ITEM_TAGTYPE: u8 = 0b11111100;
+const HID_MASK_ITEM_TAGTYPE: u8 = 0b1111_1100;
 // tag=0000, type=10 (local)
-const HID_ITEM_TAGTYPE_USAGE: u8 = 0b00001000;
+const HID_ITEM_TAGTYPE_USAGE: u8 = 0b0000_1000;
 // tag=0000, type=01 (global)
-const HID_ITEM_TAGTYPE_USAGE_PAGE: u8 = 0b00000100;
+const HID_ITEM_TAGTYPE_USAGE_PAGE: u8 = 0b0000_0100;
 
 pub struct ReportDescriptor {
     pub value: Vec<u8>,
 }
 
 impl ReportDescriptor {
     fn iter(self) -> ReportDescriptorIterator {
         ReportDescriptorIterator::new(self)
@@ -123,36 +125,39 @@ fn get_hid_short_item<'a>(buf: &'a [u8])
     // Ensure that there are enough bytes left in the buffer.
     if len > buf.len() - 1 {
         return None;
     }
 
     Some((
         buf[0] & HID_MASK_ITEM_TAGTYPE,
         1, /* key length */
-        &buf[1..1 + len],
+        &buf[1..=len],
     ))
 }
 
 fn read_uint_le(buf: &[u8]) -> u32 {
     assert!(buf.len() <= 4);
     // Parse the number in little endian byte order.
-    buf.iter().rev().fold(0, |num, b| (num << 8) | (*b as u32))
+    buf.iter()
+        .rev()
+        .fold(0, |num, b| (num << 8) | (u32::from(*b)))
 }
 
 pub fn has_fido_usage(desc: ReportDescriptor) -> bool {
     let mut usage_page = None;
     let mut usage = None;
 
     for data in desc.iter() {
         match data {
             Data::UsagePage { data } => usage_page = Some(data),
             Data::Usage { data } => usage = Some(data),
         }
 
         // Check the values we found.
         if let (Some(usage_page), Some(usage)) = (usage_page, usage) {
-            return usage_page == FIDO_USAGE_PAGE as u32 && usage == FIDO_USAGE_U2FHID as u32;
+            return usage_page == u32::from(FIDO_USAGE_PAGE)
+                && usage == u32::from(FIDO_USAGE_U2FHID);
         }
     }
 
     false
 }
--- a/dom/webauthn/u2f-hid-rs/src/lib.rs
+++ b/dom/webauthn/u2f-hid-rs/src/lib.rs
@@ -18,19 +18,16 @@ pub mod platform;
 #[cfg(any(target_os = "freebsd"))]
 extern crate devd_rs;
 
 #[cfg(any(target_os = "freebsd"))]
 #[path = "freebsd/mod.rs"]
 pub mod platform;
 
 #[cfg(any(target_os = "macos"))]
-extern crate core_foundation_sys;
-
-#[cfg(any(target_os = "macos"))]
 extern crate core_foundation;
 
 #[cfg(any(target_os = "macos"))]
 #[path = "macos/mod.rs"]
 pub mod platform;
 
 #[cfg(any(target_os = "windows"))]
 #[path = "windows/mod.rs"]
--- a/dom/webauthn/u2f-hid-rs/src/linux/device.rs
+++ b/dom/webauthn/u2f-hid-rs/src/linux/device.rs
@@ -68,16 +68,16 @@ impl Write for Device {
 
     // USB HID writes don't buffer, so this will be a nop.
     fn flush(&mut self) -> io::Result<()> {
         Ok(())
     }
 }
 
 impl U2FDevice for Device {
-    fn get_cid<'a>(&'a self) -> &'a [u8; 4] {
+    fn get_cid(&self) -> &[u8; 4] {
         &self.cid
     }
 
     fn set_cid(&mut self, cid: [u8; 4]) {
         self.cid = cid;
     }
 }
--- a/dom/webauthn/u2f-hid-rs/src/linux/hidraw.rs
+++ b/dom/webauthn/u2f-hid-rs/src/linux/hidraw.rs
@@ -1,11 +1,12 @@
 /* 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/. */
+#![cfg_attr(feature = "cargo-clippy", allow(cast_lossless))]
 
 extern crate libc;
 
 use std::io;
 use std::mem;
 use std::os::unix::io::RawFd;
 
 use hidproto::*;
--- a/dom/webauthn/u2f-hid-rs/src/linux/monitor.rs
+++ b/dom/webauthn/u2f-hid-rs/src/linux/monitor.rs
@@ -7,17 +7,17 @@ use libudev;
 use libudev::EventType;
 use runloop::RunLoop;
 use std::collections::HashMap;
 use std::ffi::OsString;
 use std::io;
 use std::os::unix::io::AsRawFd;
 use std::sync::Arc;
 
-const UDEV_SUBSYSTEM: &'static str = "hidraw";
+const UDEV_SUBSYSTEM: &str = "hidraw";
 const POLLIN: c_short = 0x0001;
 const POLL_TIMEOUT: c_int = 100;
 
 fn poll(fds: &mut Vec<::libc::pollfd>) -> io::Result<()> {
     let nfds = fds.len() as c_ulong;
 
     let rv = unsafe { ::libc::poll((&mut fds[..]).as_mut_ptr(), nfds, POLL_TIMEOUT) };
 
@@ -71,38 +71,38 @@ where
             revents: 0,
         }];
 
         while alive() {
             // Wait for new events, break on failure.
             poll(&mut fds)?;
 
             if let Some(event) = socket.receive_event() {
-                self.process_event(event);
+                self.process_event(&event);
             }
         }
 
         // Remove all tracked devices.
         self.remove_all_devices();
 
         Ok(())
     }
 
-    fn process_event(&mut self, event: libudev::Event) {
+    fn process_event(&mut self, event: &libudev::Event) {
         let path = event
             .device()
             .devnode()
             .map(|dn| dn.to_owned().into_os_string());
 
         match (event.event_type(), path) {
             (EventType::Add, Some(path)) => {
                 self.add_device(path);
             }
             (EventType::Remove, Some(path)) => {
-                self.remove_device(path);
+                self.remove_device(&path);
             }
             _ => { /* ignore other types and failures */ }
         }
     }
 
     fn add_device(&mut self, path: OsString) {
         let f = self.new_device_cb.clone();
         let key = path.clone();
@@ -113,21 +113,21 @@ where
             }
         });
 
         if let Ok(runloop) = runloop {
             self.runloops.insert(key, runloop);
         }
     }
 
-    fn remove_device(&mut self, path: OsString) {
-        if let Some(runloop) = self.runloops.remove(&path) {
+    fn remove_device(&mut self, path: &OsString) {
+        if let Some(runloop) = self.runloops.remove(path) {
             runloop.cancel();
         }
     }
 
     fn remove_all_devices(&mut self) {
         while !self.runloops.is_empty() {
             let path = self.runloops.keys().next().unwrap().clone();
-            self.remove_device(path);
+            self.remove_device(&path);
         }
     }
 }
--- a/dom/webauthn/u2f-hid-rs/src/macos/device.rs
+++ b/dom/webauthn/u2f-hid-rs/src/macos/device.rs
@@ -1,16 +1,16 @@
 /* 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/. */
 
 extern crate log;
 
 use consts::{CID_BROADCAST, HID_RPT_SIZE};
-use core_foundation_sys::base::*;
+use core_foundation::base::*;
 use platform::iokit::*;
 use std::io;
 use std::io::{Read, Write};
 use std::sync::mpsc::{Receiver, RecvTimeoutError};
 use std::time::Duration;
 use u2ftypes::U2FDevice;
 
 const READ_TIMEOUT: u64 = 15;
@@ -57,17 +57,17 @@ impl Read for Device {
         bytes.write(&data)
     }
 }
 
 impl Write for Device {
     fn write(&mut self, bytes: &[u8]) -> io::Result<usize> {
         assert_eq!(bytes.len(), HID_RPT_SIZE + 1);
 
-        let report_id = bytes[0] as i64;
+        let report_id = i64::from(bytes[0]);
         // Skip report number when not using numbered reports.
         let start = if report_id == 0x0 { 1 } else { 0 };
         let data = &bytes[start..];
 
         let result = unsafe {
             IOHIDDeviceSetReport(
                 self.device_ref,
                 kIOHIDReportTypeOutput,
--- a/dom/webauthn/u2f-hid-rs/src/macos/iokit.rs
+++ b/dom/webauthn/u2f-hid-rs/src/macos/iokit.rs
@@ -1,25 +1,23 @@
 /* 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/. */
 
 #![allow(non_snake_case, non_camel_case_types, non_upper_case_globals)]
 
-extern crate core_foundation_sys;
 extern crate libc;
 
 use consts::{FIDO_USAGE_PAGE, FIDO_USAGE_U2FHID};
+use core_foundation::array::*;
+use core_foundation::base::*;
 use core_foundation::dictionary::*;
 use core_foundation::number::*;
+use core_foundation::runloop::*;
 use core_foundation::string::*;
-use core_foundation_sys::base::*;
-use core_foundation_sys::dictionary::*;
-use core_foundation_sys::runloop::*;
-use core_foundation_sys::string::*;
 use std::ops::Deref;
 use std::os::raw::c_void;
 
 type IOOptionBits = u32;
 
 pub type IOReturn = libc::c_int;
 
 pub type IOHIDManagerRef = *mut __IOHIDManager;
@@ -157,21 +155,21 @@ pub struct IOHIDDeviceMatcher {
     pub dict: CFDictionary<CFString, CFNumber>,
 }
 
 impl IOHIDDeviceMatcher {
     pub fn new() -> Self {
         let dict = CFDictionary::<CFString, CFNumber>::from_CFType_pairs(&[
             (
                 CFString::from_static_string("DeviceUsage"),
-                CFNumber::from(FIDO_USAGE_U2FHID as i32),
+                CFNumber::from(i32::from(FIDO_USAGE_U2FHID)),
             ),
             (
                 CFString::from_static_string("DeviceUsagePage"),
-                CFNumber::from(FIDO_USAGE_PAGE as i32),
+                CFNumber::from(i32::from(FIDO_USAGE_PAGE)),
             ),
         ]);
         Self { dict }
     }
 }
 
 #[link(name = "IOKit", kind = "framework")]
 extern "C" {
--- a/dom/webauthn/u2f-hid-rs/src/macos/monitor.rs
+++ b/dom/webauthn/u2f-hid-rs/src/macos/monitor.rs
@@ -1,18 +1,17 @@
 /* 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/. */
 
 extern crate libc;
 extern crate log;
 
-use core_foundation::base::TCFType;
-use core_foundation_sys::base::*;
-use core_foundation_sys::runloop::*;
+use core_foundation::base::*;
+use core_foundation::runloop::*;
 use platform::iokit::*;
 use runloop::RunLoop;
 use std::collections::HashMap;
 use std::os::raw::c_void;
 use std::sync::mpsc::{channel, Receiver, Sender};
 use std::{io, slice};
 use util::io_err;
 
@@ -85,25 +84,25 @@ where
             }
         }
     }
 
     pub fn stop(&mut self) {
         // Remove all devices.
         while !self.map.is_empty() {
             let device_ref = *self.map.keys().next().unwrap();
-            self.remove_device(&device_ref);
+            self.remove_device(device_ref);
         }
 
         // Close the manager and its devices.
         unsafe { IOHIDManagerClose(self.manager, kIOHIDManagerOptionNone) };
     }
 
-    fn remove_device(&mut self, device_ref: &IOHIDDeviceRef) {
-        if let Some(DeviceData { tx, runloop }) = self.map.remove(device_ref) {
+    fn remove_device(&mut self, device_ref: IOHIDDeviceRef) {
+        if let Some(DeviceData { tx, runloop }) = self.map.remove(&device_ref) {
             // Dropping `tx` will make Device::read() fail eventually.
             drop(tx);
 
             // Wait until the runloop stopped.
             runloop.cancel();
         }
     }
 
@@ -122,17 +121,17 @@ where
         // Ignore the report if we can't find a device for it.
         if let Some(&DeviceData { ref tx, .. }) = this.map.get(&device_ref) {
             let data = unsafe { slice::from_raw_parts(report, report_len as usize).to_vec() };
             send_failed = tx.send(data).is_err();
         }
 
         // Remove the device if sending fails.
         if send_failed {
-            this.remove_device(&device_ref);
+            this.remove_device(device_ref);
         }
     }
 
     extern "C" fn on_device_matching(
         context: *mut c_void,
         _: IOReturn,
         _: *mut c_void,
         device_ref: IOHIDDeviceRef,
@@ -157,17 +156,17 @@ where
 
     extern "C" fn on_device_removal(
         context: *mut c_void,
         _: IOReturn,
         _: *mut c_void,
         device_ref: IOHIDDeviceRef,
     ) {
         let this = unsafe { &mut *(context as *mut Self) };
-        this.remove_device(&device_ref);
+        this.remove_device(device_ref);
     }
 }
 
 impl<F> Drop for Monitor<F>
 where
     F: Fn((IOHIDDeviceRef, Receiver<Vec<u8>>), &Fn() -> bool) + Sync,
 {
     fn drop(&mut self) {
--- a/dom/webauthn/u2f-hid-rs/src/macos/transaction.rs
+++ b/dom/webauthn/u2f-hid-rs/src/macos/transaction.rs
@@ -1,15 +1,15 @@
 /* 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/. */
 
 extern crate libc;
 
-use core_foundation_sys::runloop::*;
+use core_foundation::runloop::*;
 use platform::iokit::{CFRunLoopEntryObserver, IOHIDDeviceRef, SendableRunLoop};
 use platform::monitor::Monitor;
 use std::os::raw::c_void;
 use std::sync::mpsc::{channel, Receiver, Sender};
 use std::thread;
 use util::OnceCallback;
 
 // A transaction will run the given closure in a new thread, thereby using a
--- a/dom/webauthn/u2f-hid-rs/src/manager.rs
+++ b/dom/webauthn/u2f-hid-rs/src/manager.rs
@@ -86,20 +86,17 @@ impl U2FManager {
                     _ => { /* continue */ }
                 }
             }
 
             // Cancel any ongoing activity.
             sm.cancel();
         })?;
 
-        Ok(Self {
-            queue: queue,
-            tx: tx,
-        })
+        Ok(Self { queue, tx })
     }
 
     pub fn register<F>(
         &self,
         flags: ::RegisterFlags,
         timeout: u64,
         challenge: Vec<u8>,
         application: ::AppId,
@@ -144,17 +141,17 @@ impl U2FManager {
     where
         F: FnOnce(Result<::SignResult, ::Error>),
         F: Send + 'static,
     {
         if challenge.len() != PARAMETER_SIZE {
             return Err(::Error::Unknown);
         }
 
-        if app_ids.len() < 1 {
+        if app_ids.is_empty() {
             return Err(::Error::Unknown);
         }
 
         for app_id in &app_ids {
             if app_id.len() != PARAMETER_SIZE {
                 return Err(::Error::Unknown);
             }
         }
--- a/dom/webauthn/u2f-hid-rs/src/statemachine.rs
+++ b/dom/webauthn/u2f-hid-rs/src/statemachine.rs
@@ -10,38 +10,38 @@ use std::time::Duration;
 use u2fprotocol::{u2f_init_device, u2f_is_keyhandle_valid, u2f_register, u2f_sign};
 use util::OnceCallback;
 
 fn is_valid_transport(transports: ::AuthenticatorTransports) -> bool {
     transports.is_empty() || transports.contains(::AuthenticatorTransports::USB)
 }
 
 fn find_valid_key_handles<'a, F>(
-    app_ids: &'a Vec<::AppId>,
-    key_handles: &'a Vec<::KeyHandle>,
+    app_ids: &'a [::AppId],
+    key_handles: &'a [::KeyHandle],
     mut is_valid: F,
 ) -> (&'a ::AppId, Vec<&'a ::KeyHandle>)
 where
     F: FnMut(&Vec<u8>, &::KeyHandle) -> bool,
 {
     // Try all given app_ids in order.
     for app_id in app_ids {
         // Find all valid key handles for the current app_id.
         let valid_handles = key_handles
             .iter()
             .filter(|key_handle| is_valid(app_id, key_handle))
             .collect::<Vec<_>>();
 
         // If there's at least one, stop.
-        if valid_handles.len() > 0 {
+        if !valid_handles.is_empty() {
             return (app_id, valid_handles);
         }
     }
 
-    return (&app_ids[0], vec![]);
+    (&app_ids[0], vec![])
 }
 
 #[derive(Default)]
 pub struct StateMachine {
     transaction: Option<Transaction>,
 }
 
 impl StateMachine {
@@ -96,25 +96,23 @@ impl StateMachine {
                     &application,
                     &key_handle.credential,
                 ).unwrap_or(false) /* no match on failure */
             });
 
             while alive() {
                 if excluded {
                     let blank = vec![0u8; PARAMETER_SIZE];
-                    if let Ok(_) = u2f_register(dev, &blank, &blank) {
+                    if u2f_register(dev, &blank, &blank).is_ok() {
                         callback.call(Err(::Error::InvalidState));
                         break;
                     }
-                } else {
-                    if let Ok(bytes) = u2f_register(dev, &challenge, &application) {
-                        callback.call(Ok(bytes));
-                        break;
-                    }
+                } else if let Ok(bytes) = u2f_register(dev, &challenge, &application) {
+                    callback.call(Ok(bytes));
+                    break;
                 }
 
                 // Sleep a bit before trying again.
                 thread::sleep(Duration::from_millis(100));
             }
         });
 
         self.transaction = Some(try_or!(transaction, |e| cbc.call(Err(e))));
@@ -176,17 +174,17 @@ impl StateMachine {
                 return;
             }
 
             while alive() {
                 // If the device matches none of the given key handles
                 // then just make it blink with bogus data.
                 if valid_handles.is_empty() {
                     let blank = vec![0u8; PARAMETER_SIZE];
-                    if let Ok(_) = u2f_register(dev, &blank, &blank) {
+                    if u2f_register(dev, &blank, &blank).is_ok() {
                         callback.call(Err(::Error::InvalidState));
                         break;
                     }
                 } else {
                     // Otherwise, try to sign.
                     for key_handle in &valid_handles {
                         if let Ok(bytes) = u2f_sign(dev, &challenge, app_id, &key_handle.credential)
                         {
--- a/dom/webauthn/u2f-hid-rs/src/u2fprotocol.rs
+++ b/dom/webauthn/u2f-hid-rs/src/u2fprotocol.rs
@@ -1,12 +1,14 @@
 /* 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/. */
 
+#![cfg_attr(feature = "cargo-clippy", allow(needless_lifetimes))]
+
 extern crate std;
 
 use rand::{thread_rng, Rng};
 use std::ffi::CString;
 use std::io;
 use std::io::{Read, Write};
 
 use consts::*;
@@ -189,17 +191,17 @@ where
 
     Ok(data)
 }
 
 fn send_apdu<T>(dev: &mut T, cmd: u8, p1: u8, send: &[u8]) -> io::Result<(Vec<u8>, [u8; 2])>
 where
     T: U2FDevice + Read + Write,
 {
-    let apdu = U2FAPDUHeader::to_bytes(cmd, p1, send)?;
+    let apdu = U2FAPDUHeader::serialize(cmd, p1, send)?;
     let mut data = sendrecv(dev, U2FHID_MSG, &apdu)?;
 
     if data.len() < 2 {
         return Err(io_err("unexpected response"));
     }
 
     let split_at = data.len() - 2;
     let status = data.split_off(split_at);
@@ -240,58 +242,58 @@ mod tests {
             }
 
             pub fn add_write(&mut self, packet: &[u8], fill_value: u8) {
                 // Add one to deal with record index check
                 let mut write = [fill_value; HID_RPT_SIZE + 1];
                 // Make sure we start with a 0, for HID record index
                 write[0] = 0;
                 // Clone packet data in at 1, since front is padded with HID record index
-                write[1..packet.len() + 1].clone_from_slice(packet);
+                write[1..=packet.len()].clone_from_slice(packet);
                 self.writes.push(write);
             }
 
             pub fn add_read(&mut self, packet: &[u8], fill_value: u8) {
                 let mut read = [fill_value; HID_RPT_SIZE];
                 read[..packet.len()].clone_from_slice(packet);
                 self.reads.push(read);
             }
         }
 
         impl Write for TestDevice {
             fn write(&mut self, bytes: &[u8]) -> io::Result<usize> {
                 // Pop a vector from the expected writes, check for quality
                 // against bytes array.
-                assert!(self.writes.len() > 0, "Ran out of expected write values!");
+                assert!(!self.writes.is_empty(), "Ran out of expected write values!");
                 let check = self.writes.remove(0);
                 assert_eq!(check.len(), bytes.len());
                 assert_eq!(&check[..], bytes);
                 Ok(bytes.len())
             }
 
             // nop
             fn flush(&mut self) -> io::Result<()> {
                 Ok(())
             }
         }
 
         impl Read for TestDevice {
             fn read(&mut self, bytes: &mut [u8]) -> io::Result<usize> {
-                assert!(self.reads.len() > 0, "Ran out of read values!");
+                assert!(!self.reads.is_empty(), "Ran out of read values!");
                 let check = self.reads.remove(0);
                 assert_eq!(check.len(), bytes.len());
                 bytes.clone_from_slice(&check[..]);
                 Ok(check.len())
             }
         }
 
         impl Drop for TestDevice {
             fn drop(&mut self) {
-                assert_eq!(self.reads.len(), 0);
-                assert_eq!(self.writes.len(), 0);
+                assert!(self.reads.is_empty());
+                assert!(self.writes.is_empty());
             }
         }
 
         impl U2FDevice for TestDevice {
             fn get_cid<'a>(&'a self) -> &'a [u8; 4] {
                 &self.cid
             }
 
@@ -327,17 +329,17 @@ mod tests {
         init_device(&mut device, &nonce).unwrap();
         assert_eq!(device.get_cid(), &cid);
     }
 
     #[test]
     fn test_sendrecv_multiple() {
         let mut device = platform::TestDevice::new();
         let cid = [0x01, 0x02, 0x03, 0x04];
-        device.set_cid(cid.clone());
+        device.set_cid(cid);
 
         // init packet
         let mut msg = cid.to_vec();
         msg.extend(vec![U2FHID_PING, 0x00, 0xe4]); // cmd + length = 228
                                                    // write msg, append [1u8; 57], 171 bytes remain
         device.add_write(&msg, 1);
         device.add_read(&msg, 1);
 
@@ -369,17 +371,17 @@ mod tests {
         assert_eq!(d, &data[..]);
     }
 
     #[test]
     fn test_sendapdu() {
         let cid = [0x01, 0x02, 0x03, 0x04];
         let data = [0x01, 0x02, 0x03, 0x04, 0x05];
         let mut device = platform::TestDevice::new();
-        device.set_cid(cid.clone());
+        device.set_cid(cid);
 
         let mut msg = cid.to_vec();
         // sendrecv header
         msg.extend(vec![U2FHID_MSG, 0x00, 0x0e]); // len = 14
                                                   // apdu header
         msg.extend(vec![0x00, U2FHID_PING, 0xaa, 0x00, 0x00, 0x00, 0x05]);
         // apdu data
         msg.extend_from_slice(&data);
--- a/dom/webauthn/u2f-hid-rs/src/u2ftypes.rs
+++ b/dom/webauthn/u2f-hid-rs/src/u2ftypes.rs
@@ -162,17 +162,17 @@ impl U2FHIDInitResp {
 }
 
 // https://en.wikipedia.org/wiki/Smart_card_application_protocol_data_unit
 // https://fidoalliance.org/specs/fido-u2f-v1.
 // 0-nfc-bt-amendment-20150514/fido-u2f-raw-message-formats.html#u2f-message-framing
 pub struct U2FAPDUHeader {}
 
 impl U2FAPDUHeader {
-    pub fn to_bytes(ins: u8, p1: u8, data: &[u8]) -> io::Result<Vec<u8>> {
+    pub fn serialize(ins: u8, p1: u8, data: &[u8]) -> io::Result<Vec<u8>> {
         if data.len() > 0xffff {
             return Err(io_err("payload length > 2^16"));
         }
 
         // Size of header + data + 2 zero bytes for maximum return size.
         let mut bytes = vec![0u8; U2FAPDUHEADER_SIZE + data.len() + 2];
         bytes[1] = ins;
         bytes[2] = p1;
--- a/third_party/rust/core-foundation-sys/.cargo-checksum.json
+++ b/third_party/rust/core-foundation-sys/.cargo-checksum.json
@@ -1,1 +1,1 @@
-{"files":{"Cargo.toml":"49682adfbd90c37132993902a2e4e131474859c1f12c49bb150417d44dd47aa0","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"62065228e42caebca7e7d7db1204cbb867033de5982ca4009928915e4095f3a3","build.rs":"9433ed3b20cc99e716dda4c6d8507c29bc04882544cbbea8d4e48ba80fd0fa12","src/array.rs":"40c305658e16b07d86353a5ad34e7b5fb98720f19cc2b5173360d6a61ce2642f","src/base.rs":"f0f8424099a4269e2359b063c3f055e115aec6df0f6aa71695ca91257dfd64e2","src/bundle.rs":"e8ad47f9f0280e1eef7e9aea2eb88020443953ac2cda234396321450ffc3d48a","src/data.rs":"4547e98f4e25a99606d8f33e82f8de3d9889612485d445d4467138b8ad29b7e9","src/date.rs":"c064ee4c3ebd1927532c34871e2e41179d6e3c3e400f6b409a18ad9e2337477f","src/dictionary.rs":"3327a6f90f1e0db5e3fde1973e2df4143ca896716a816d03f2b17c8e988c5159","src/error.rs":"6205ebeb7631daa8bcd560862b6daa10f640c8c117ce5f6f7184f268dcbcb42a","src/filedescriptor.rs":"49580654b657811fade7adaa256f5f895cb011c9baa4731e2f44a6ec7fdba235","src/lib.rs":"0b1fa29a241df0bd6a2310e4905766150687f62453f635a693219f665fc70658","src/messageport.rs":"e9227d5907cba8e29cdeea41bcb3ae5c7840220442953ab19aace31a84542f47","src/number.rs":"b1154203e74cb2258ba5520e20bcd4d524f1a957e09a19dd026b18d23baa3868","src/propertylist.rs":"7ec928438826c4ce40befedf3de0a37c8ecbc0fc17896dfa629d5864000b2cfe","src/runloop.rs":"67a6c2e4773f13de9452c9f8e4791b9889e03e56c07a7bdf64dbba99e9821f45","src/set.rs":"8aef5f4ba75a067e271ad6cb960569f1d22a0acee0eb6c79e31bb8b636619d9d","src/string.rs":"3ebfa11bba928d0ab1b07ecc0bd0f11367642eb818c8e21f08c16a4be8f9494f","src/timezone.rs":"42741f556af081be32987d2705488959c60aeb794e7c737b092f0dce5851ca89","src/url.rs":"4cd2950660ad234f7f833b3f5c092f7322465085452cca8ced623564400cdef9","src/uuid.rs":"82f75efa73d0842dff2e13d299c166c6593a77fcb69c4b7629a2df1c17ae507d"},"package":"b2a53cce0ddcf7e7e1f998738d757d5a3bf08bf799a180e50ebe50d298f52f5a"}
\ No newline at end of file
+{"files":{"Cargo.toml":"dc9a55f461f23bf82bb9b3ee7d9b74807b7a905e31f05074bb05b5e3cb1ab267","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"62065228e42caebca7e7d7db1204cbb867033de5982ca4009928915e4095f3a3","build.rs":"9433ed3b20cc99e716dda4c6d8507c29bc04882544cbbea8d4e48ba80fd0fa12","src/array.rs":"40c305658e16b07d86353a5ad34e7b5fb98720f19cc2b5173360d6a61ce2642f","src/attributed_string.rs":"693b6c745c5aef1929595c94363d500b4b25ebcfed0b4b8dee0103b8fc0537f8","src/base.rs":"f0f8424099a4269e2359b063c3f055e115aec6df0f6aa71695ca91257dfd64e2","src/bundle.rs":"e8ad47f9f0280e1eef7e9aea2eb88020443953ac2cda234396321450ffc3d48a","src/data.rs":"4547e98f4e25a99606d8f33e82f8de3d9889612485d445d4467138b8ad29b7e9","src/date.rs":"c064ee4c3ebd1927532c34871e2e41179d6e3c3e400f6b409a18ad9e2337477f","src/dictionary.rs":"3327a6f90f1e0db5e3fde1973e2df4143ca896716a816d03f2b17c8e988c5159","src/error.rs":"6205ebeb7631daa8bcd560862b6daa10f640c8c117ce5f6f7184f268dcbcb42a","src/filedescriptor.rs":"49580654b657811fade7adaa256f5f895cb011c9baa4731e2f44a6ec7fdba235","src/lib.rs":"af7183760214be155e2cf562bf4265bd2d73da079e35d05e29ea0146e3c87654","src/messageport.rs":"e9227d5907cba8e29cdeea41bcb3ae5c7840220442953ab19aace31a84542f47","src/number.rs":"b1154203e74cb2258ba5520e20bcd4d524f1a957e09a19dd026b18d23baa3868","src/propertylist.rs":"7ec928438826c4ce40befedf3de0a37c8ecbc0fc17896dfa629d5864000b2cfe","src/runloop.rs":"67a6c2e4773f13de9452c9f8e4791b9889e03e56c07a7bdf64dbba99e9821f45","src/set.rs":"8aef5f4ba75a067e271ad6cb960569f1d22a0acee0eb6c79e31bb8b636619d9d","src/string.rs":"3ebfa11bba928d0ab1b07ecc0bd0f11367642eb818c8e21f08c16a4be8f9494f","src/timezone.rs":"42741f556af081be32987d2705488959c60aeb794e7c737b092f0dce5851ca89","src/url.rs":"4cd2950660ad234f7f833b3f5c092f7322465085452cca8ced623564400cdef9","src/uuid.rs":"82f75efa73d0842dff2e13d299c166c6593a77fcb69c4b7629a2df1c17ae507d"},"package":"e7ca8a5221364ef15ce201e8ed2f609fc312682a8f4e0e3d4aa5879764e0fa3b"}
\ No newline at end of file
--- a/third_party/rust/core-foundation-sys/Cargo.toml
+++ b/third_party/rust/core-foundation-sys/Cargo.toml
@@ -7,17 +7,17 @@
 #
 # If you believe there's an error in this file please file an
 # issue against the rust-lang/cargo repository. If you're
 # editing this file be aware that the upstream Cargo.toml
 # will likely look very different (and much more reasonable)
 
 [package]
 name = "core-foundation-sys"
-version = "0.6.0"
+version = "0.6.2"
 authors = ["The Servo Project Developers"]
 build = "build.rs"
 description = "Bindings to Core Foundation for OS X"
 homepage = "https://github.com/servo/core-foundation-rs"
 license = "MIT / Apache-2.0"
 repository = "https://github.com/servo/core-foundation-rs"
 
 [dependencies]
new file mode 100644
--- /dev/null
+++ b/third_party/rust/core-foundation-sys/src/attributed_string.rs
@@ -0,0 +1,56 @@
+// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::os::raw::c_void;
+use base::{CFAllocatorRef, CFTypeRef, CFIndex, CFRange, CFTypeID};
+use string::CFStringRef;
+use dictionary::CFDictionaryRef;
+
+#[repr(C)]
+pub struct __CFAttributedString(c_void);
+
+pub type CFAttributedStringRef = *const __CFAttributedString;
+pub type CFMutableAttributedStringRef = *const __CFAttributedString;
+
+extern {
+    /* CFAttributedString */
+
+    pub fn CFAttributedStringCreate(
+        allocator: CFAllocatorRef,
+        str: CFStringRef,
+        attributes: CFDictionaryRef,
+    ) -> CFAttributedStringRef;
+
+    pub fn CFAttributedStringGetLength(astr: CFAttributedStringRef) -> CFIndex;
+
+    pub fn CFAttributedStringGetTypeID() -> CFTypeID;
+
+    /* CFMutableAttributedString */
+
+    pub fn CFAttributedStringCreateMutableCopy(
+        allocator: CFAllocatorRef, max_length: CFIndex, astr: CFAttributedStringRef
+    ) -> CFMutableAttributedStringRef;
+
+    pub fn CFAttributedStringCreateMutable(
+        allocator: CFAllocatorRef,
+        max_length: CFIndex,
+    ) -> CFMutableAttributedStringRef;
+
+    pub fn CFAttributedStringReplaceString(
+        astr: CFMutableAttributedStringRef, range: CFRange, replacement: CFStringRef);
+
+    pub fn CFAttributedStringSetAttribute(
+        astr: CFMutableAttributedStringRef,
+        range: CFRange,
+        attr_name: CFStringRef,
+        value: CFTypeRef,
+    );
+
+    pub fn CFMutableAttributedStringGetTypeID() -> CFTypeID;
+}
--- a/third_party/rust/core-foundation-sys/src/lib.rs
+++ b/third_party/rust/core-foundation-sys/src/lib.rs
@@ -6,16 +6,17 @@
 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 #![allow(non_snake_case, non_camel_case_types, non_upper_case_globals, improper_ctypes)]
 
 #![cfg_attr(all(feature="mac_os_10_7_support", feature="mac_os_10_8_features"), feature(linkage))] // back-compat requires weak linkage
 
 pub mod array;
+pub mod attributed_string;
 pub mod base;
 pub mod bundle;
 pub mod data;
 pub mod date;
 pub mod dictionary;
 pub mod error;
 pub mod filedescriptor;
 pub mod messageport;
--- a/third_party/rust/core-foundation/.cargo-checksum.json
+++ b/third_party/rust/core-foundation/.cargo-checksum.json
@@ -1,1 +1,1 @@
-{"files":{"Cargo.toml":"c0a87a7aa5bb6fa2d5a20acc9384c37e686035d043ab9e169b6a1953bf62acaf","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"62065228e42caebca7e7d7db1204cbb867033de5982ca4009928915e4095f3a3","src/array.rs":"c0d67c88f85d01303998e95b8399bc5018a1de9de610ae6365cd05eea1377176","src/base.rs":"e33fedff5017420b88c7488691b42d714cce7f8a573e14bf04329e8b0a4b6a11","src/boolean.rs":"f5b4d295aaf6cc3681212afebeae2974c5d551125badcc066e6089ac0d2a0873","src/bundle.rs":"9cd6e6bf79ea9c8ac24b2e4d62b01b9ca22935cf331a51871e061269ef2c394d","src/data.rs":"a1d7e6430c745731fc7b2aee49af9f14e79c8a288951c82ea6507689a3356af8","src/date.rs":"a02f6cca7b6e8fbabc7713177429012658dba5146556e14a08e7baaf81958d83","src/dictionary.rs":"bdae97f43b95a9c97934b102e3ec383f026d5def81faeccdddb02c56b9c954a0","src/error.rs":"22c21087d9c2c103d1bcb2c4af33b684317bbda5d4747902e510d410f8c1a14b","src/filedescriptor.rs":"f01da404e42760a50d91a43af648e781916c0a10c23753bea94f0f67bdc4d00c","src/lib.rs":"b2939b828b4d7a863c26adde3c7f20f587bcbe071f4ab3625ee83bd14fda1645","src/number.rs":"0c2842b8ea973a2c12173a13544b7d49472df11e166540ca5c28f38f54a746f6","src/propertylist.rs":"762e1ed2db80badd1b491767c02a62c9aa31d9751ecd45c2e4b3bec89ebd40ad","src/runloop.rs":"98334ee796cea1634a5a9baf59d62f02c25b718d45baab5230a5cc14cb2ee6d5","src/set.rs":"f8e80eefe5257084350f04fce2cf6b051f08efe7921f6459cba67ccd7ea1e1e7","src/string.rs":"50c08f0504c718576e4f2397218a963ab701de0214422dc82e1991d4ab9a00e3","src/timezone.rs":"65859378232ee55f04bc4544b88f5dbc21f5db01bd16f2df3e82136ee3ce26b4","src/url.rs":"ee5370a1ba88823ee0eaa8615c5dafd55cedd7bd50172e9f2caa52ed305e2233","src/uuid.rs":"c532363a1a322a88e195f8606e613a68012708454b0d61ffe7abce432ec68596","tests/use_macro_outside_crate.rs":"ed5e74ac9e988f2609c0b785189f1e6368d693f6401603ad065521f3ab51df94"},"package":"c7caa6cb9e76ddddbea09a03266d6b3bc98cd41e9fb9b017c473e7cca593ec25"}
\ No newline at end of file
+{"files":{"Cargo.toml":"072515f7973c73e5db7674b3c3f0e0c13a07800fcacb2ef1efb0c656f0ca77fe","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"62065228e42caebca7e7d7db1204cbb867033de5982ca4009928915e4095f3a3","src/array.rs":"c38c9364cbd53c7656959b62cb3fa93f6e2fb37f2822fed89f052ea73bb4b052","src/attributed_string.rs":"b3b998991234c3740751a21a38ad5179b9761d79fa51f975921c40d515a69825","src/base.rs":"043dc1c905fce6b3c3a2b7ebf6de937c728ca5e75766639ff45b31ec7b0a11cf","src/boolean.rs":"f5b4d295aaf6cc3681212afebeae2974c5d551125badcc066e6089ac0d2a0873","src/bundle.rs":"7e0fbe7032c8658ba5751a236eaaaa4b031fef43daf0be3aa229de4beb83b52a","src/data.rs":"a1d7e6430c745731fc7b2aee49af9f14e79c8a288951c82ea6507689a3356af8","src/date.rs":"a02f6cca7b6e8fbabc7713177429012658dba5146556e14a08e7baaf81958d83","src/dictionary.rs":"897886dd2ff5f011e838829fc82564404e9384e7bee58db7dc7d4c08c352599d","src/error.rs":"22c21087d9c2c103d1bcb2c4af33b684317bbda5d4747902e510d410f8c1a14b","src/filedescriptor.rs":"f01da404e42760a50d91a43af648e781916c0a10c23753bea94f0f67bdc4d00c","src/lib.rs":"98a1deda9e40c293dfd2410d8f9bdcbc033ec0c55e3b2807050fc6a7d68f23ce","src/number.rs":"9de607a5809dcb7f43ccce5ea2b587423dfe69aa94c1cf68a52e20b50f8c9835","src/propertylist.rs":"762e1ed2db80badd1b491767c02a62c9aa31d9751ecd45c2e4b3bec89ebd40ad","src/runloop.rs":"98334ee796cea1634a5a9baf59d62f02c25b718d45baab5230a5cc14cb2ee6d5","src/set.rs":"f8e80eefe5257084350f04fce2cf6b051f08efe7921f6459cba67ccd7ea1e1e7","src/string.rs":"1f1216a9b126e0496b0f757a42c28c59f0ee53f9b8bd45a7b2b6dc8046a3f3e7","src/timezone.rs":"65859378232ee55f04bc4544b88f5dbc21f5db01bd16f2df3e82136ee3ce26b4","src/url.rs":"ee5370a1ba88823ee0eaa8615c5dafd55cedd7bd50172e9f2caa52ed305e2233","src/uuid.rs":"c532363a1a322a88e195f8606e613a68012708454b0d61ffe7abce432ec68596","tests/use_macro_outside_crate.rs":"ed5e74ac9e988f2609c0b785189f1e6368d693f6401603ad065521f3ab51df94"},"package":"4e2640d6d0bf22e82bed1b73c6aef8d5dd31e5abe6666c57e6d45e2649f4f887"}
\ No newline at end of file
--- a/third_party/rust/core-foundation/Cargo.toml
+++ b/third_party/rust/core-foundation/Cargo.toml
@@ -7,28 +7,28 @@
 #
 # If you believe there's an error in this file please file an
 # issue against the rust-lang/cargo repository. If you're
 # editing this file be aware that the upstream Cargo.toml
 # will likely look very different (and much more reasonable)
 
 [package]
 name = "core-foundation"
-version = "0.6.0"
+version = "0.6.3"
 authors = ["The Servo Project Developers"]
 description = "Bindings to Core Foundation for OS X"
 homepage = "https://github.com/servo/core-foundation-rs"
 license = "MIT / Apache-2.0"
 repository = "https://github.com/servo/core-foundation-rs"
 [dependencies.chrono]
 version = "0.4"
 optional = true
 
 [dependencies.core-foundation-sys]
-version = "0.6"
+version = "0.6.1"
 
 [dependencies.libc]
 version = "0.2"
 
 [dependencies.uuid]
 version = "0.5"
 optional = true
 
--- a/third_party/rust/core-foundation/src/array.rs
+++ b/third_party/rust/core-foundation/src/array.rs
@@ -10,16 +10,17 @@
 //! Heterogeneous immutable arrays.
 
 pub use core_foundation_sys::array::*;
 pub use core_foundation_sys::base::CFIndex;
 use core_foundation_sys::base::{CFTypeRef, CFRelease, kCFAllocatorDefault};
 use std::mem;
 use std::marker::PhantomData;
 use std::os::raw::c_void;
+use std::ptr;
 use ConcreteCFType;
 
 use base::{CFIndexConvertible, TCFType, CFRange};
 use base::{FromVoid, ItemRef};
 
 /// A heterogeneous immutable array.
 pub struct CFArray<T = *const c_void>(CFArrayRef, PhantomData<T>);
 
@@ -56,16 +57,27 @@ impl<'a, T: FromVoid> ExactSizeIterator 
 }
 
 impl_TCFType!(CFArray<T>, CFArrayRef, CFArrayGetTypeID);
 impl_CFTypeDescription!(CFArray);
 
 unsafe impl ConcreteCFType for CFArray<*const c_void> {}
 
 impl<T> CFArray<T> {
+    /// Creates a new `CFArray` with the given elements, which must implement `Copy`.
+    pub fn from_copyable(elems: &[T]) -> CFArray<T> where T: Copy {
+        unsafe {
+            let array_ref = CFArrayCreate(kCFAllocatorDefault,
+                                          mem::transmute(elems.as_ptr()),
+                                          elems.len().to_CFIndex(),
+                                          ptr::null());
+            TCFType::wrap_under_create_rule(array_ref)
+        }
+    }
+
     /// Creates a new `CFArray` with the given elements, which must be `CFType` objects.
     pub fn from_CFTypes(elems: &[T]) -> CFArray<T> where T: TCFType {
         unsafe {
             let elems: Vec<CFTypeRef> = elems.iter().map(|elem| elem.as_CFTypeRef()).collect();
             let array_ref = CFArrayCreate(kCFAllocatorDefault,
                                           mem::transmute(elems.as_ptr()),
                                           elems.len().to_CFIndex(),
                                           &kCFTypeArrayCallBacks);
new file mode 100644
--- /dev/null
+++ b/third_party/rust/core-foundation/src/attributed_string.rs
@@ -0,0 +1,79 @@
+// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+pub use core_foundation_sys::attributed_string::*;
+
+use base::TCFType;
+use core_foundation_sys::base::{CFIndex, CFRange, kCFAllocatorDefault};
+use std::ptr::null;
+use string::{CFString, CFStringRef};
+
+declare_TCFType!{
+    CFAttributedString, CFAttributedStringRef
+}
+impl_TCFType!(CFAttributedString, CFAttributedStringRef, CFAttributedStringGetTypeID);
+
+impl CFAttributedString {
+    #[inline]
+    pub fn new(string: &CFString) -> Self {
+        unsafe {
+            let astr_ref = CFAttributedStringCreate(
+                kCFAllocatorDefault, string.as_concrete_TypeRef(), null());
+
+            CFAttributedString::wrap_under_create_rule(astr_ref)
+        }
+    }
+
+    #[inline]
+    pub fn char_len(&self) -> CFIndex {
+        unsafe {
+            CFAttributedStringGetLength(self.0)
+        }
+    }
+}
+
+declare_TCFType!{
+    CFMutableAttributedString, CFMutableAttributedStringRef
+}
+impl_TCFType!(CFMutableAttributedString, CFMutableAttributedStringRef, CFMutableAttributedStringGetTypeID);
+
+impl CFMutableAttributedString {
+    #[inline]
+    pub fn new() -> Self {
+        unsafe {
+            let astr_ref = CFAttributedStringCreateMutable(
+                kCFAllocatorDefault, 0);
+
+            CFMutableAttributedString::wrap_under_create_rule(astr_ref)
+        }
+    }
+
+    #[inline]
+    pub fn char_len(&self) -> CFIndex {
+        unsafe {
+            CFAttributedStringGetLength(self.0)
+        }
+    }
+
+    #[inline]
+    pub fn replace_str(&mut self, string: &CFString, range: CFRange) {
+        unsafe {
+            CFAttributedStringReplaceString(
+                self.0, range, string.as_concrete_TypeRef());
+        }
+    }
+
+    #[inline]
+    pub fn set_attribute<T: TCFType>(&mut self, range: CFRange, name: CFStringRef, value: T) {
+        unsafe {
+            CFAttributedStringSetAttribute(
+                self.0, range, name, value.as_CFTypeRef());
+        }
+    }
+}
--- a/third_party/rust/core-foundation/src/base.rs
+++ b/third_party/rust/core-foundation/src/base.rs
@@ -7,17 +7,17 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
 use std;
 use std::fmt;
 use std::marker::PhantomData;
 use std::mem;
 use std::mem::ManuallyDrop;
-use std::ops::Deref;
+use std::ops::{Deref, DerefMut};
 use std::os::raw::c_void;
 
 pub use core_foundation_sys::base::*;
 
 use string::CFString;
 use ConcreteCFType;
 
 pub trait CFIndexConvertible {
@@ -59,16 +59,31 @@ impl CFType {
     /// // Cast it up to a CFType.
     /// let cf_type: CFType = string.as_CFType();
     /// // Cast it down again.
     /// assert!(cf_type.downcast::<CFString>().unwrap().to_string() == "FooBar");
     /// // Casting it to some other type will yield `None`
     /// assert!(cf_type.downcast::<CFBoolean>().is_none());
     /// ```
     ///
+    /// ```compile_fail
+    /// # use core_foundation::array::CFArray;
+    /// # use core_foundation::base::TCFType;
+    /// # use core_foundation::boolean::CFBoolean;
+    /// # use core_foundation::string::CFString;
+    /// #
+    /// let boolean_array = CFArray::from_CFTypes(&[CFBoolean::true_value()]).into_CFType();
+    ///
+    /// // This downcast is not allowed and causes compiler error, since it would cause undefined
+    /// // behavior to access the elements of the array as a CFString:
+    /// let invalid_string_array = boolean_array
+    ///     .downcast_into::<CFArray<CFString>>()
+    ///     .unwrap();
+    /// ```
+    ///
     /// [`Box::downcast`]: https://doc.rust-lang.org/std/boxed/struct.Box.html#method.downcast
     /// [`CFPropertyList::downcast`]: ../propertylist/struct.CFPropertyList.html#method.downcast
     #[inline]
     pub fn downcast<T: ConcreteCFType>(&self) -> Option<T> {
         if self.instance_of::<T>() {
             unsafe {
                 let reference = T::Ref::from_void_ptr(self.0);
                 Some(T::wrap_under_get_rule(reference))
@@ -77,17 +92,17 @@ impl CFType {
             None
         }
     }
 
     /// Similar to [`downcast`], but consumes self and can thus avoid touching the retain count.
     ///
     /// [`downcast`]: #method.downcast
     #[inline]
-    pub fn downcast_into<T: TCFType>(self) -> Option<T> {
+    pub fn downcast_into<T: ConcreteCFType>(self) -> Option<T> {
         if self.instance_of::<T>() {
             unsafe {
                 let reference = T::Ref::from_void_ptr(self.0);
                 mem::forget(self);
                 Some(T::wrap_under_create_rule(reference))
             }
         } else {
             None
@@ -260,16 +275,68 @@ impl<'a, T: fmt::Debug> fmt::Debug for I
 }
 
 impl<'a, T: PartialEq> PartialEq for ItemRef<'a, T> {
     fn eq(&self, other: &Self) -> bool {
         self.0.eq(&other.0)
     }
 }
 
+/// A reference to a mutable element inside a container
+pub struct ItemMutRef<'a, T: 'a>(ManuallyDrop<T>, PhantomData<&'a T>);
+
+impl<'a, T> Deref for ItemMutRef<'a, T> {
+    type Target = T;
+
+    fn deref(&self) -> &T {
+        &self.0
+    }
+}
+
+impl<'a, T> DerefMut for ItemMutRef<'a, T> {
+    fn deref_mut(&mut self) -> &mut T {
+        &mut self.0
+    }
+}
+
+impl<'a, T: fmt::Debug> fmt::Debug for ItemMutRef<'a, T> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
+        self.0.fmt(f)
+    }
+}
+
+impl<'a, T: PartialEq> PartialEq for ItemMutRef<'a, T> {
+    fn eq(&self, other: &Self) -> bool {
+        self.0.eq(&other.0)
+    }
+}
+
+/// A trait describing how to convert from the stored *mut c_void to the desired T
+pub unsafe trait FromMutVoid {
+    unsafe fn from_mut_void<'a>(x: *mut c_void) -> ItemMutRef<'a, Self> where Self: std::marker::Sized;
+}
+
+unsafe impl FromMutVoid for u32 {
+    unsafe fn from_mut_void<'a>(x: *mut c_void) -> ItemMutRef<'a, Self> {
+        ItemMutRef(ManuallyDrop::new(x as u32), PhantomData)
+    }
+}
+
+unsafe impl FromMutVoid for *const c_void {
+    unsafe fn from_mut_void<'a>(x: *mut c_void) -> ItemMutRef<'a, Self> {
+        ItemMutRef(ManuallyDrop::new(x), PhantomData)
+    }
+}
+
+unsafe impl<T: TCFType> FromMutVoid for T {
+    unsafe fn from_mut_void<'a>(x: *mut c_void) -> ItemMutRef<'a, Self> {
+        ItemMutRef(ManuallyDrop::new(TCFType::wrap_under_create_rule(T::Ref::from_void_ptr(x))), PhantomData)
+    }
+}
+
 /// A trait describing how to convert from the stored *const c_void to the desired T
 pub unsafe trait FromVoid {
     unsafe fn from_void<'a>(x: *const c_void) -> ItemRef<'a, Self> where Self: std::marker::Sized;
 }
 
 unsafe impl FromVoid for u32 {
     unsafe fn from_void<'a>(x: *const c_void) -> ItemRef<'a, Self> {
         // Functions like CGFontCopyTableTags treat the void*'s as u32's
--- a/third_party/rust/core-foundation/src/bundle.rs
+++ b/third_party/rust/core-foundation/src/bundle.rs
@@ -10,19 +10,19 @@
 //! Core Foundation Bundle Type
 
 pub use core_foundation_sys::bundle::*;
 use core_foundation_sys::base::kCFAllocatorDefault;
 
 use base::{CFType, TCFType};
 use url::CFURL;
 use dictionary::CFDictionary;
+use std::os::raw::c_void;
 use string::CFString;
 
-
 declare_TCFType!{
     /// A Bundle type.
     CFBundle, CFBundleRef
 }
 impl_TCFType!(CFBundle, CFBundleRef, CFBundleGetTypeID);
 
 impl CFBundle {
     pub fn new(bundleURL: CFURL) -> Option<CFBundle> {
@@ -31,16 +31,34 @@ impl CFBundle {
             if bundle_ref.is_null() {
                 None
             } else {
                 Some(TCFType::wrap_under_create_rule(bundle_ref))
             }
         }
     }
 
+    pub fn bundle_with_identifier(identifier: CFString) -> Option<CFBundle> {
+        unsafe {
+            let bundle_ref = CFBundleGetBundleWithIdentifier(identifier.as_concrete_TypeRef());
+            if bundle_ref.is_null() {
+                None
+            } else {
+                Some(TCFType::wrap_under_get_rule(bundle_ref))
+            }
+        }
+    }
+
+    pub fn function_pointer_for_name(&self, function_name: CFString) -> *const c_void {
+        unsafe {
+            CFBundleGetFunctionPointerForName(self.as_concrete_TypeRef(),
+                                              function_name.as_concrete_TypeRef())
+        }
+    }
+
     pub fn main_bundle() -> CFBundle {
         unsafe {
             let bundle_ref = CFBundleGetMainBundle();
             TCFType::wrap_under_get_rule(bundle_ref)
         }
     }
 
     pub fn info_dictionary(&self) -> CFDictionary<CFString, CFType> {
--- a/third_party/rust/core-foundation/src/dictionary.rs
+++ b/third_party/rust/core-foundation/src/dictionary.rs
@@ -14,29 +14,32 @@ pub use core_foundation_sys::dictionary:
 use core_foundation_sys::base::{CFTypeRef, CFRelease, kCFAllocatorDefault};
 use std::mem;
 use std::os::raw::c_void;
 use std::ptr;
 use std::marker::PhantomData;
 
 use base::{ItemRef, FromVoid, ToVoid};
 use base::{CFIndexConvertible, TCFType};
+use ConcreteCFType;
 
 // consume the type parameters with PhantomDatas
 pub struct CFDictionary<K = *const c_void, V = *const c_void>(CFDictionaryRef, PhantomData<K>, PhantomData<V>);
 
 impl<K, V> Drop for CFDictionary<K, V> {
     fn drop(&mut self) {
         unsafe { CFRelease(self.as_CFTypeRef()) }
     }
 }
 
 impl_TCFType!(CFDictionary<K, V>, CFDictionaryRef, CFDictionaryGetTypeID);
 impl_CFTypeDescription!(CFDictionary);
 
+unsafe impl ConcreteCFType for CFDictionary<*const c_void, *const c_void> {}
+
 impl<K, V> CFDictionary<K, V> {
     pub fn from_CFType_pairs(pairs: &[(K, V)]) -> CFDictionary<K, V> where K: TCFType, V: TCFType {
         let (keys, values): (Vec<CFTypeRef>, Vec<CFTypeRef>) = pairs
             .iter()
             .map(|&(ref key, ref value)| (key.as_CFTypeRef(), value.as_CFTypeRef()))
             .unzip();
 
         unsafe {
@@ -46,16 +49,30 @@ impl<K, V> CFDictionary<K, V> {
                                                     keys.len().to_CFIndex(),
                                                     &kCFTypeDictionaryKeyCallBacks,
                                                     &kCFTypeDictionaryValueCallBacks);
             TCFType::wrap_under_create_rule(dictionary_ref)
         }
     }
 
     #[inline]
+    pub fn to_untyped(&self) -> CFDictionary {
+        unsafe { CFDictionary::wrap_under_get_rule(self.0) }
+    }
+
+    /// Returns the same dictionary, but with the types reset to void pointers.
+    /// Equal to `to_untyped`, but is faster since it does not increment the retain count.
+    #[inline]
+    pub fn into_untyped(self) -> CFDictionary {
+        let reference = self.0;
+        mem::forget(self);
+        unsafe { CFDictionary::wrap_under_create_rule(reference) }
+    }
+
+    #[inline]
     pub fn len(&self) -> usize {
         unsafe {
             CFDictionaryGetCount(self.0) as usize
         }
     }
 
     #[inline]
     pub fn is_empty(&self) -> bool {
@@ -141,16 +158,36 @@ impl<K, V> CFMutableDictionary<K, V> {
     pub fn from_CFType_pairs(pairs: &[(K, V)]) -> CFMutableDictionary<K, V> where K: ToVoid<K>, V: ToVoid<V> {
         let mut result = Self::with_capacity(pairs.len() as _);
         for &(ref key, ref value) in pairs {
             result.add(key, value);
         }
         result
     }
 
+    #[inline]
+    pub fn to_untyped(&self) -> CFMutableDictionary {
+        unsafe { CFMutableDictionary::wrap_under_get_rule(self.0) }
+    }
+
+    /// Returns the same dictionary, but with the types reset to void pointers.
+    /// Equal to `to_untyped`, but is faster since it does not increment the retain count.
+    #[inline]
+    pub fn into_untyped(self) -> CFMutableDictionary {
+        let reference = self.0;
+        mem::forget(self);
+        unsafe { CFMutableDictionary::wrap_under_create_rule(reference) }
+    }
+
+    /// Returns a `CFDictionary` pointing to the same underlying dictionary as this mutable one.
+    #[inline]
+    pub fn to_immutable(&self) -> CFDictionary<K, V> {
+        unsafe { CFDictionary::wrap_under_get_rule(self.0) }
+    }
+
     // Immutable interface
 
     #[inline]
     pub fn len(&self) -> usize {
         unsafe {
             CFDictionaryGetCount(self.0) as usize
         }
     }
@@ -230,16 +267,27 @@ impl<K, V> CFMutableDictionary<K, V> {
     }
 
     #[inline]
     pub fn remove_all(&mut self) {
         unsafe { CFDictionaryRemoveAllValues(self.0) }
     }
 }
 
+impl<'a, K, V> From<&'a CFDictionary<K, V>> for CFMutableDictionary<K, V> {
+    /// Creates a new mutable dictionary with the key-value pairs from another dictionary.
+    /// The capacity of the new mutable dictionary is not limited.
+    fn from(dict: &'a CFDictionary<K, V>) -> Self {
+        unsafe {
+            let mut_dict_ref = CFDictionaryCreateMutableCopy(kCFAllocatorDefault, 0, dict.0);
+            TCFType::wrap_under_create_rule(mut_dict_ref)
+        }
+    }
+}
+
 
 #[cfg(test)]
 pub mod test {
     use super::*;
     use base::{CFType, TCFType};
     use boolean::CFBoolean;
     use number::CFNumber;
     use string::CFString;
@@ -308,9 +356,41 @@ pub mod test {
 
         assert!(dict.contains_key(&key));
         assert!(!dict.contains_key(&invalid_key));
 
         let value = dict.find(&key).unwrap().clone();
         assert_eq!(value, CFBoolean::true_value());
         assert_eq!(dict.find(&invalid_key), None);
     }
+
+    #[test]
+    fn convert_immutable_to_mutable_dict() {
+        let dict: CFDictionary<CFString, CFBoolean> = CFDictionary::from_CFType_pairs(&[
+            (CFString::from_static_string("Foo"), CFBoolean::true_value()),
+        ]);
+        let mut mut_dict = CFMutableDictionary::from(&dict);
+        assert_eq!(dict.retain_count(), 1);
+        assert_eq!(mut_dict.retain_count(), 1);
+
+        assert_eq!(mut_dict.len(), 1);
+        assert_eq!(*mut_dict.get(&CFString::from_static_string("Foo")), CFBoolean::true_value());
+
+        mut_dict.add(&CFString::from_static_string("Bar"), &CFBoolean::false_value());
+        assert_eq!(dict.len(), 1);
+        assert_eq!(mut_dict.len(), 2);
+    }
+
+    #[test]
+    fn mutable_dictionary_as_immutable() {
+        let mut mut_dict: CFMutableDictionary<CFString, CFBoolean> = CFMutableDictionary::new();
+        mut_dict.add(&CFString::from_static_string("Bar"), &CFBoolean::false_value());
+        assert_eq!(mut_dict.retain_count(), 1);
+
+        let dict = mut_dict.to_immutable();
+        assert_eq!(mut_dict.retain_count(), 2);
+        assert_eq!(dict.retain_count(), 2);
+        assert_eq!(*dict.get(&CFString::from_static_string("Bar")), CFBoolean::false_value());
+
+        mem::drop(dict);
+        assert_eq!(mut_dict.retain_count(), 1);
+    }
 }
--- a/third_party/rust/core-foundation/src/lib.rs
+++ b/third_party/rust/core-foundation/src/lib.rs
@@ -48,26 +48,23 @@ macro_rules! impl_TCFType {
 
             #[inline]
             fn as_concrete_TypeRef(&self) -> $ty_ref {
                 self.0
             }
 
             #[inline]
             unsafe fn wrap_under_get_rule(reference: $ty_ref) -> Self {
-                use std::mem;
-                let reference = mem::transmute($crate::base::CFRetain(mem::transmute(reference)));
+                let reference = $crate::base::CFRetain(reference as *const ::std::os::raw::c_void) as $ty_ref;
                 $crate::base::TCFType::wrap_under_create_rule(reference)
             }
 
             #[inline]
             fn as_CFTypeRef(&self) -> $crate::base::CFTypeRef {
-                unsafe {
-                    ::std::mem::transmute(self.as_concrete_TypeRef())
-                }
+                self.as_concrete_TypeRef() as $crate::base::CFTypeRef
             }
 
             #[inline]
             unsafe fn wrap_under_create_rule(reference: $ty_ref) -> Self {
                 // we need one PhantomData for each type parameter so call ourselves
                 // again with @Phantom $p to produce that
                 $ty(reference $(, impl_TCFType!(@Phantom $p))*)
             }
@@ -95,31 +92,31 @@ macro_rules! impl_TCFType {
                 self.as_CFType().eq(&other.as_CFType())
             }
         }
 
         impl Eq for $ty { }
 
         unsafe impl<'a> $crate::base::ToVoid<$ty> for &'a $ty {
             fn to_void(&self) -> *const ::std::os::raw::c_void {
-            use $crate::base::TCFTypeRef;
+                use $crate::base::TCFTypeRef;
                 self.as_concrete_TypeRef().as_void_ptr()
             }
         }
 
         unsafe impl $crate::base::ToVoid<$ty> for $ty {
             fn to_void(&self) -> *const ::std::os::raw::c_void {
-            use $crate::base::TCFTypeRef;
+                use $crate::base::TCFTypeRef;
                 self.as_concrete_TypeRef().as_void_ptr()
             }
         }
 
         unsafe impl $crate::base::ToVoid<$ty> for $ty_ref {
             fn to_void(&self) -> *const ::std::os::raw::c_void {
-            use $crate::base::TCFTypeRef;
+                use $crate::base::TCFTypeRef;
                 self.as_void_ptr()
             }
         }
 
     };
 
     (@Phantom $x:ident) => { ::std::marker::PhantomData };
 }
@@ -157,16 +154,17 @@ macro_rules! impl_CFComparison {
             fn cmp(&self, other: &$ty) -> ::std::cmp::Ordering {
                 self.partial_cmp(other).unwrap()
             }
         }
     }
 }
 
 pub mod array;
+pub mod attributed_string;
 pub mod base;
 pub mod boolean;
 pub mod data;
 pub mod date;
 pub mod dictionary;
 pub mod error;
 pub mod filedescriptor;
 pub mod number;
--- a/third_party/rust/core-foundation/src/number.rs
+++ b/third_party/rust/core-foundation/src/number.rs
@@ -20,16 +20,26 @@ declare_TCFType!{
     /// An immutable numeric value.
     CFNumber, CFNumberRef
 }
 impl_TCFType!(CFNumber, CFNumberRef, CFNumberGetTypeID);
 impl_CFTypeDescription!(CFNumber);
 impl_CFComparison!(CFNumber, CFNumberCompare);
 
 impl CFNumber {
+
+    #[inline]
+    pub fn to_i32(&self) -> Option<i32> {
+        unsafe {
+            let mut value: i32 = 0;
+            let ok = CFNumberGetValue(self.0, kCFNumberSInt32Type, mem::transmute(&mut value));
+            if ok { Some(value) } else { None }
+        }
+    }
+
     #[inline]
     pub fn to_i64(&self) -> Option<i64> {
         unsafe {
             let mut value: i64 = 0;
             let ok = CFNumberGetValue(self.0, kCFNumberSInt64Type, mem::transmute(&mut value));
             if ok { Some(value) } else { None }
         }
     }
--- a/third_party/rust/core-foundation/src/string.rs
+++ b/third_party/rust/core-foundation/src/string.rs
@@ -10,16 +10,17 @@
 //! Immutable strings.
 
 pub use core_foundation_sys::string::*;
 
 use base::{CFIndexConvertible, TCFType};
 
 use core_foundation_sys::base::{Boolean, CFIndex, CFRange};
 use core_foundation_sys::base::{kCFAllocatorDefault, kCFAllocatorNull};
+use std::borrow::Cow;
 use std::fmt;
 use std::str::{self, FromStr};
 use std::ptr;
 use std::ffi::CStr;
 
 
 declare_TCFType!{
     /// An immutable string in one of a variety of encodings.
@@ -39,61 +40,67 @@ impl FromStr for CFString {
 
 impl<'a> From<&'a str> for CFString {
     #[inline]
     fn from(string: &'a str) -> CFString {
         CFString::new(string)
     }
 }
 
-impl fmt::Display for CFString {
-    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+impl<'a> From<&'a CFString> for Cow<'a, str> {
+    fn from(cf_str: &'a CFString) -> Cow<'a, str> {
         unsafe {
             // Do this without allocating if we can get away with it
-            let c_string = CFStringGetCStringPtr(self.0, kCFStringEncodingUTF8);
+            let c_string = CFStringGetCStringPtr(cf_str.0, kCFStringEncodingUTF8);
             if c_string != ptr::null() {
                 let c_str = CStr::from_ptr(c_string);
-                fmt.write_str(str::from_utf8_unchecked(c_str.to_bytes()))
+                Cow::Borrowed(str::from_utf8_unchecked(c_str.to_bytes()))
             } else {
-                let char_len = self.char_len();
+                let char_len = cf_str.char_len();
 
                 // First, ask how big the buffer ought to be.
                 let mut bytes_required: CFIndex = 0;
-                CFStringGetBytes(self.0,
+                CFStringGetBytes(cf_str.0,
                                  CFRange { location: 0, length: char_len },
                                  kCFStringEncodingUTF8,
                                  0,
                                  false as Boolean,
                                  ptr::null_mut(),
                                  0,
                                  &mut bytes_required);
 
                 // Then, allocate the buffer and actually copy.
                 let mut buffer = vec![b'\x00'; bytes_required as usize];
 
                 let mut bytes_used: CFIndex = 0;
-                let chars_written = CFStringGetBytes(self.0,
+                let chars_written = CFStringGetBytes(cf_str.0,
                                                      CFRange { location: 0, length: char_len },
                                                      kCFStringEncodingUTF8,
                                                      0,
                                                      false as Boolean,
                                                      buffer.as_mut_ptr(),
                                                      buffer.len().to_CFIndex(),
-                                                     &mut bytes_used) as usize;
-                assert!(chars_written.to_CFIndex() == char_len);
+                                                     &mut bytes_used);
+                assert!(chars_written == char_len);
 
                 // This is dangerous; we over-allocate and null-terminate the string (during
                 // initialization).
                 assert!(bytes_used == buffer.len().to_CFIndex());
-                fmt.write_str(str::from_utf8_unchecked(&buffer))
+                Cow::Owned(String::from_utf8_unchecked(buffer))
             }
         }
     }
 }
 
+impl fmt::Display for CFString {
+    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+        fmt.write_str(&Cow::from(self))
+    }
+}
+
 impl fmt::Debug for CFString {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         write!(f, "\"{}\"", self)
     }
 }
 
 
 impl CFString {